diff --git a/.hgtags b/.hgtags
index 9daf994a27..ccdaf294b4 100644
--- a/.hgtags
+++ b/.hgtags
@@ -10,3 +10,2991 @@
32a0b05096cb83083f5e66d008030a8b1cacfc81 purchase_secondary_unit-5.8.0
0000000000000000000000000000000000000000 6.0.0
33f97eb44c2ea967e49411860d2c05c088ab15e0 purchase_secondary_unit-6.0.0
+6b4b291f70b6ad9ead4cbe9f8c2da88b5c324c8b 2.4.0
+1ee11d51aa0b6c2ecc06cb00ef9ef941d10fb3e7 2.6.0
+cd43d73b08c73a75fecae0b59e5da96a89d68498 2.8.0
+8ec1c5e5086391eef8c93b129311f19a52072f4d 3.0.0
+2dbc358ddf12b5b77705805bc72e17fe38f01a19 3.2.0
+63b3d63e95e64905bccc9dcf0e4e685dac81dfd3 3.4.0
+59d25a92cc7e19b50f6a11181bcf02b78dc4c09a 3.6.0
+bbdb8fc7bf4aea317d452b38798f2d7d915e5a75 3.8.0
+ad55847e968de20322cc71d504e48f769aa22baf 4.0.0
+173cf80a9a9df5f685c12d2acfa0faddacc94222 4.2.0
+07a2480b0e2834e758862e8230d8e93d28a57223 4.4.0
+b0428a99c8532d7a580ef686b853880b27beda3d 4.6.0
+209bd2b3806e73a9e10756f258a0a482fe55e009 4.8.0
+1f4d598b3d9c2afcff4aa60fb22a76d54e989bf3 5.0.0
+ed23e3603ff4c74033f22413278cd40e7c35240d 5.2.0
+de17813d9dd55d8be1a8258f5bc654d19e1bc26a 5.4.0
+cf45aa4d44a7f7e01557a040983d8308b1fcbd8a 5.6.0
+0cf9649d3f25d140770921c544853a07c84bec89 5.8.0
+38078366523c7a71bd738efda43047503d81c7a6 6.0.0
+0000000000000000000000000000000000000000 2.4.0
+6b4b291f70b6ad9ead4cbe9f8c2da88b5c324c8b purchase_shipment_cost-2.4.0
+0000000000000000000000000000000000000000 2.6.0
+1ee11d51aa0b6c2ecc06cb00ef9ef941d10fb3e7 purchase_shipment_cost-2.6.0
+0000000000000000000000000000000000000000 2.8.0
+cd43d73b08c73a75fecae0b59e5da96a89d68498 purchase_shipment_cost-2.8.0
+0000000000000000000000000000000000000000 3.0.0
+8ec1c5e5086391eef8c93b129311f19a52072f4d purchase_shipment_cost-3.0.0
+0000000000000000000000000000000000000000 3.2.0
+2dbc358ddf12b5b77705805bc72e17fe38f01a19 purchase_shipment_cost-3.2.0
+0000000000000000000000000000000000000000 3.4.0
+63b3d63e95e64905bccc9dcf0e4e685dac81dfd3 purchase_shipment_cost-3.4.0
+0000000000000000000000000000000000000000 3.6.0
+59d25a92cc7e19b50f6a11181bcf02b78dc4c09a purchase_shipment_cost-3.6.0
+0000000000000000000000000000000000000000 3.8.0
+bbdb8fc7bf4aea317d452b38798f2d7d915e5a75 purchase_shipment_cost-3.8.0
+0000000000000000000000000000000000000000 4.0.0
+ad55847e968de20322cc71d504e48f769aa22baf purchase_shipment_cost-4.0.0
+0000000000000000000000000000000000000000 4.2.0
+173cf80a9a9df5f685c12d2acfa0faddacc94222 purchase_shipment_cost-4.2.0
+0000000000000000000000000000000000000000 4.4.0
+07a2480b0e2834e758862e8230d8e93d28a57223 purchase_shipment_cost-4.4.0
+0000000000000000000000000000000000000000 4.6.0
+b0428a99c8532d7a580ef686b853880b27beda3d purchase_shipment_cost-4.6.0
+0000000000000000000000000000000000000000 4.8.0
+209bd2b3806e73a9e10756f258a0a482fe55e009 purchase_shipment_cost-4.8.0
+0000000000000000000000000000000000000000 5.0.0
+1f4d598b3d9c2afcff4aa60fb22a76d54e989bf3 purchase_shipment_cost-5.0.0
+0000000000000000000000000000000000000000 5.2.0
+ed23e3603ff4c74033f22413278cd40e7c35240d purchase_shipment_cost-5.2.0
+0000000000000000000000000000000000000000 5.4.0
+de17813d9dd55d8be1a8258f5bc654d19e1bc26a purchase_shipment_cost-5.4.0
+0000000000000000000000000000000000000000 5.6.0
+cf45aa4d44a7f7e01557a040983d8308b1fcbd8a purchase_shipment_cost-5.6.0
+0000000000000000000000000000000000000000 5.8.0
+0cf9649d3f25d140770921c544853a07c84bec89 purchase_shipment_cost-5.8.0
+0000000000000000000000000000000000000000 6.0.0
+38078366523c7a71bd738efda43047503d81c7a6 purchase_shipment_cost-6.0.0
+ffef8bae0da2388021948bcabbf6d6132df1d10d 4.4.0
+53aedf3c5a2907c144e5a4ddac42286e4a5b4e91 4.6.0
+5f91c5b9dbcf3d847e6acfc5ab73ea28e413d5b8 4.8.0
+bd304a295c3400cdd1d3ab88057cf52e3636d8b1 5.0.0
+7e8b2014f3b70fbb4d53bce379e9fffa7493fb4f 5.2.0
+088527a43d2fd9eed9e607d39bd79ae0083950a9 5.4.0
+3ac2fd3f244745e7e8ef98c9dbef84a883eedcc6 5.6.0
+66b2d8e545d2d1ec95b982d0ae82ac05e2f107d7 5.8.0
+ed3a20a42ba3e8d04ddd3c09d221227332e93f17 6.0.0
+45f4ad544e91fb6a8c1c9f7ee90228fc01858775 6.0.1
+0000000000000000000000000000000000000000 4.4.0
+ffef8bae0da2388021948bcabbf6d6132df1d10d sale_advance_payment-4.4.0
+0000000000000000000000000000000000000000 4.6.0
+53aedf3c5a2907c144e5a4ddac42286e4a5b4e91 sale_advance_payment-4.6.0
+0000000000000000000000000000000000000000 4.8.0
+5f91c5b9dbcf3d847e6acfc5ab73ea28e413d5b8 sale_advance_payment-4.8.0
+0000000000000000000000000000000000000000 5.0.0
+bd304a295c3400cdd1d3ab88057cf52e3636d8b1 sale_advance_payment-5.0.0
+0000000000000000000000000000000000000000 5.2.0
+7e8b2014f3b70fbb4d53bce379e9fffa7493fb4f sale_advance_payment-5.2.0
+0000000000000000000000000000000000000000 5.4.0
+088527a43d2fd9eed9e607d39bd79ae0083950a9 sale_advance_payment-5.4.0
+0000000000000000000000000000000000000000 5.6.0
+3ac2fd3f244745e7e8ef98c9dbef84a883eedcc6 sale_advance_payment-5.6.0
+0000000000000000000000000000000000000000 5.8.0
+66b2d8e545d2d1ec95b982d0ae82ac05e2f107d7 sale_advance_payment-5.8.0
+0000000000000000000000000000000000000000 6.0.0
+ed3a20a42ba3e8d04ddd3c09d221227332e93f17 sale_advance_payment-6.0.0
+0000000000000000000000000000000000000000 6.0.1
+45f4ad544e91fb6a8c1c9f7ee90228fc01858775 sale_advance_payment-6.0.1
+2bc978e32824fac17d3c2665444c2bc738ae33ce 5.4.0
+16165133e8fb931f1a8d8dbb8f003c5c1c183132 5.6.0
+3d55751ec3e0150575541c445c0d60846f098336 5.8.0
+a60f0bcd2fa08bb785bf8090b58e4b023c5b97d3 6.0.0
+ec8c8833939e98e33f6a9687472158ab185b977e 6.0.1
+0000000000000000000000000000000000000000 5.4.0
+2bc978e32824fac17d3c2665444c2bc738ae33ce sale_amendment-5.4.0
+0000000000000000000000000000000000000000 5.6.0
+16165133e8fb931f1a8d8dbb8f003c5c1c183132 sale_amendment-5.6.0
+0000000000000000000000000000000000000000 5.8.0
+3d55751ec3e0150575541c445c0d60846f098336 sale_amendment-5.8.0
+0000000000000000000000000000000000000000 6.0.0
+a60f0bcd2fa08bb785bf8090b58e4b023c5b97d3 sale_amendment-6.0.0
+0000000000000000000000000000000000000000 6.0.1
+ec8c8833939e98e33f6a9687472158ab185b977e sale_amendment-6.0.1
+5e6544b5721589986fb34fb9d8189b96113a1812 3.8.0
+1452882cb48099b2b8774488952ef0da93549fba 4.0.0
+852c30b3f34953898bc8cd4ea2ebdb332ff3e733 4.2.0
+9cbc898a393f97b61f6d4716a1fb5433206238bd 4.4.0
+b437d3f8a855595bd87630a7118b0286f5ab1c85 4.6.0
+55166280b2e699bc8b8f0e99be726c4869743857 4.8.0
+266f997e91440b9bc36ae8a435d60c5679ea12fa 5.0.0
+a4923a52b963bce948b479ca426392efd0701d08 5.2.0
+2c543ccd3232d58d1b2d59fa757a7975c72f2372 5.4.0
+da18123e3fd5dccc41fb6f0385078c73d2f133ac 5.6.0
+2c985bccb02403f187f09b68c6869aa6daf8717a 5.8.0
+0d35637e6b73934bbc6edd6accabb7bf1841e77c 6.0.0
+6df66d282bd56fe55b0b53040c91bee1914c9148 6.0.1
+c366c311d9fb66015a70296ee23e17e5e2293616 6.0.2
+0000000000000000000000000000000000000000 3.8.0
+5e6544b5721589986fb34fb9d8189b96113a1812 sale_complaint-3.8.0
+0000000000000000000000000000000000000000 4.0.0
+1452882cb48099b2b8774488952ef0da93549fba sale_complaint-4.0.0
+0000000000000000000000000000000000000000 4.2.0
+852c30b3f34953898bc8cd4ea2ebdb332ff3e733 sale_complaint-4.2.0
+0000000000000000000000000000000000000000 4.4.0
+9cbc898a393f97b61f6d4716a1fb5433206238bd sale_complaint-4.4.0
+0000000000000000000000000000000000000000 4.6.0
+b437d3f8a855595bd87630a7118b0286f5ab1c85 sale_complaint-4.6.0
+0000000000000000000000000000000000000000 4.8.0
+55166280b2e699bc8b8f0e99be726c4869743857 sale_complaint-4.8.0
+0000000000000000000000000000000000000000 5.0.0
+266f997e91440b9bc36ae8a435d60c5679ea12fa sale_complaint-5.0.0
+0000000000000000000000000000000000000000 5.2.0
+a4923a52b963bce948b479ca426392efd0701d08 sale_complaint-5.2.0
+0000000000000000000000000000000000000000 5.4.0
+2c543ccd3232d58d1b2d59fa757a7975c72f2372 sale_complaint-5.4.0
+0000000000000000000000000000000000000000 5.6.0
+da18123e3fd5dccc41fb6f0385078c73d2f133ac sale_complaint-5.6.0
+0000000000000000000000000000000000000000 5.8.0
+2c985bccb02403f187f09b68c6869aa6daf8717a sale_complaint-5.8.0
+0000000000000000000000000000000000000000 6.0.0
+0d35637e6b73934bbc6edd6accabb7bf1841e77c sale_complaint-6.0.0
+0000000000000000000000000000000000000000 6.0.1
+6df66d282bd56fe55b0b53040c91bee1914c9148 sale_complaint-6.0.1
+0000000000000000000000000000000000000000 6.0.2
+c366c311d9fb66015a70296ee23e17e5e2293616 sale_complaint-6.0.2
+9f3593c47d8e61701a48dd4994c87c8932cd03b4 3.2.0
+de61c4b9fa8b5d491a76de99866c9e6f6b7f18da 3.4.0
+53ed2c17b8fab91c131e4845130f5c643b610c4e 3.6.0
+9b0631e3b18e191780b3406becced025d9a6997c 3.8.0
+441f649129f3a3797f27d820c767acf1a2389a3a 4.0.0
+11f83d0ee53b6a3a453bf7c6d9d049dc86b958cd 4.2.0
+9ba1ef5999e04e46bb639917dde537d9f285312a 4.4.0
+d472c520bc15b3b3b2b36b1df50c9e38038d0c94 4.6.0
+5b7b57e25d0b85f530a8ff679209eabfc1e8800d 4.8.0
+912186dd35981e767a934197d0a7eaf2fd043524 5.0.0
+cbfca971ec9fd828f80888abf9fb86d43e159428 5.2.0
+e42f713281f747681fe9c20c822a276f5f9b729c 5.4.0
+7f3949969dbb1c999d977c261d49fe9945f431dc 5.6.0
+3d735aa32b29b9ba2ccb0e03762cd4f0a2f4a257 5.8.0
+538501607c2f00960a49f89d4249855ef0ce15cb 6.0.0
+0000000000000000000000000000000000000000 3.2.0
+9f3593c47d8e61701a48dd4994c87c8932cd03b4 sale_credit_limit-3.2.0
+0000000000000000000000000000000000000000 3.4.0
+de61c4b9fa8b5d491a76de99866c9e6f6b7f18da sale_credit_limit-3.4.0
+0000000000000000000000000000000000000000 3.6.0
+53ed2c17b8fab91c131e4845130f5c643b610c4e sale_credit_limit-3.6.0
+0000000000000000000000000000000000000000 3.8.0
+9b0631e3b18e191780b3406becced025d9a6997c sale_credit_limit-3.8.0
+0000000000000000000000000000000000000000 4.0.0
+441f649129f3a3797f27d820c767acf1a2389a3a sale_credit_limit-4.0.0
+0000000000000000000000000000000000000000 4.2.0
+11f83d0ee53b6a3a453bf7c6d9d049dc86b958cd sale_credit_limit-4.2.0
+0000000000000000000000000000000000000000 4.4.0
+9ba1ef5999e04e46bb639917dde537d9f285312a sale_credit_limit-4.4.0
+0000000000000000000000000000000000000000 4.6.0
+d472c520bc15b3b3b2b36b1df50c9e38038d0c94 sale_credit_limit-4.6.0
+0000000000000000000000000000000000000000 4.8.0
+5b7b57e25d0b85f530a8ff679209eabfc1e8800d sale_credit_limit-4.8.0
+0000000000000000000000000000000000000000 5.0.0
+912186dd35981e767a934197d0a7eaf2fd043524 sale_credit_limit-5.0.0
+0000000000000000000000000000000000000000 5.2.0
+cbfca971ec9fd828f80888abf9fb86d43e159428 sale_credit_limit-5.2.0
+0000000000000000000000000000000000000000 5.4.0
+e42f713281f747681fe9c20c822a276f5f9b729c sale_credit_limit-5.4.0
+0000000000000000000000000000000000000000 5.6.0
+7f3949969dbb1c999d977c261d49fe9945f431dc sale_credit_limit-5.6.0
+0000000000000000000000000000000000000000 5.8.0
+3d735aa32b29b9ba2ccb0e03762cd4f0a2f4a257 sale_credit_limit-5.8.0
+0000000000000000000000000000000000000000 6.0.0
+538501607c2f00960a49f89d4249855ef0ce15cb sale_credit_limit-6.0.0
+048f3939e4fe68df605f29805d421f0e4029e1e3 5.8.0
+e11442b5963bc719317414861dd81c13c7b941ce 6.0.0
+58afdb843fb2ec14c732a56181967e539738855f 6.0.1
+0000000000000000000000000000000000000000 5.8.0
+048f3939e4fe68df605f29805d421f0e4029e1e3 sale_discount-5.8.0
+0000000000000000000000000000000000000000 6.0.0
+e11442b5963bc719317414861dd81c13c7b941ce sale_discount-6.0.0
+0000000000000000000000000000000000000000 6.0.1
+58afdb843fb2ec14c732a56181967e539738855f sale_discount-6.0.1
+ed754e9dc954f77a62e5c13cce8982150df6c5fc 3.6.0
+1a28a341c3b19e92faec157cd3f1daef3882c9d0 3.8.0
+caee5c8f0b7246b0f14e2cd0772959ac13a9f2c8 4.0.0
+58dea19b24d01c729c9f35a7c3e6b95a65afffa7 4.2.0
+d3edd73f98f75ae80f1ba1058c7a0a7c0c1485df 4.4.0
+e1f0b6a705e5e87c5707d737b2a271177ab42ca0 4.6.0
+b07c3f104931d10aa1d015e7d712b2c6519b54bc 4.8.0
+e7516800e812afa2065d1e08e86021dcf0cc5bdb 5.0.0
+126cdf7207c7dc8e7cc0fb00b49dec3c2326031c 5.2.0
+3f4e25ec446eb2b04cb941890120df86d5d629b6 5.4.0
+7a7bfdc619295e1e225b1ea8f6b07dfb8769d4ec 5.6.0
+f3e01b105d1983d8835916e46748a28f492a5aec 5.8.0
+46c0de980742bcd165e258d654df7a2b1d164f8f 6.0.0
+0000000000000000000000000000000000000000 3.6.0
+ed754e9dc954f77a62e5c13cce8982150df6c5fc sale_extra-3.6.0
+0000000000000000000000000000000000000000 3.8.0
+1a28a341c3b19e92faec157cd3f1daef3882c9d0 sale_extra-3.8.0
+0000000000000000000000000000000000000000 4.0.0
+caee5c8f0b7246b0f14e2cd0772959ac13a9f2c8 sale_extra-4.0.0
+0000000000000000000000000000000000000000 4.2.0
+58dea19b24d01c729c9f35a7c3e6b95a65afffa7 sale_extra-4.2.0
+0000000000000000000000000000000000000000 4.4.0
+d3edd73f98f75ae80f1ba1058c7a0a7c0c1485df sale_extra-4.4.0
+0000000000000000000000000000000000000000 4.6.0
+e1f0b6a705e5e87c5707d737b2a271177ab42ca0 sale_extra-4.6.0
+0000000000000000000000000000000000000000 4.8.0
+b07c3f104931d10aa1d015e7d712b2c6519b54bc sale_extra-4.8.0
+0000000000000000000000000000000000000000 5.0.0
+e7516800e812afa2065d1e08e86021dcf0cc5bdb sale_extra-5.0.0
+0000000000000000000000000000000000000000 5.2.0
+126cdf7207c7dc8e7cc0fb00b49dec3c2326031c sale_extra-5.2.0
+0000000000000000000000000000000000000000 5.4.0
+3f4e25ec446eb2b04cb941890120df86d5d629b6 sale_extra-5.4.0
+0000000000000000000000000000000000000000 5.6.0
+7a7bfdc619295e1e225b1ea8f6b07dfb8769d4ec sale_extra-5.6.0
+0000000000000000000000000000000000000000 5.8.0
+f3e01b105d1983d8835916e46748a28f492a5aec sale_extra-5.8.0
+0000000000000000000000000000000000000000 6.0.0
+46c0de980742bcd165e258d654df7a2b1d164f8f sale_extra-6.0.0
+f7260dcf0ebb5739b6b66482ba4bc09b0d4f3e1d 6.0.0
+0379892ea1576bd17c67dae247b16acf688d88a9 6.0.1
+5c1d0d625a8f719800dfe3c6f5fca3e026c06cb6 6.0.2
+526e26430819ade46d6d7745aec20a7fdc395db7 6.0.3
+df89d6304a01a3a379e7f7cc869ae8b6c1c09b0d 6.0.4
+0000000000000000000000000000000000000000 6.0.0
+f7260dcf0ebb5739b6b66482ba4bc09b0d4f3e1d sale_gift_card-6.0.0
+0000000000000000000000000000000000000000 6.0.1
+0379892ea1576bd17c67dae247b16acf688d88a9 sale_gift_card-6.0.1
+0000000000000000000000000000000000000000 6.0.2
+5c1d0d625a8f719800dfe3c6f5fca3e026c06cb6 sale_gift_card-6.0.2
+0000000000000000000000000000000000000000 6.0.3
+526e26430819ade46d6d7745aec20a7fdc395db7 sale_gift_card-6.0.3
+0000000000000000000000000000000000000000 6.0.4
+df89d6304a01a3a379e7f7cc869ae8b6c1c09b0d sale_gift_card-6.0.4
+a10cbe150870d184b9a520b155de9cbc87ecc2f2 1.0.0
+cad9154b8847193dff951b9c4c0a4fa16c66d550 1.2.0
+107d9341d8067b074c60250a15e6cede4f038f7e 1.4.0
+dd5101ebaec9f7d1d13071e0e1ffcf3958a6b0f1 1.6.0
+13263ec7282b5a58dedd84cceb8e33de76a6952e 1.8.0
+4a6f7eb2afa6f6aa315fac3148397a01b0d6ed8e 2.0.0
+746ade947a1b66841722d5bfb4e50a3f87c18c9f 2.2.0
+5cc785354c99154c3656c94aa399a9e1d708db9f 2.4.0
+585d14523722fad71a1d6494123bc763db7ea851 2.6.0
+4b450ba768ec05bd3a46e28d0bdd8f49260f810b 2.8.0
+98c4a6bc6e9e9e26f4cbad60d055b22fa074e0fe 3.0.0
+626631267226df32a752f731624daacafa18e493 3.2.0
+2a184031033ef6cd2bb53f5d754cde0a57a3014a 3.4.0
+57e860bd74aa8d46a8092b643d24b64e5fea6a51 3.6.0
+8dd80d3a8f35cb56e1013d29a4ab2509ac4ee769 3.8.0
+fb552d3041962f3ffd92cd4c2b9822351b546079 4.0.0
+43663308f7adff661eb9c1c7336c9a063d38f945 4.2.0
+7fee0182f57fcf1ec8d7aaef5af2657d9a57ffc3 4.4.0
+e6b09f17a450ee17476bfdffd6610ad424991216 4.6.0
+1a675500baf9f714881ea69f0c045b486f834d1b 4.8.0
+5a31d0c21fa4aefeeb28784a1e7b181d4a71d6d2 5.0.0
+270f93e1f0f67b4d538d6e4931882b616e191707 5.2.0
+0ecdabf1630d793489597e59f3bc4760da48817f 5.4.0
+fc05c15856a5018d7ad0bdb0f34e80dfd56e7b3a 5.6.0
+8bef621cc3cda3d6bdaf1cd4b85fa43e9dacfd51 5.8.0
+1f5bf85b97b4457c460270884d1c0cd839008e59 6.0.0
+0d832b5962c0410c7a26b5e6d18127f89d6fa538 6.0.1
+afcd8bc6a21e7e1b4396e2e7acea123ccaada167 6.0.2
+cff569537d36a9e137a8ce5606db12096a4ac1a1 6.0.3
+03ad81c9b703f727474552d6c377568a95ddd534 6.0.4
+90fe3a8e962d793ad6ab5d6747ca67021a76f90f 6.0.5
+524e1570accd177a27cbde1a53301738f04efabe 6.0.6
+73036e90680d214c3865a4a39575ff7f1e842fe2 6.0.7
+99047c4da39bb9519f91e6fb36ccb90557107ff1 6.0.8
+cdc3e1a724d07f578eef65768c65028b7880f7bd 6.0.9
+0000000000000000000000000000000000000000 1.0.0
+a10cbe150870d184b9a520b155de9cbc87ecc2f2 sale-1.0.0
+0000000000000000000000000000000000000000 1.2.0
+cad9154b8847193dff951b9c4c0a4fa16c66d550 sale-1.2.0
+0000000000000000000000000000000000000000 1.4.0
+107d9341d8067b074c60250a15e6cede4f038f7e sale-1.4.0
+0000000000000000000000000000000000000000 1.6.0
+dd5101ebaec9f7d1d13071e0e1ffcf3958a6b0f1 sale-1.6.0
+0000000000000000000000000000000000000000 1.8.0
+13263ec7282b5a58dedd84cceb8e33de76a6952e sale-1.8.0
+0000000000000000000000000000000000000000 2.0.0
+4a6f7eb2afa6f6aa315fac3148397a01b0d6ed8e sale-2.0.0
+0000000000000000000000000000000000000000 2.2.0
+746ade947a1b66841722d5bfb4e50a3f87c18c9f sale-2.2.0
+0000000000000000000000000000000000000000 2.4.0
+5cc785354c99154c3656c94aa399a9e1d708db9f sale-2.4.0
+0000000000000000000000000000000000000000 2.6.0
+585d14523722fad71a1d6494123bc763db7ea851 sale-2.6.0
+0000000000000000000000000000000000000000 2.8.0
+4b450ba768ec05bd3a46e28d0bdd8f49260f810b sale-2.8.0
+0000000000000000000000000000000000000000 3.0.0
+98c4a6bc6e9e9e26f4cbad60d055b22fa074e0fe sale-3.0.0
+0000000000000000000000000000000000000000 3.2.0
+626631267226df32a752f731624daacafa18e493 sale-3.2.0
+0000000000000000000000000000000000000000 3.4.0
+2a184031033ef6cd2bb53f5d754cde0a57a3014a sale-3.4.0
+0000000000000000000000000000000000000000 3.6.0
+57e860bd74aa8d46a8092b643d24b64e5fea6a51 sale-3.6.0
+0000000000000000000000000000000000000000 3.8.0
+8dd80d3a8f35cb56e1013d29a4ab2509ac4ee769 sale-3.8.0
+0000000000000000000000000000000000000000 4.0.0
+fb552d3041962f3ffd92cd4c2b9822351b546079 sale-4.0.0
+0000000000000000000000000000000000000000 4.2.0
+43663308f7adff661eb9c1c7336c9a063d38f945 sale-4.2.0
+0000000000000000000000000000000000000000 4.4.0
+7fee0182f57fcf1ec8d7aaef5af2657d9a57ffc3 sale-4.4.0
+0000000000000000000000000000000000000000 4.6.0
+e6b09f17a450ee17476bfdffd6610ad424991216 sale-4.6.0
+0000000000000000000000000000000000000000 4.8.0
+1a675500baf9f714881ea69f0c045b486f834d1b sale-4.8.0
+0000000000000000000000000000000000000000 5.0.0
+5a31d0c21fa4aefeeb28784a1e7b181d4a71d6d2 sale-5.0.0
+0000000000000000000000000000000000000000 5.2.0
+270f93e1f0f67b4d538d6e4931882b616e191707 sale-5.2.0
+0000000000000000000000000000000000000000 5.4.0
+0ecdabf1630d793489597e59f3bc4760da48817f sale-5.4.0
+0000000000000000000000000000000000000000 5.6.0
+fc05c15856a5018d7ad0bdb0f34e80dfd56e7b3a sale-5.6.0
+0000000000000000000000000000000000000000 5.8.0
+8bef621cc3cda3d6bdaf1cd4b85fa43e9dacfd51 sale-5.8.0
+0000000000000000000000000000000000000000 6.0.0
+1f5bf85b97b4457c460270884d1c0cd839008e59 sale-6.0.0
+0000000000000000000000000000000000000000 6.0.1
+0d832b5962c0410c7a26b5e6d18127f89d6fa538 sale-6.0.1
+0000000000000000000000000000000000000000 6.0.2
+afcd8bc6a21e7e1b4396e2e7acea123ccaada167 sale-6.0.2
+0000000000000000000000000000000000000000 6.0.3
+cff569537d36a9e137a8ce5606db12096a4ac1a1 sale-6.0.3
+0000000000000000000000000000000000000000 6.0.4
+03ad81c9b703f727474552d6c377568a95ddd534 sale-6.0.4
+0000000000000000000000000000000000000000 6.0.5
+90fe3a8e962d793ad6ab5d6747ca67021a76f90f sale-6.0.5
+0000000000000000000000000000000000000000 6.0.6
+524e1570accd177a27cbde1a53301738f04efabe sale-6.0.6
+0000000000000000000000000000000000000000 6.0.7
+73036e90680d214c3865a4a39575ff7f1e842fe2 sale-6.0.7
+0000000000000000000000000000000000000000 6.0.8
+99047c4da39bb9519f91e6fb36ccb90557107ff1 sale-6.0.8
+0000000000000000000000000000000000000000 6.0.9
+cdc3e1a724d07f578eef65768c65028b7880f7bd sale-6.0.9
+183c2adb200e9ebb4d04e37d16843a86842e5fc4 5.4.0
+818c4a409fd405f8e29257235d3f33c228f98528 5.6.0
+037afc127047ce9a8558cb7f3c5778b8ff84eb60 5.8.0
+18ef01aa2e6feb211bbfc1a53449e227f369ffee 6.0.0
+0000000000000000000000000000000000000000 5.4.0
+183c2adb200e9ebb4d04e37d16843a86842e5fc4 sale_history-5.4.0
+0000000000000000000000000000000000000000 5.6.0
+818c4a409fd405f8e29257235d3f33c228f98528 sale_history-5.6.0
+0000000000000000000000000000000000000000 5.8.0
+037afc127047ce9a8558cb7f3c5778b8ff84eb60 sale_history-5.8.0
+0000000000000000000000000000000000000000 6.0.0
+18ef01aa2e6feb211bbfc1a53449e227f369ffee sale_history-6.0.0
+02193968928ea7a8040f51efb7cbf71a63f6716c 3.0.0
+a3e8ad8e20b1bf89588a287ed33ab8e787934e1f 3.2.0
+a194a1b7c60769f1d3dc847006440be35609ee09 3.4.0
+1e1ada5c238f9e03c696877a237fe2e5eb51a804 3.6.0
+c92b890fd994b9fec5745a294018fa263dfcc444 3.8.0
+eb3a77d0925df79a1ac2e7bea95f38a5cb9703e4 4.0.0
+115f9e97cb33ca748fb1d51275127c272458b56e 4.2.0
+f3a9b35ed2a519b4a9a423459e00ba9dc93ab6be 4.4.0
+59bcb84c02d49c4600e211fd78a875d22034a929 4.6.0
+64ec2452692d45978f759a391b44ab56514559b6 4.8.0
+f61d4e4dc1cb442e84f322be136cf3609cd74991 5.0.0
+ecde908cdd3d027dc6cfad5bfc68538dad162b30 5.2.0
+b564fcd0dcd00071678e81767914bffe6e855d9b 5.4.0
+a15f7ba308fcb2ff1133491c843a079bf9c976f3 5.6.0
+b2b863a78064e4324237d10f17ed3001703c7c13 5.8.0
+d660bd5979030f91ff945fb68a1402e85a57e006 6.0.0
+0000000000000000000000000000000000000000 3.0.0
+02193968928ea7a8040f51efb7cbf71a63f6716c sale_invoice_grouping-3.0.0
+0000000000000000000000000000000000000000 3.2.0
+a3e8ad8e20b1bf89588a287ed33ab8e787934e1f sale_invoice_grouping-3.2.0
+0000000000000000000000000000000000000000 3.4.0
+a194a1b7c60769f1d3dc847006440be35609ee09 sale_invoice_grouping-3.4.0
+0000000000000000000000000000000000000000 3.6.0
+1e1ada5c238f9e03c696877a237fe2e5eb51a804 sale_invoice_grouping-3.6.0
+0000000000000000000000000000000000000000 3.8.0
+c92b890fd994b9fec5745a294018fa263dfcc444 sale_invoice_grouping-3.8.0
+0000000000000000000000000000000000000000 4.0.0
+eb3a77d0925df79a1ac2e7bea95f38a5cb9703e4 sale_invoice_grouping-4.0.0
+0000000000000000000000000000000000000000 4.2.0
+115f9e97cb33ca748fb1d51275127c272458b56e sale_invoice_grouping-4.2.0
+0000000000000000000000000000000000000000 4.4.0
+f3a9b35ed2a519b4a9a423459e00ba9dc93ab6be sale_invoice_grouping-4.4.0
+0000000000000000000000000000000000000000 4.6.0
+59bcb84c02d49c4600e211fd78a875d22034a929 sale_invoice_grouping-4.6.0
+0000000000000000000000000000000000000000 4.8.0
+64ec2452692d45978f759a391b44ab56514559b6 sale_invoice_grouping-4.8.0
+0000000000000000000000000000000000000000 5.0.0
+f61d4e4dc1cb442e84f322be136cf3609cd74991 sale_invoice_grouping-5.0.0
+0000000000000000000000000000000000000000 5.2.0
+ecde908cdd3d027dc6cfad5bfc68538dad162b30 sale_invoice_grouping-5.2.0
+0000000000000000000000000000000000000000 5.4.0
+b564fcd0dcd00071678e81767914bffe6e855d9b sale_invoice_grouping-5.4.0
+0000000000000000000000000000000000000000 5.6.0
+a15f7ba308fcb2ff1133491c843a079bf9c976f3 sale_invoice_grouping-5.6.0
+0000000000000000000000000000000000000000 5.8.0
+b2b863a78064e4324237d10f17ed3001703c7c13 sale_invoice_grouping-5.8.0
+0000000000000000000000000000000000000000 6.0.0
+d660bd5979030f91ff945fb68a1402e85a57e006 sale_invoice_grouping-6.0.0
+8a95588381b35cb27577087832c5ae4da9cd7e3f 1.6.0
+ebc57da9bed5ee9fe72fe058f4df25f1bf64b3d2 1.8.0
+79949ff632053561e2e165741bf0173902de44bf 2.0.0
+ab0f0de52d17ccca323a8b88185d460c168486b8 2.2.0
+b883df5cada60b8fb8885da6a09805ebd82b93ab 2.4.0
+1cf3fa4815060810f3d7da1f011e6b9d104bf2b7 2.6.0
+31409c9f2ef35ddf938d8a75edaa7fb531b2b24b 2.8.0
+78047448b367fbe6f204a0c593f5d6e1791cc097 3.0.0
+fac58ec726e0bb8c4dc9ea5f5d0f0a1fbaf8f94f 3.2.0
+bb0ed6867cabf05d58b5ef98eeb7a364939acdc1 3.4.0
+6ef578dc4f6da372f04cd1c0198a94bfd6f3eb62 3.6.0
+2f848da36791fc48112cd6c7c81a8708f5827431 3.8.0
+fd788ea3774d3eb2aca8480d8076d25513297d69 4.0.0
+e632dd78214b52c0dc93f2471cdd624d9556517b 4.2.0
+0d16cfcf221ed8608565e6e4f5c946b9909d7f14 4.4.0
+11a9ed7c950aee7e9f311ea7d04a4878c06a0257 4.6.0
+f8c109894b1eff1d3b39e8182239553776fab26f 4.8.0
+5888934279521ac12caf69431fa5385380fde816 5.0.0
+1256de2cad83864e82fb1b0bf52c63f7a6338187 5.2.0
+dd0ebdb6c44a90773a827d18e014019f9fb9666d 5.4.0
+fe5bf66c49251e367441e76f708e4c24b4d44d3d 5.6.0
+95169acf1c0a88a30c2fac46e2da054b32e4799f 5.8.0
+13a5b61b9b4583bfe0c9007e410aa5a914955b84 6.0.0
+8f17d0cb6ce9f91620409d1c090e3d8355d24dc4 6.0.1
+0000000000000000000000000000000000000000 1.6.0
+8a95588381b35cb27577087832c5ae4da9cd7e3f sale_opportunity-1.6.0
+0000000000000000000000000000000000000000 1.8.0
+ebc57da9bed5ee9fe72fe058f4df25f1bf64b3d2 sale_opportunity-1.8.0
+0000000000000000000000000000000000000000 2.0.0
+79949ff632053561e2e165741bf0173902de44bf sale_opportunity-2.0.0
+0000000000000000000000000000000000000000 2.2.0
+ab0f0de52d17ccca323a8b88185d460c168486b8 sale_opportunity-2.2.0
+0000000000000000000000000000000000000000 2.4.0
+b883df5cada60b8fb8885da6a09805ebd82b93ab sale_opportunity-2.4.0
+0000000000000000000000000000000000000000 2.6.0
+1cf3fa4815060810f3d7da1f011e6b9d104bf2b7 sale_opportunity-2.6.0
+0000000000000000000000000000000000000000 2.8.0
+31409c9f2ef35ddf938d8a75edaa7fb531b2b24b sale_opportunity-2.8.0
+0000000000000000000000000000000000000000 3.0.0
+78047448b367fbe6f204a0c593f5d6e1791cc097 sale_opportunity-3.0.0
+0000000000000000000000000000000000000000 3.2.0
+fac58ec726e0bb8c4dc9ea5f5d0f0a1fbaf8f94f sale_opportunity-3.2.0
+0000000000000000000000000000000000000000 3.4.0
+bb0ed6867cabf05d58b5ef98eeb7a364939acdc1 sale_opportunity-3.4.0
+0000000000000000000000000000000000000000 3.6.0
+6ef578dc4f6da372f04cd1c0198a94bfd6f3eb62 sale_opportunity-3.6.0
+0000000000000000000000000000000000000000 3.8.0
+2f848da36791fc48112cd6c7c81a8708f5827431 sale_opportunity-3.8.0
+0000000000000000000000000000000000000000 4.0.0
+fd788ea3774d3eb2aca8480d8076d25513297d69 sale_opportunity-4.0.0
+0000000000000000000000000000000000000000 4.2.0
+e632dd78214b52c0dc93f2471cdd624d9556517b sale_opportunity-4.2.0
+0000000000000000000000000000000000000000 4.4.0
+0d16cfcf221ed8608565e6e4f5c946b9909d7f14 sale_opportunity-4.4.0
+0000000000000000000000000000000000000000 4.6.0
+11a9ed7c950aee7e9f311ea7d04a4878c06a0257 sale_opportunity-4.6.0
+0000000000000000000000000000000000000000 4.8.0
+f8c109894b1eff1d3b39e8182239553776fab26f sale_opportunity-4.8.0
+0000000000000000000000000000000000000000 5.0.0
+5888934279521ac12caf69431fa5385380fde816 sale_opportunity-5.0.0
+0000000000000000000000000000000000000000 5.2.0
+1256de2cad83864e82fb1b0bf52c63f7a6338187 sale_opportunity-5.2.0
+0000000000000000000000000000000000000000 5.4.0
+dd0ebdb6c44a90773a827d18e014019f9fb9666d sale_opportunity-5.4.0
+0000000000000000000000000000000000000000 5.6.0
+fe5bf66c49251e367441e76f708e4c24b4d44d3d sale_opportunity-5.6.0
+0000000000000000000000000000000000000000 5.8.0
+95169acf1c0a88a30c2fac46e2da054b32e4799f sale_opportunity-5.8.0
+0000000000000000000000000000000000000000 6.0.0
+13a5b61b9b4583bfe0c9007e410aa5a914955b84 sale_opportunity-6.0.0
+0000000000000000000000000000000000000000 6.0.1
+8f17d0cb6ce9f91620409d1c090e3d8355d24dc4 sale_opportunity-6.0.1
+cf14756390fc8104236ac571a1985ada6dbfbcfb 4.6.0
+92b49453423dbd713b2fe0c4c8acf4a3e2429b05 4.8.0
+cacdd3e5f2f6d79335bc8b2d59c20989104bd700 5.0.0
+5dda623c16d968c13ea93a15736ebc0e40c54997 5.2.0
+bc6b67bbc1c6be7f765ea846a7a9b4705ed7898a 5.4.0
+55badc28caf6c17a1cec03414342862917b50aae 5.6.0
+48510945db7404f4eeb1b3ed097d74f4b0bfa133 5.8.0
+8cf2cd8b23e95b1b20e0ef6e034f87d22e046c30 6.0.0
+0f82434b6bd5a746848c517b56d0b50329dd9032 6.0.1
+6ab687ba33684d9d99ea64d3f6ae66ac0319eb57 6.0.2
+0000000000000000000000000000000000000000 4.6.0
+cf14756390fc8104236ac571a1985ada6dbfbcfb sale_payment-4.6.0
+0000000000000000000000000000000000000000 4.8.0
+92b49453423dbd713b2fe0c4c8acf4a3e2429b05 sale_payment-4.8.0
+0000000000000000000000000000000000000000 5.0.0
+cacdd3e5f2f6d79335bc8b2d59c20989104bd700 sale_payment-5.0.0
+0000000000000000000000000000000000000000 5.2.0
+5dda623c16d968c13ea93a15736ebc0e40c54997 sale_payment-5.2.0
+0000000000000000000000000000000000000000 5.4.0
+bc6b67bbc1c6be7f765ea846a7a9b4705ed7898a sale_payment-5.4.0
+0000000000000000000000000000000000000000 5.6.0
+55badc28caf6c17a1cec03414342862917b50aae sale_payment-5.6.0
+0000000000000000000000000000000000000000 5.8.0
+48510945db7404f4eeb1b3ed097d74f4b0bfa133 sale_payment-5.8.0
+0000000000000000000000000000000000000000 6.0.0
+8cf2cd8b23e95b1b20e0ef6e034f87d22e046c30 sale_payment-6.0.0
+0000000000000000000000000000000000000000 6.0.1
+0f82434b6bd5a746848c517b56d0b50329dd9032 sale_payment-6.0.1
+0000000000000000000000000000000000000000 6.0.2
+6ab687ba33684d9d99ea64d3f6ae66ac0319eb57 sale_payment-6.0.2
+ab27d5f885523aea9a019286456f0d1e5e8004ce 1.4.0
+f9b3c65cec15cb254f0dabd277267713b27ac85e 1.6.0
+fd059eb6efc541f8017126fe01244840d97e9734 1.8.0
+8fba70f4cccaf6eecb33ab96b912896925e0c53c 2.0.0
+72abba3cf573b24c299d8c436ad1ee7ebc7ec019 2.2.0
+2707ce9a73005af39c738bd1ebc802510dea26c6 2.4.0
+77cab32b37ac5edd7633c5180c27a6c714910404 2.6.0
+1e016db1de37328bf2cbfd5e269e3f08fd52aea5 2.8.0
+89e39e7632c711d6b55296cc882dd84269e9c204 3.0.0
+2275c8a82001381ec5b05a110c268cbebcbadf50 3.2.0
+fcccce714c6ea6b301ccfddfcfad3ebd340ba1ab 3.4.0
+da4b0d936e33a548f38c744746fcb09d0a8d8981 3.6.0
+7ab4b6c816aac80c456cccd720f532b0f2683599 3.8.0
+32947c8017123b169ce3016d5ace19b2f3180a5c 4.0.0
+8077ddce6393d8c26c2a827cf26a1c0b800328cf 4.2.0
+655dd1c019ba39803cc86c7ad206d50e637f2cae 4.4.0
+2f8fbabe66588be2c44258cef94188b822d86aa6 4.6.0
+bc8164a5def26df10bfa7f7f6822caf4baa695cf 4.8.0
+38bdc770d89ba2771ed9db9aaa5070a1241e2316 5.0.0
+3e8dba0fb8a97f7f85b4b81c068bb1035ed9f591 5.2.0
+d55fde4995043af44a2db09d2b30fc05aa07e650 5.4.0
+ee4594b79aebab2288a48acc19d437d26660702e 5.6.0
+3dd6b2922b2ce7e7b495a4a9989d51b30f9d20d0 5.8.0
+774b4432599f895c9321db4c1df1c8440e66b05a 6.0.0
+c1f6221592b86abb1c47859ec919af44d302a983 6.0.1
+0000000000000000000000000000000000000000 1.4.0
+ab27d5f885523aea9a019286456f0d1e5e8004ce sale_price_list-1.4.0
+0000000000000000000000000000000000000000 1.6.0
+f9b3c65cec15cb254f0dabd277267713b27ac85e sale_price_list-1.6.0
+0000000000000000000000000000000000000000 1.8.0
+fd059eb6efc541f8017126fe01244840d97e9734 sale_price_list-1.8.0
+0000000000000000000000000000000000000000 2.0.0
+8fba70f4cccaf6eecb33ab96b912896925e0c53c sale_price_list-2.0.0
+0000000000000000000000000000000000000000 2.2.0
+72abba3cf573b24c299d8c436ad1ee7ebc7ec019 sale_price_list-2.2.0
+0000000000000000000000000000000000000000 2.4.0
+2707ce9a73005af39c738bd1ebc802510dea26c6 sale_price_list-2.4.0
+0000000000000000000000000000000000000000 2.6.0
+77cab32b37ac5edd7633c5180c27a6c714910404 sale_price_list-2.6.0
+0000000000000000000000000000000000000000 2.8.0
+1e016db1de37328bf2cbfd5e269e3f08fd52aea5 sale_price_list-2.8.0
+0000000000000000000000000000000000000000 3.0.0
+89e39e7632c711d6b55296cc882dd84269e9c204 sale_price_list-3.0.0
+0000000000000000000000000000000000000000 3.2.0
+2275c8a82001381ec5b05a110c268cbebcbadf50 sale_price_list-3.2.0
+0000000000000000000000000000000000000000 3.4.0
+fcccce714c6ea6b301ccfddfcfad3ebd340ba1ab sale_price_list-3.4.0
+0000000000000000000000000000000000000000 3.6.0
+da4b0d936e33a548f38c744746fcb09d0a8d8981 sale_price_list-3.6.0
+0000000000000000000000000000000000000000 3.8.0
+7ab4b6c816aac80c456cccd720f532b0f2683599 sale_price_list-3.8.0
+0000000000000000000000000000000000000000 4.0.0
+32947c8017123b169ce3016d5ace19b2f3180a5c sale_price_list-4.0.0
+0000000000000000000000000000000000000000 4.2.0
+8077ddce6393d8c26c2a827cf26a1c0b800328cf sale_price_list-4.2.0
+0000000000000000000000000000000000000000 4.4.0
+655dd1c019ba39803cc86c7ad206d50e637f2cae sale_price_list-4.4.0
+0000000000000000000000000000000000000000 4.6.0
+2f8fbabe66588be2c44258cef94188b822d86aa6 sale_price_list-4.6.0
+0000000000000000000000000000000000000000 4.8.0
+bc8164a5def26df10bfa7f7f6822caf4baa695cf sale_price_list-4.8.0
+0000000000000000000000000000000000000000 5.0.0
+38bdc770d89ba2771ed9db9aaa5070a1241e2316 sale_price_list-5.0.0
+0000000000000000000000000000000000000000 5.2.0
+3e8dba0fb8a97f7f85b4b81c068bb1035ed9f591 sale_price_list-5.2.0
+0000000000000000000000000000000000000000 5.4.0
+d55fde4995043af44a2db09d2b30fc05aa07e650 sale_price_list-5.4.0
+0000000000000000000000000000000000000000 5.6.0
+ee4594b79aebab2288a48acc19d437d26660702e sale_price_list-5.6.0
+0000000000000000000000000000000000000000 5.8.0
+3dd6b2922b2ce7e7b495a4a9989d51b30f9d20d0 sale_price_list-5.8.0
+0000000000000000000000000000000000000000 6.0.0
+774b4432599f895c9321db4c1df1c8440e66b05a sale_price_list-6.0.0
+0000000000000000000000000000000000000000 6.0.1
+c1f6221592b86abb1c47859ec919af44d302a983 sale_price_list-6.0.1
+3bc89a03c30827599ba2358137451740c0ed3d32 5.2.0
+8601dafabd0098f2e5df235458ee3d3cd9a7c56d 5.4.0
+e55081ceaa04185643d06774bf80303827e4d53b 5.6.0
+875d7e3c1ea4f922723e9e513171f86d4e47ce06 5.8.0
+8fbeddc61c5fbf7fcd6ea98ca8c918030035c435 6.0.0
+c72b6ac9a0d3d248e0aa710c1f92a6ad64822eff 6.0.1
+2dfbb343ca9515f1cee2f909103a49eb4ba7fcbb 6.0.2
+46fa607228c4eb55edecace49a70e2da9e31dec9 6.0.3
+0000000000000000000000000000000000000000 5.2.0
+3bc89a03c30827599ba2358137451740c0ed3d32 sale_product_customer-5.2.0
+0000000000000000000000000000000000000000 5.4.0
+8601dafabd0098f2e5df235458ee3d3cd9a7c56d sale_product_customer-5.4.0
+0000000000000000000000000000000000000000 5.6.0
+e55081ceaa04185643d06774bf80303827e4d53b sale_product_customer-5.6.0
+0000000000000000000000000000000000000000 5.8.0
+875d7e3c1ea4f922723e9e513171f86d4e47ce06 sale_product_customer-5.8.0
+0000000000000000000000000000000000000000 6.0.0
+8fbeddc61c5fbf7fcd6ea98ca8c918030035c435 sale_product_customer-6.0.0
+0000000000000000000000000000000000000000 6.0.1
+c72b6ac9a0d3d248e0aa710c1f92a6ad64822eff sale_product_customer-6.0.1
+0000000000000000000000000000000000000000 6.0.2
+2dfbb343ca9515f1cee2f909103a49eb4ba7fcbb sale_product_customer-6.0.2
+0000000000000000000000000000000000000000 6.0.3
+46fa607228c4eb55edecace49a70e2da9e31dec9 sale_product_customer-6.0.3
+eb3633ef7e348b175c1de2d74b74ebb8d35ccd7a 4.8.0
+a559a9907346a3ed392d1253d85720553130ee04 5.0.0
+d78fac53046d868f11c8d42f0baff6a0a16497bf 5.2.0
+3c28cf8cc29c42acf80fe349e0e74ebf16b30f3e 5.4.0
+06446e2efbb22a5a2900d58e2c450a4d80d11cbf 5.6.0
+a7c5dedf708211de95b5d6f18be8fe2a40b01477 5.8.0
+b3e615c084feedfd747423c775eb55300824804e 6.0.0
+0000000000000000000000000000000000000000 4.8.0
+eb3633ef7e348b175c1de2d74b74ebb8d35ccd7a sale_promotion_coupon-4.8.0
+0000000000000000000000000000000000000000 5.0.0
+a559a9907346a3ed392d1253d85720553130ee04 sale_promotion_coupon-5.0.0
+0000000000000000000000000000000000000000 5.2.0
+d78fac53046d868f11c8d42f0baff6a0a16497bf sale_promotion_coupon-5.2.0
+0000000000000000000000000000000000000000 5.4.0
+3c28cf8cc29c42acf80fe349e0e74ebf16b30f3e sale_promotion_coupon-5.4.0
+0000000000000000000000000000000000000000 5.6.0
+06446e2efbb22a5a2900d58e2c450a4d80d11cbf sale_promotion_coupon-5.6.0
+0000000000000000000000000000000000000000 5.8.0
+a7c5dedf708211de95b5d6f18be8fe2a40b01477 sale_promotion_coupon-5.8.0
+0000000000000000000000000000000000000000 6.0.0
+b3e615c084feedfd747423c775eb55300824804e sale_promotion_coupon-6.0.0
+9f34c79d46c2d737af28e5989d170dc4c29f8bca 3.8.0
+e9dfc299f0412d0a1d6ab4fa779ce8e1879e0289 4.0.0
+643a8dff3fc66b95106bbe3ea58d3a8bf3f7d702 4.2.0
+932ea4b106c6b82582ae20a257940961bf64c636 4.4.0
+ab0740f8088064fca42753a6cfe2ea6bf7f06826 4.6.0
+79e9c913b4816af96b1eb2366ef0e53b1a76809d 4.8.0
+8cc1caf51ac1a8c6213bb6b60917f6e2754c9d2a 5.0.0
+533b36c56838dcca47711c338612816e2b2f7823 5.2.0
+f6c780c48d4d649ba2cb421fde633ccb38f0e8d1 5.4.0
+fd11abb781d777f1e0e97d7566a541b6adb12321 5.6.0
+3e261884cfc342f9af6527162c804eae3990006a 5.8.0
+201938015dab5f5c3e45f8e38096d6fb7a6a439c 6.0.0
+8e66edc558f665a508a7f2b9897213ce1ca8b212 6.0.1
+a14ed38f936838505a7f3c3310590f5d3ef4c804 6.0.2
+0000000000000000000000000000000000000000 3.8.0
+9f34c79d46c2d737af28e5989d170dc4c29f8bca sale_promotion-3.8.0
+0000000000000000000000000000000000000000 4.0.0
+e9dfc299f0412d0a1d6ab4fa779ce8e1879e0289 sale_promotion-4.0.0
+0000000000000000000000000000000000000000 4.2.0
+643a8dff3fc66b95106bbe3ea58d3a8bf3f7d702 sale_promotion-4.2.0
+0000000000000000000000000000000000000000 4.4.0
+932ea4b106c6b82582ae20a257940961bf64c636 sale_promotion-4.4.0
+0000000000000000000000000000000000000000 4.6.0
+ab0740f8088064fca42753a6cfe2ea6bf7f06826 sale_promotion-4.6.0
+0000000000000000000000000000000000000000 4.8.0
+79e9c913b4816af96b1eb2366ef0e53b1a76809d sale_promotion-4.8.0
+0000000000000000000000000000000000000000 5.0.0
+8cc1caf51ac1a8c6213bb6b60917f6e2754c9d2a sale_promotion-5.0.0
+0000000000000000000000000000000000000000 5.2.0
+533b36c56838dcca47711c338612816e2b2f7823 sale_promotion-5.2.0
+0000000000000000000000000000000000000000 5.4.0
+f6c780c48d4d649ba2cb421fde633ccb38f0e8d1 sale_promotion-5.4.0
+0000000000000000000000000000000000000000 5.6.0
+fd11abb781d777f1e0e97d7566a541b6adb12321 sale_promotion-5.6.0
+0000000000000000000000000000000000000000 5.8.0
+3e261884cfc342f9af6527162c804eae3990006a sale_promotion-5.8.0
+0000000000000000000000000000000000000000 6.0.0
+201938015dab5f5c3e45f8e38096d6fb7a6a439c sale_promotion-6.0.0
+0000000000000000000000000000000000000000 6.0.1
+8e66edc558f665a508a7f2b9897213ce1ca8b212 sale_promotion-6.0.1
+0000000000000000000000000000000000000000 6.0.2
+a14ed38f936838505a7f3c3310590f5d3ef4c804 sale_promotion-6.0.2
+2a228469da4bed16d7d4c457abbc807cc573c265 5.4.0
+56454423ca2d4e487200814673f5ecd8fc980efd 5.6.0
+d805b804f29e407ea4b0f69efcafe6a61865362c 5.8.0
+31c032243180722071056f4e2e2a1d4ae4df953f 6.0.0
+0000000000000000000000000000000000000000 5.4.0
+2a228469da4bed16d7d4c457abbc807cc573c265 sale_secondary_unit-5.4.0
+0000000000000000000000000000000000000000 5.6.0
+56454423ca2d4e487200814673f5ecd8fc980efd sale_secondary_unit-5.6.0
+0000000000000000000000000000000000000000 5.8.0
+d805b804f29e407ea4b0f69efcafe6a61865362c sale_secondary_unit-5.8.0
+0000000000000000000000000000000000000000 6.0.0
+31c032243180722071056f4e2e2a1d4ae4df953f sale_secondary_unit-6.0.0
+71a276c5d18a81476b1545a4d958cda80c4450ab 2.0.0
+36b22ce15af6266455a7344bdb1b7708658a3918 2.2.0
+8b23387948920fbc4acf986227a563387b1086f5 2.4.0
+f45b4c88b84945e0238c9ae55e5c8cd19deb58a8 2.6.0
+4a59cbca07a505cfab07d3da66a5b269b4506ce7 2.8.0
+fbe62f5dc0f7ba0cf659be52bd4e89a14f3af072 3.0.0
+cc69cb0d3fa633a4e40e5deff44a1dc1de6d3d7d 3.2.0
+88f6c7e4d90d1f1a06d13678b864065a62c3dbc6 3.4.0
+c90dd0c24002a8411ec0835bc1f5529b17346a58 3.6.0
+e7ccf8e2b8de17273886b3b3c12fdcedd41310ae 3.8.0
+b60a07baabd40970d72e6f475d129246a2949bf2 4.0.0
+f779a1568b6448e577353c9b5264e9837e0818a9 4.2.0
+b4750cf7a2a1bef268ec448124a8eb94f5c7f3ac 4.4.0
+3c4b4407aedd9dfde45b280f305c95abc1887fa0 4.6.0
+e32589a3bcb51b0afa39c03add8945cd551ef58a 4.8.0
+1f0897f8bf5b6d063011d84250c4d9f2eb54ccbe 5.0.0
+8ae25e38066bc15ac698466d9ed1ff869b5a314a 5.2.0
+00af805dd3e38da7fb98f605bf0122592158c0f6 5.4.0
+724b009489d5ad49fe41028cc9409b60c263b672 5.6.0
+c4d5e46fcf82f58c549f986399f83668dc01e90c 5.8.0
+74a631f9669fcd6d19c994950b9b090d45c96e1f 6.0.0
+1df76bb0fde08ee6c3b456bc7a07348c10f87cdf 6.0.1
+0991e079f758f572450cf07ebcda1c450e6789cf 6.0.2
+aba842b19d04f6534dbc5c000605d90337613448 6.0.3
+caef0e34a8d179924724cd4e9a0c30c365e40679 6.0.4
+0000000000000000000000000000000000000000 2.0.0
+71a276c5d18a81476b1545a4d958cda80c4450ab sale_shipment_cost-2.0.0
+0000000000000000000000000000000000000000 2.2.0
+36b22ce15af6266455a7344bdb1b7708658a3918 sale_shipment_cost-2.2.0
+0000000000000000000000000000000000000000 2.4.0
+8b23387948920fbc4acf986227a563387b1086f5 sale_shipment_cost-2.4.0
+0000000000000000000000000000000000000000 2.6.0
+f45b4c88b84945e0238c9ae55e5c8cd19deb58a8 sale_shipment_cost-2.6.0
+0000000000000000000000000000000000000000 2.8.0
+4a59cbca07a505cfab07d3da66a5b269b4506ce7 sale_shipment_cost-2.8.0
+0000000000000000000000000000000000000000 3.0.0
+fbe62f5dc0f7ba0cf659be52bd4e89a14f3af072 sale_shipment_cost-3.0.0
+0000000000000000000000000000000000000000 3.2.0
+cc69cb0d3fa633a4e40e5deff44a1dc1de6d3d7d sale_shipment_cost-3.2.0
+0000000000000000000000000000000000000000 3.4.0
+88f6c7e4d90d1f1a06d13678b864065a62c3dbc6 sale_shipment_cost-3.4.0
+0000000000000000000000000000000000000000 3.6.0
+c90dd0c24002a8411ec0835bc1f5529b17346a58 sale_shipment_cost-3.6.0
+0000000000000000000000000000000000000000 3.8.0
+e7ccf8e2b8de17273886b3b3c12fdcedd41310ae sale_shipment_cost-3.8.0
+0000000000000000000000000000000000000000 4.0.0
+b60a07baabd40970d72e6f475d129246a2949bf2 sale_shipment_cost-4.0.0
+0000000000000000000000000000000000000000 4.2.0
+f779a1568b6448e577353c9b5264e9837e0818a9 sale_shipment_cost-4.2.0
+0000000000000000000000000000000000000000 4.4.0
+b4750cf7a2a1bef268ec448124a8eb94f5c7f3ac sale_shipment_cost-4.4.0
+0000000000000000000000000000000000000000 4.6.0
+3c4b4407aedd9dfde45b280f305c95abc1887fa0 sale_shipment_cost-4.6.0
+0000000000000000000000000000000000000000 4.8.0
+e32589a3bcb51b0afa39c03add8945cd551ef58a sale_shipment_cost-4.8.0
+0000000000000000000000000000000000000000 5.0.0
+1f0897f8bf5b6d063011d84250c4d9f2eb54ccbe sale_shipment_cost-5.0.0
+0000000000000000000000000000000000000000 5.2.0
+8ae25e38066bc15ac698466d9ed1ff869b5a314a sale_shipment_cost-5.2.0
+0000000000000000000000000000000000000000 5.4.0
+00af805dd3e38da7fb98f605bf0122592158c0f6 sale_shipment_cost-5.4.0
+0000000000000000000000000000000000000000 5.6.0
+724b009489d5ad49fe41028cc9409b60c263b672 sale_shipment_cost-5.6.0
+0000000000000000000000000000000000000000 5.8.0
+c4d5e46fcf82f58c549f986399f83668dc01e90c sale_shipment_cost-5.8.0
+0000000000000000000000000000000000000000 6.0.0
+74a631f9669fcd6d19c994950b9b090d45c96e1f sale_shipment_cost-6.0.0
+0000000000000000000000000000000000000000 6.0.1
+1df76bb0fde08ee6c3b456bc7a07348c10f87cdf sale_shipment_cost-6.0.1
+0000000000000000000000000000000000000000 6.0.2
+0991e079f758f572450cf07ebcda1c450e6789cf sale_shipment_cost-6.0.2
+0000000000000000000000000000000000000000 6.0.3
+aba842b19d04f6534dbc5c000605d90337613448 sale_shipment_cost-6.0.3
+0000000000000000000000000000000000000000 6.0.4
+caef0e34a8d179924724cd4e9a0c30c365e40679 sale_shipment_cost-6.0.4
+4e18bffba1d928a833714369987e61ee691a51e6 3.2.0
+214c0ae0defc5d398a757857953aa3b73e8daaa9 3.4.0
+96118825d91dfa186e344ad464592145bdbdbc03 3.6.0
+234e6dd84adc0e12d1bd4424ac95ea3c53bd8e41 3.8.0
+d753906e57e00e17b3dc46723bc84c51dcac4312 4.0.0
+56504fa2f4fec8ca7e36135be82c93e307e9dde0 4.2.0
+29287b1c5d08d892c5af513ae75a0dda240c0eeb 4.4.0
+3f7db5247270711f88180bdb61676c73a352cfc3 4.6.0
+d2a6c1af0d0aae8c840c4fec727f67ac14d83283 4.8.0
+53c2c7174be144c346358abcf4e5c2e7f280208f 5.0.0
+adad4c039e95428fc3dc357251dbd782264e8a1a 5.2.0
+5ee73bbc4e00d21a6efbeb6d358b3b280aab1744 5.4.0
+70c7edd923532816e22c96397f3201279ef6bd41 5.6.0
+ea9261c209bcd28dafd29205c58f2199596eef50 5.8.0
+5defabd519cf5e50cde2f4779d889abe22f28b75 6.0.0
+0000000000000000000000000000000000000000 3.2.0
+4e18bffba1d928a833714369987e61ee691a51e6 sale_shipment_grouping-3.2.0
+0000000000000000000000000000000000000000 3.4.0
+214c0ae0defc5d398a757857953aa3b73e8daaa9 sale_shipment_grouping-3.4.0
+0000000000000000000000000000000000000000 3.6.0
+96118825d91dfa186e344ad464592145bdbdbc03 sale_shipment_grouping-3.6.0
+0000000000000000000000000000000000000000 3.8.0
+234e6dd84adc0e12d1bd4424ac95ea3c53bd8e41 sale_shipment_grouping-3.8.0
+0000000000000000000000000000000000000000 4.0.0
+d753906e57e00e17b3dc46723bc84c51dcac4312 sale_shipment_grouping-4.0.0
+0000000000000000000000000000000000000000 4.2.0
+56504fa2f4fec8ca7e36135be82c93e307e9dde0 sale_shipment_grouping-4.2.0
+0000000000000000000000000000000000000000 4.4.0
+29287b1c5d08d892c5af513ae75a0dda240c0eeb sale_shipment_grouping-4.4.0
+0000000000000000000000000000000000000000 4.6.0
+3f7db5247270711f88180bdb61676c73a352cfc3 sale_shipment_grouping-4.6.0
+0000000000000000000000000000000000000000 4.8.0
+d2a6c1af0d0aae8c840c4fec727f67ac14d83283 sale_shipment_grouping-4.8.0
+0000000000000000000000000000000000000000 5.0.0
+53c2c7174be144c346358abcf4e5c2e7f280208f sale_shipment_grouping-5.0.0
+0000000000000000000000000000000000000000 5.2.0
+adad4c039e95428fc3dc357251dbd782264e8a1a sale_shipment_grouping-5.2.0
+0000000000000000000000000000000000000000 5.4.0
+5ee73bbc4e00d21a6efbeb6d358b3b280aab1744 sale_shipment_grouping-5.4.0
+0000000000000000000000000000000000000000 5.6.0
+70c7edd923532816e22c96397f3201279ef6bd41 sale_shipment_grouping-5.6.0
+0000000000000000000000000000000000000000 5.8.0
+ea9261c209bcd28dafd29205c58f2199596eef50 sale_shipment_grouping-5.8.0
+0000000000000000000000000000000000000000 6.0.0
+5defabd519cf5e50cde2f4779d889abe22f28b75 sale_shipment_grouping-6.0.0
+85881e061cd7c54322b0f6c2283b6c3ddf552668 4.6.0
+4e2af555b00f240d2902f1c89e269dad16f82250 4.8.0
+d53c9cc0a7aa80ec6fca13e6e7e63da1ef278bbf 5.0.0
+fe7da63d5ea6de75e3fe13109ef8219a69fc2391 5.2.0
+2742ddec3cb1c8334f9d9ecde0a9c6ad5a8ed36c 5.4.0
+1de405190689ab072107b79be6f003938efa1a3b 5.6.0
+6b06320f1b17705be25b353e4b9c11045af31583 5.8.0
+cb41254aec0000127774331aedec41f96a17956b 6.0.0
+0000000000000000000000000000000000000000 4.6.0
+85881e061cd7c54322b0f6c2283b6c3ddf552668 sale_shipment_tolerance-4.6.0
+0000000000000000000000000000000000000000 4.8.0
+4e2af555b00f240d2902f1c89e269dad16f82250 sale_shipment_tolerance-4.8.0
+0000000000000000000000000000000000000000 5.0.0
+d53c9cc0a7aa80ec6fca13e6e7e63da1ef278bbf sale_shipment_tolerance-5.0.0
+0000000000000000000000000000000000000000 5.2.0
+fe7da63d5ea6de75e3fe13109ef8219a69fc2391 sale_shipment_tolerance-5.2.0
+0000000000000000000000000000000000000000 5.4.0
+2742ddec3cb1c8334f9d9ecde0a9c6ad5a8ed36c sale_shipment_tolerance-5.4.0
+0000000000000000000000000000000000000000 5.6.0
+1de405190689ab072107b79be6f003938efa1a3b sale_shipment_tolerance-5.6.0
+0000000000000000000000000000000000000000 5.8.0
+6b06320f1b17705be25b353e4b9c11045af31583 sale_shipment_tolerance-5.8.0
+0000000000000000000000000000000000000000 6.0.0
+cb41254aec0000127774331aedec41f96a17956b sale_shipment_tolerance-6.0.0
+104c6a538cb716b5c27719d633c2d5aff8171646 3.8.0
+905096471c40bdbacfd13f42491991a9b27c21d7 4.0.0
+427e7da28ce7af6b2f4607253c9b235cc669b903 4.2.0
+d992148e8e2f1a8823d265c4ca42d34ab3d8ddf7 4.4.0
+898df1302a7dbaa01416abeeb8d28d59a06da359 4.6.0
+743a19f34c4dbb78065f1404e96c5f923e37e3c8 4.8.0
+b05d84f765a67911944adce3ac14745fce028175 5.0.0
+95f8a4bf87c5e1e810fd1c9f41da850ede67feb9 5.2.0
+7058bd1a301a8b39af68ea44edebffd7752fac05 5.4.0
+2e8927a7d0e2232f5abae5240998a68b72dc7303 5.6.0
+449248ae2cbb69613de518014a0920a44127b53c 5.8.0
+c994d5caf96e9febbdb906400d75ee32a0832125 6.0.0
+744cab2037bee3b12f80d2e96e37d5555d0460e5 6.0.1
+0000000000000000000000000000000000000000 3.8.0
+104c6a538cb716b5c27719d633c2d5aff8171646 sale_stock_quantity-3.8.0
+0000000000000000000000000000000000000000 4.0.0
+905096471c40bdbacfd13f42491991a9b27c21d7 sale_stock_quantity-4.0.0
+0000000000000000000000000000000000000000 4.2.0
+427e7da28ce7af6b2f4607253c9b235cc669b903 sale_stock_quantity-4.2.0
+0000000000000000000000000000000000000000 4.4.0
+d992148e8e2f1a8823d265c4ca42d34ab3d8ddf7 sale_stock_quantity-4.4.0
+0000000000000000000000000000000000000000 4.6.0
+898df1302a7dbaa01416abeeb8d28d59a06da359 sale_stock_quantity-4.6.0
+0000000000000000000000000000000000000000 4.8.0
+743a19f34c4dbb78065f1404e96c5f923e37e3c8 sale_stock_quantity-4.8.0
+0000000000000000000000000000000000000000 5.0.0
+b05d84f765a67911944adce3ac14745fce028175 sale_stock_quantity-5.0.0
+0000000000000000000000000000000000000000 5.2.0
+95f8a4bf87c5e1e810fd1c9f41da850ede67feb9 sale_stock_quantity-5.2.0
+0000000000000000000000000000000000000000 5.4.0
+7058bd1a301a8b39af68ea44edebffd7752fac05 sale_stock_quantity-5.4.0
+0000000000000000000000000000000000000000 5.6.0
+2e8927a7d0e2232f5abae5240998a68b72dc7303 sale_stock_quantity-5.6.0
+0000000000000000000000000000000000000000 5.8.0
+449248ae2cbb69613de518014a0920a44127b53c sale_stock_quantity-5.8.0
+0000000000000000000000000000000000000000 6.0.0
+c994d5caf96e9febbdb906400d75ee32a0832125 sale_stock_quantity-6.0.0
+0000000000000000000000000000000000000000 6.0.1
+744cab2037bee3b12f80d2e96e37d5555d0460e5 sale_stock_quantity-6.0.1
+75517bd9657c0e40c5ec4e9e3e37df1586f4dc90 5.0.0
+b3dc75efc82dbe9433628ecb62de248d27db2ad3 5.2.0
+6f9c41ec5642ab214b9ec0f72d2fb9bf0c94e98d 5.4.0
+3bcc53cee134356e3bb99c6c2deb4c54d7121a99 5.6.0
+d2667ef655e3fcd2bce97d45493dd3ca2d39981c 5.8.0
+4de0f53738952b064ded56a22ba8f7dd8f3c78ff 6.0.0
+b369f465f2801b165b0178fe351bfd1b30401b41 6.0.1
+0000000000000000000000000000000000000000 5.0.0
+75517bd9657c0e40c5ec4e9e3e37df1586f4dc90 sale_subscription_asset-5.0.0
+0000000000000000000000000000000000000000 5.2.0
+b3dc75efc82dbe9433628ecb62de248d27db2ad3 sale_subscription_asset-5.2.0
+0000000000000000000000000000000000000000 5.4.0
+6f9c41ec5642ab214b9ec0f72d2fb9bf0c94e98d sale_subscription_asset-5.4.0
+0000000000000000000000000000000000000000 5.6.0
+3bcc53cee134356e3bb99c6c2deb4c54d7121a99 sale_subscription_asset-5.6.0
+0000000000000000000000000000000000000000 5.8.0
+d2667ef655e3fcd2bce97d45493dd3ca2d39981c sale_subscription_asset-5.8.0
+0000000000000000000000000000000000000000 6.0.0
+4de0f53738952b064ded56a22ba8f7dd8f3c78ff sale_subscription_asset-6.0.0
+0000000000000000000000000000000000000000 6.0.1
+b369f465f2801b165b0178fe351bfd1b30401b41 sale_subscription_asset-6.0.1
+1e234d7fe95a4207e73e849c12ca95b99723007c 4.4.0
+cf51019e46261067d3ae3b02e89fde523fa0d6a4 4.6.0
+c61628856c63e5efc941573029a21dfb14f1ce06 4.8.0
+0d147bdf58a17b11fe3fb8fcf875ee3d1a75dde6 5.0.0
+5a0870de5f7ae7d7461c9f9eca3af6f235ff3cb6 5.2.0
+5e15f189af137372ca03673beacec43acb69c2c9 5.4.0
+516aa84817b09c7bccbbe86b66b6417aeb425243 5.6.0
+199c9c6bf4abe1ab1984ddd7d11e3ef6cd973d0b 5.8.0
+6770e1add356bc79935ab2b7a7cf9021d94e4cd8 6.0.0
+f86052339cb97ce945912155ee5beb071c6bf58d 6.0.1
+beff7dd082dc6634338cc91e2a7d8749f583af18 6.0.2
+0000000000000000000000000000000000000000 4.4.0
+1e234d7fe95a4207e73e849c12ca95b99723007c sale_subscription-4.4.0
+0000000000000000000000000000000000000000 4.6.0
+cf51019e46261067d3ae3b02e89fde523fa0d6a4 sale_subscription-4.6.0
+0000000000000000000000000000000000000000 4.8.0
+c61628856c63e5efc941573029a21dfb14f1ce06 sale_subscription-4.8.0
+0000000000000000000000000000000000000000 5.0.0
+0d147bdf58a17b11fe3fb8fcf875ee3d1a75dde6 sale_subscription-5.0.0
+0000000000000000000000000000000000000000 5.2.0
+5a0870de5f7ae7d7461c9f9eca3af6f235ff3cb6 sale_subscription-5.2.0
+0000000000000000000000000000000000000000 5.4.0
+5e15f189af137372ca03673beacec43acb69c2c9 sale_subscription-5.4.0
+0000000000000000000000000000000000000000 5.6.0
+516aa84817b09c7bccbbe86b66b6417aeb425243 sale_subscription-5.6.0
+0000000000000000000000000000000000000000 5.8.0
+199c9c6bf4abe1ab1984ddd7d11e3ef6cd973d0b sale_subscription-5.8.0
+0000000000000000000000000000000000000000 6.0.0
+6770e1add356bc79935ab2b7a7cf9021d94e4cd8 sale_subscription-6.0.0
+0000000000000000000000000000000000000000 6.0.1
+f86052339cb97ce945912155ee5beb071c6bf58d sale_subscription-6.0.1
+0000000000000000000000000000000000000000 6.0.2
+beff7dd082dc6634338cc91e2a7d8749f583af18 sale_subscription-6.0.2
+19a57b0b3ad67a2c214b86511794cef0396736e7 2.8.0
+f711cca156f5b37f1979421cec9eb7519ac1fc98 3.0.0
+d66d5107d6b1eecab92dffedaf71343abbc87b48 3.2.0
+7205cff4d35b08ecfc535bc04394365b1503922f 3.4.0
+7127d9b83914b90ba27e1ca499fd30a4d4e39791 3.6.0
+baddf1fac5d962cf2339b003f4099def522f263d 3.8.0
+36405360c0de87f3aaf7603f6794864c2e988bbb 4.0.0
+d928b2d0144e706c003caef549ee1166dadf41f9 4.2.0
+678245521b888dba63e5b31eadc4cb09d3229631 4.4.0
+e395bc2eea0270a69dae5cd36785799006474532 4.6.0
+b4ecb0306ebf8b7d04ce8005edbb70a9f4ba1019 4.8.0
+e2452d05303463862d2da2b262a0a9624787f41e 5.0.0
+97d07dba78b2bc9b87f00d17266e68f6ae7d8da3 5.2.0
+48139e76f98ce32ede8a0f79c414a674a4ebfdcf 5.4.0
+614b1e3edc866b885d531338cbd008c126de3956 5.6.0
+3dd257f7aacb341fc9d3b36bcd5a7ca137e1a39c 5.8.0
+394e3db8573728ed4b4aff1520aeea8ab3f4e063 6.0.0
+906621151e54dc1207e32fd0020d5011fe410448 6.0.1
+5adad935706d1d3d9e03b79abffb815ec77ba3af 6.0.2
+6b39b2b8632615e7a32a108acf40c099f493868b 6.0.3
+0000000000000000000000000000000000000000 2.8.0
+19a57b0b3ad67a2c214b86511794cef0396736e7 sale_supply_drop_shipment-2.8.0
+0000000000000000000000000000000000000000 3.0.0
+f711cca156f5b37f1979421cec9eb7519ac1fc98 sale_supply_drop_shipment-3.0.0
+0000000000000000000000000000000000000000 3.2.0
+d66d5107d6b1eecab92dffedaf71343abbc87b48 sale_supply_drop_shipment-3.2.0
+0000000000000000000000000000000000000000 3.4.0
+7205cff4d35b08ecfc535bc04394365b1503922f sale_supply_drop_shipment-3.4.0
+0000000000000000000000000000000000000000 3.6.0
+7127d9b83914b90ba27e1ca499fd30a4d4e39791 sale_supply_drop_shipment-3.6.0
+0000000000000000000000000000000000000000 3.8.0
+baddf1fac5d962cf2339b003f4099def522f263d sale_supply_drop_shipment-3.8.0
+0000000000000000000000000000000000000000 4.0.0
+36405360c0de87f3aaf7603f6794864c2e988bbb sale_supply_drop_shipment-4.0.0
+0000000000000000000000000000000000000000 4.2.0
+d928b2d0144e706c003caef549ee1166dadf41f9 sale_supply_drop_shipment-4.2.0
+0000000000000000000000000000000000000000 4.4.0
+678245521b888dba63e5b31eadc4cb09d3229631 sale_supply_drop_shipment-4.4.0
+0000000000000000000000000000000000000000 4.6.0
+e395bc2eea0270a69dae5cd36785799006474532 sale_supply_drop_shipment-4.6.0
+0000000000000000000000000000000000000000 4.8.0
+b4ecb0306ebf8b7d04ce8005edbb70a9f4ba1019 sale_supply_drop_shipment-4.8.0
+0000000000000000000000000000000000000000 5.0.0
+e2452d05303463862d2da2b262a0a9624787f41e sale_supply_drop_shipment-5.0.0
+0000000000000000000000000000000000000000 5.2.0
+97d07dba78b2bc9b87f00d17266e68f6ae7d8da3 sale_supply_drop_shipment-5.2.0
+0000000000000000000000000000000000000000 5.4.0
+48139e76f98ce32ede8a0f79c414a674a4ebfdcf sale_supply_drop_shipment-5.4.0
+0000000000000000000000000000000000000000 5.6.0
+614b1e3edc866b885d531338cbd008c126de3956 sale_supply_drop_shipment-5.6.0
+0000000000000000000000000000000000000000 5.8.0
+3dd257f7aacb341fc9d3b36bcd5a7ca137e1a39c sale_supply_drop_shipment-5.8.0
+0000000000000000000000000000000000000000 6.0.0
+394e3db8573728ed4b4aff1520aeea8ab3f4e063 sale_supply_drop_shipment-6.0.0
+0000000000000000000000000000000000000000 6.0.1
+906621151e54dc1207e32fd0020d5011fe410448 sale_supply_drop_shipment-6.0.1
+0000000000000000000000000000000000000000 6.0.2
+5adad935706d1d3d9e03b79abffb815ec77ba3af sale_supply_drop_shipment-6.0.2
+0000000000000000000000000000000000000000 6.0.3
+6b39b2b8632615e7a32a108acf40c099f493868b sale_supply_drop_shipment-6.0.3
+9d51a13e8346425ad0304993f732c1e5a20a76c1 2.8.0
+2073077ab2b0c6a1f8a0b39accf36ccb14fd77c0 3.0.0
+25a90ba19bbcf5b93a2ec81d96590f0c244d3df4 3.2.0
+5478dfb45b7d156cb8ce9069290f94ff7340a1b4 3.4.0
+836d4865c124edda9132ce46eedf39031112930a 3.6.0
+ccee92d5cac85cd171a4190c106ca13e17cc077f 3.8.0
+d58ed0bed67cb50a6c576bf6abd582ecbb902d74 4.0.0
+25e9c457fd1097bb0898194632ef719ad1edd8e5 4.2.0
+be59a2b5ff6771cf4d5c9b1c78f72ed8f2995c9a 4.4.0
+cbbb1d178e77d277bdb7c27a0c8b1ecce443b942 4.6.0
+698ea041c44ede7b132ac142db13642c2d4a0e4b 4.8.0
+e869a845b7d9fdbcfe7ed17d4c322230efc34f6e 5.0.0
+e0ebd4611c7a3c6486bd3cb553cb703ce7e03d33 5.2.0
+ecaf5fd99a7a59e3fc5e4615cd668eba43a037ac 5.4.0
+920a0452a4d5fb8781ecb9e3971e77dc54c82802 5.6.0
+2bdcbedcd4c2b51bb9fb1170ccbc856bb0e4c62d 5.8.0
+156bd2b7b22290d9bc319376801d1c70f5a4b6c0 6.0.0
+87d145c8591c8b46f9731cbec8dcfbfc19d22355 6.0.1
+0000000000000000000000000000000000000000 2.8.0
+9d51a13e8346425ad0304993f732c1e5a20a76c1 sale_supply-2.8.0
+0000000000000000000000000000000000000000 3.0.0
+2073077ab2b0c6a1f8a0b39accf36ccb14fd77c0 sale_supply-3.0.0
+0000000000000000000000000000000000000000 3.2.0
+25a90ba19bbcf5b93a2ec81d96590f0c244d3df4 sale_supply-3.2.0
+0000000000000000000000000000000000000000 3.4.0
+5478dfb45b7d156cb8ce9069290f94ff7340a1b4 sale_supply-3.4.0
+0000000000000000000000000000000000000000 3.6.0
+836d4865c124edda9132ce46eedf39031112930a sale_supply-3.6.0
+0000000000000000000000000000000000000000 3.8.0
+ccee92d5cac85cd171a4190c106ca13e17cc077f sale_supply-3.8.0
+0000000000000000000000000000000000000000 4.0.0
+d58ed0bed67cb50a6c576bf6abd582ecbb902d74 sale_supply-4.0.0
+0000000000000000000000000000000000000000 4.2.0
+25e9c457fd1097bb0898194632ef719ad1edd8e5 sale_supply-4.2.0
+0000000000000000000000000000000000000000 4.4.0
+be59a2b5ff6771cf4d5c9b1c78f72ed8f2995c9a sale_supply-4.4.0
+0000000000000000000000000000000000000000 4.6.0
+cbbb1d178e77d277bdb7c27a0c8b1ecce443b942 sale_supply-4.6.0
+0000000000000000000000000000000000000000 4.8.0
+698ea041c44ede7b132ac142db13642c2d4a0e4b sale_supply-4.8.0
+0000000000000000000000000000000000000000 5.0.0
+e869a845b7d9fdbcfe7ed17d4c322230efc34f6e sale_supply-5.0.0
+0000000000000000000000000000000000000000 5.2.0
+e0ebd4611c7a3c6486bd3cb553cb703ce7e03d33 sale_supply-5.2.0
+0000000000000000000000000000000000000000 5.4.0
+ecaf5fd99a7a59e3fc5e4615cd668eba43a037ac sale_supply-5.4.0
+0000000000000000000000000000000000000000 5.6.0
+920a0452a4d5fb8781ecb9e3971e77dc54c82802 sale_supply-5.6.0
+0000000000000000000000000000000000000000 5.8.0
+2bdcbedcd4c2b51bb9fb1170ccbc856bb0e4c62d sale_supply-5.8.0
+0000000000000000000000000000000000000000 6.0.0
+156bd2b7b22290d9bc319376801d1c70f5a4b6c0 sale_supply-6.0.0
+0000000000000000000000000000000000000000 6.0.1
+87d145c8591c8b46f9731cbec8dcfbfc19d22355 sale_supply-6.0.1
+f62f4846d82f2c05110d92ddb65f764478df50d4 5.6.0
+2e4a3b14e265050e2df36c1c96b03fd246a5da6e 5.8.0
+2081017ba6e796df571eb28475f82ada5ab9c27f 6.0.0
+dd0c6e4d288c0a5ba33192e58cb37808ee3fdec2 6.0.1
+0000000000000000000000000000000000000000 5.6.0
+f62f4846d82f2c05110d92ddb65f764478df50d4 sale_supply_production-5.6.0
+0000000000000000000000000000000000000000 5.8.0
+2e4a3b14e265050e2df36c1c96b03fd246a5da6e sale_supply_production-5.8.0
+0000000000000000000000000000000000000000 6.0.0
+2081017ba6e796df571eb28475f82ada5ab9c27f sale_supply_production-6.0.0
+0000000000000000000000000000000000000000 6.0.1
+dd0c6e4d288c0a5ba33192e58cb37808ee3fdec2 sale_supply_production-6.0.1
+2ecdd7815e6c21be61cd051a6a9e8b717f070a88 5.8.0
+8ca8057e893a91132d0cd825f4d657f33d7ea0e7 6.0.0
+3e67ce9619dd4fa27ad1ea43b1b91a56b59f9d01 6.0.1
+0000000000000000000000000000000000000000 5.8.0
+2ecdd7815e6c21be61cd051a6a9e8b717f070a88 stock_assign_manual-5.8.0
+0000000000000000000000000000000000000000 6.0.0
+8ca8057e893a91132d0cd825f4d657f33d7ea0e7 stock_assign_manual-6.0.0
+0000000000000000000000000000000000000000 6.0.1
+3e67ce9619dd4fa27ad1ea43b1b91a56b59f9d01 stock_assign_manual-6.0.1
+1cca6d14276b659f00a0fc38be07cc5fe34f5ee3 4.6.0
+f4fdf5e0eed18ad55d81251b7836d58d82a2c8e6 4.8.0
+a70b520434de02e84563ff24c9355edbfcf211bd 5.0.0
+9f4f86318326142aa40c5581d7ee6305e80bb54c 5.2.0
+9caec42518ff5f7bcae3b3318f8f1a93c659e2df 5.4.0
+30267e762f4cff49765e21f8676afb8a82378004 5.6.0
+2f3647bc2b8116b932578ea01c1933e56c3e6e72 5.8.0
+ae83f77292cfd1c40a0997c570a4fba56ccb09d0 6.0.0
+e135f31b4507791092dc1e3812d47706bf6269ee 6.0.1
+e0f024b6d13467e95992fe5e5a3ff73ee007621e 6.0.2
+0000000000000000000000000000000000000000 4.6.0
+1cca6d14276b659f00a0fc38be07cc5fe34f5ee3 stock_consignment-4.6.0
+0000000000000000000000000000000000000000 4.8.0
+f4fdf5e0eed18ad55d81251b7836d58d82a2c8e6 stock_consignment-4.8.0
+0000000000000000000000000000000000000000 5.0.0
+a70b520434de02e84563ff24c9355edbfcf211bd stock_consignment-5.0.0
+0000000000000000000000000000000000000000 5.2.0
+9f4f86318326142aa40c5581d7ee6305e80bb54c stock_consignment-5.2.0
+0000000000000000000000000000000000000000 5.4.0
+9caec42518ff5f7bcae3b3318f8f1a93c659e2df stock_consignment-5.4.0
+0000000000000000000000000000000000000000 5.6.0
+30267e762f4cff49765e21f8676afb8a82378004 stock_consignment-5.6.0
+0000000000000000000000000000000000000000 5.8.0
+2f3647bc2b8116b932578ea01c1933e56c3e6e72 stock_consignment-5.8.0
+0000000000000000000000000000000000000000 6.0.0
+ae83f77292cfd1c40a0997c570a4fba56ccb09d0 stock_consignment-6.0.0
+0000000000000000000000000000000000000000 6.0.1
+e135f31b4507791092dc1e3812d47706bf6269ee stock_consignment-6.0.1
+0000000000000000000000000000000000000000 6.0.2
+e0f024b6d13467e95992fe5e5a3ff73ee007621e stock_consignment-6.0.2
+b9ba6291ff01f9f6ceaa7685324e385aaad70ed8 1.2.0
+ddd1eccfec75e5a7c29f1679e68987ec16c4079b 1.4.0
+ec15c191467d843cee84661735d8e6b1a614e87f 1.6.0
+3e2d602a2d7bef0d69b99daa0c2c82bc98bbe3f0 1.8.0
+a0bef2c542a5d734e6a7f9d7984e945156cf5be2 2.0.0
+2745e0851b7da8701df441dac1b27e8ec95f5b5e 2.2.0
+7f0bb8e8f9faba66514b88819a8cf38cf79490d3 2.4.0
+88b74de7c907a886cc73be70f38d624ac7ebee19 2.6.0
+ca9d55dd442d515a52a3fcfc8fc60f784ea5e906 2.8.0
+94dfb0ac9d740888fa59ba2d58a9a5c0aef409e1 3.0.0
+9658f3f89a68c82b80138a37a115b764657493c5 3.2.0
+4d5fc8837f7eae07f8634d718b3ae2903b6ae60a 3.4.0
+d22c87db76f1557f048c68f6ad3ad87776b41079 3.6.0
+229754c2419cb9201649abe4a937457458a87c31 3.8.0
+d8d9d25f84964e131574d5c2af10127d5def2de1 4.0.0
+5dcd83fc7e31a660b1bf3481e82fd66fe913917d 4.2.0
+ca7feded741ba1714157280cdb4012d5ec0eee34 4.4.0
+b8a5320254d19e69acf55a9e0d15efd1617963ac 4.6.0
+e51f3aa6f87fd0b45a49d19f1f96f85f024f41cb 4.8.0
+1605875226050dfba9bdbec52bdc178c4d12b3ab 5.0.0
+e3220f9f070d012d207eb41083f9e5b645a14213 5.2.0
+8aa238ec2462dbde49cc8e0d0ab72a48d0e8ffd9 5.4.0
+823cc750b4c3758e09e2b5a9dbc908b6096922e8 5.6.0
+2ea6e7d95ad940d0a7f2b6e35c0547caa3d47ed2 5.8.0
+6b68d584ffcc365975efb0e4754d92b90d060d85 6.0.0
+e233e9feddcc6b91e38f96117d09f77944be1a7e 6.0.1
+cb1831b5b9fbcbb6089ea440e439fb73167cf307 6.0.2
+0000000000000000000000000000000000000000 1.2.0
+b9ba6291ff01f9f6ceaa7685324e385aaad70ed8 stock_forecast-1.2.0
+0000000000000000000000000000000000000000 1.4.0
+ddd1eccfec75e5a7c29f1679e68987ec16c4079b stock_forecast-1.4.0
+0000000000000000000000000000000000000000 1.6.0
+ec15c191467d843cee84661735d8e6b1a614e87f stock_forecast-1.6.0
+0000000000000000000000000000000000000000 1.8.0
+3e2d602a2d7bef0d69b99daa0c2c82bc98bbe3f0 stock_forecast-1.8.0
+0000000000000000000000000000000000000000 2.0.0
+a0bef2c542a5d734e6a7f9d7984e945156cf5be2 stock_forecast-2.0.0
+0000000000000000000000000000000000000000 2.2.0
+2745e0851b7da8701df441dac1b27e8ec95f5b5e stock_forecast-2.2.0
+0000000000000000000000000000000000000000 2.4.0
+7f0bb8e8f9faba66514b88819a8cf38cf79490d3 stock_forecast-2.4.0
+0000000000000000000000000000000000000000 2.6.0
+88b74de7c907a886cc73be70f38d624ac7ebee19 stock_forecast-2.6.0
+0000000000000000000000000000000000000000 2.8.0
+ca9d55dd442d515a52a3fcfc8fc60f784ea5e906 stock_forecast-2.8.0
+0000000000000000000000000000000000000000 3.0.0
+94dfb0ac9d740888fa59ba2d58a9a5c0aef409e1 stock_forecast-3.0.0
+0000000000000000000000000000000000000000 3.2.0
+9658f3f89a68c82b80138a37a115b764657493c5 stock_forecast-3.2.0
+0000000000000000000000000000000000000000 3.4.0
+4d5fc8837f7eae07f8634d718b3ae2903b6ae60a stock_forecast-3.4.0
+0000000000000000000000000000000000000000 3.6.0
+d22c87db76f1557f048c68f6ad3ad87776b41079 stock_forecast-3.6.0
+0000000000000000000000000000000000000000 3.8.0
+229754c2419cb9201649abe4a937457458a87c31 stock_forecast-3.8.0
+0000000000000000000000000000000000000000 4.0.0
+d8d9d25f84964e131574d5c2af10127d5def2de1 stock_forecast-4.0.0
+0000000000000000000000000000000000000000 4.2.0
+5dcd83fc7e31a660b1bf3481e82fd66fe913917d stock_forecast-4.2.0
+0000000000000000000000000000000000000000 4.4.0
+ca7feded741ba1714157280cdb4012d5ec0eee34 stock_forecast-4.4.0
+0000000000000000000000000000000000000000 4.6.0
+b8a5320254d19e69acf55a9e0d15efd1617963ac stock_forecast-4.6.0
+0000000000000000000000000000000000000000 4.8.0
+e51f3aa6f87fd0b45a49d19f1f96f85f024f41cb stock_forecast-4.8.0
+0000000000000000000000000000000000000000 5.0.0
+1605875226050dfba9bdbec52bdc178c4d12b3ab stock_forecast-5.0.0
+0000000000000000000000000000000000000000 5.2.0
+e3220f9f070d012d207eb41083f9e5b645a14213 stock_forecast-5.2.0
+0000000000000000000000000000000000000000 5.4.0
+8aa238ec2462dbde49cc8e0d0ab72a48d0e8ffd9 stock_forecast-5.4.0
+0000000000000000000000000000000000000000 5.6.0
+823cc750b4c3758e09e2b5a9dbc908b6096922e8 stock_forecast-5.6.0
+0000000000000000000000000000000000000000 5.8.0
+2ea6e7d95ad940d0a7f2b6e35c0547caa3d47ed2 stock_forecast-5.8.0
+0000000000000000000000000000000000000000 6.0.0
+6b68d584ffcc365975efb0e4754d92b90d060d85 stock_forecast-6.0.0
+0000000000000000000000000000000000000000 6.0.1
+e233e9feddcc6b91e38f96117d09f77944be1a7e stock_forecast-6.0.1
+0000000000000000000000000000000000000000 6.0.2
+cb1831b5b9fbcbb6089ea440e439fb73167cf307 stock_forecast-6.0.2
+36cc8c10a10e0df5e7a0ef2cb6d6cdda706c0180 1.0.0
+f1d720635a60692c9abeb972734482e01ebc4b87 1.2.0
+0571f5c67623c43272e5fc05cc381554d6bf3db0 1.4.0
+6a658c8f74a540a10272f5d7f311d6c61c04f3da 1.6.0
+902e4b31b9d56918b1e9eb6e9486f52d19820fa6 1.8.0
+c2e3b9e568b73f262ebf0b69c2ca98f97cbb886e 2.0.0
+3babec8ed968fa95e07a7d90351de0e23a1125bf 2.2.0
+6217a989c27b4780c99ae09ee8cd1bd99807f857 2.4.0
+be073cc040e1ea0eabf77e09eaa8c8c97062e3ab 2.6.0
+83de8e4076f99f7247dc034a909a85a0dc500d84 2.8.0
+1e2bd2e0ec24c7c6109d38625e90462dffb18c13 3.0.0
+bcb26eaee7652f9b11cc717402859b0c3c6d87d2 3.2.0
+70be46258bf1471f5712285ae1772941610aaf7b 3.4.0
+70c741dc67fb55b51b950b2c5fa383318e693e04 3.6.0
+1b17ff426586b71fc7df09353c6337abe409c7cc 3.8.0
+f8628e226bd36c24c4ba5fece3363a272d2090eb 4.0.0
+ba22e15da88bf5736b49a85f12d8d4c864f4bd3f 4.2.0
+03dc7be46d80699cc35528ffe1416d972868d830 4.4.0
+e987bc41694de75a4a74235c12d7a576083c24ba 4.6.0
+697136ec827439a97ba89764f6c4e603f44c2dde 4.8.0
+997d19b737f02756d91647bbcf2c244c75454a13 5.0.0
+72a0c9157ce92abc2aef770d49e4f4d2df334e53 5.2.0
+2d1eab94f8c1efa0b7c9008f333d3419d3afd92e 5.4.0
+942dd4faf224b4b7a4d24fa47488f9453c9d37de 5.6.0
+d1e67fbb11774d0a7ca3bd5761cf4ea11dbaa4b8 5.8.0
+07499733ef86626acae2c8249ea02eb14ac4990f 6.0.0
+d2ee66917e7a025dbe0a45c5e20246921f88e3ab 6.0.1
+e0f26d2d46f0b8d2466f74c572e7b3eac747ef6d 6.0.2
+39ab9008e2b31f3067ca193e97e6b4182a97dbf1 6.0.3
+c4559954273ed17956b9f424e506e004cad913a8 6.0.4
+a231e37aa2b8074e0a5ddc4957decd74d528268b 6.0.5
+bdbcc38971c21643796423e4fe7af1d487d7abc6 6.0.6
+95d6cbcf8e8e4c2661c872fbadfc031ed9294a57 6.0.7
+046cf4bde35642bf0dfd9701a4cf2fcfbd0599a7 6.0.8
+21767740f556a7cc537b4e1f39d2d709b7f5ea3a 6.0.9
+7eb0b3717a39da9388a90ed5aa6a84f68494c594 6.0.10
+642a659e1017214dd9559d3c1ab97ffdd5457d79 6.0.11
+a29dbdb162873ebdea451f6895f895b063b3bb07 6.0.12
+b2feddae43b362b85b5b70908cefcff96ba1b0dd 6.0.13
+3688ec9159b359be2fbb3b3de8a8fce97e9effb6 6.0.14
+0dd8675f2ca761e2f461cb96ba36ec5b841404b2 6.0.15
+95767dcfed28d7257ca79b81157006aa8cd78c51 6.0.16
+27b7111d95687f65648992b8c2bc09fdbc24aebe 6.0.17
+98b3979b26627af842f6552583a216346c4ece89 6.0.18
+0000000000000000000000000000000000000000 1.0.0
+36cc8c10a10e0df5e7a0ef2cb6d6cdda706c0180 stock-1.0.0
+0000000000000000000000000000000000000000 1.2.0
+f1d720635a60692c9abeb972734482e01ebc4b87 stock-1.2.0
+0000000000000000000000000000000000000000 1.4.0
+0571f5c67623c43272e5fc05cc381554d6bf3db0 stock-1.4.0
+0000000000000000000000000000000000000000 1.6.0
+6a658c8f74a540a10272f5d7f311d6c61c04f3da stock-1.6.0
+0000000000000000000000000000000000000000 1.8.0
+902e4b31b9d56918b1e9eb6e9486f52d19820fa6 stock-1.8.0
+0000000000000000000000000000000000000000 2.0.0
+c2e3b9e568b73f262ebf0b69c2ca98f97cbb886e stock-2.0.0
+0000000000000000000000000000000000000000 2.2.0
+3babec8ed968fa95e07a7d90351de0e23a1125bf stock-2.2.0
+0000000000000000000000000000000000000000 2.4.0
+6217a989c27b4780c99ae09ee8cd1bd99807f857 stock-2.4.0
+0000000000000000000000000000000000000000 2.6.0
+be073cc040e1ea0eabf77e09eaa8c8c97062e3ab stock-2.6.0
+0000000000000000000000000000000000000000 2.8.0
+83de8e4076f99f7247dc034a909a85a0dc500d84 stock-2.8.0
+0000000000000000000000000000000000000000 3.0.0
+1e2bd2e0ec24c7c6109d38625e90462dffb18c13 stock-3.0.0
+0000000000000000000000000000000000000000 3.2.0
+bcb26eaee7652f9b11cc717402859b0c3c6d87d2 stock-3.2.0
+0000000000000000000000000000000000000000 3.4.0
+70be46258bf1471f5712285ae1772941610aaf7b stock-3.4.0
+0000000000000000000000000000000000000000 3.6.0
+70c741dc67fb55b51b950b2c5fa383318e693e04 stock-3.6.0
+0000000000000000000000000000000000000000 3.8.0
+1b17ff426586b71fc7df09353c6337abe409c7cc stock-3.8.0
+0000000000000000000000000000000000000000 4.0.0
+f8628e226bd36c24c4ba5fece3363a272d2090eb stock-4.0.0
+0000000000000000000000000000000000000000 4.2.0
+ba22e15da88bf5736b49a85f12d8d4c864f4bd3f stock-4.2.0
+0000000000000000000000000000000000000000 4.4.0
+03dc7be46d80699cc35528ffe1416d972868d830 stock-4.4.0
+0000000000000000000000000000000000000000 4.6.0
+e987bc41694de75a4a74235c12d7a576083c24ba stock-4.6.0
+0000000000000000000000000000000000000000 4.8.0
+697136ec827439a97ba89764f6c4e603f44c2dde stock-4.8.0
+0000000000000000000000000000000000000000 5.0.0
+997d19b737f02756d91647bbcf2c244c75454a13 stock-5.0.0
+0000000000000000000000000000000000000000 5.2.0
+72a0c9157ce92abc2aef770d49e4f4d2df334e53 stock-5.2.0
+0000000000000000000000000000000000000000 5.4.0
+2d1eab94f8c1efa0b7c9008f333d3419d3afd92e stock-5.4.0
+0000000000000000000000000000000000000000 5.6.0
+942dd4faf224b4b7a4d24fa47488f9453c9d37de stock-5.6.0
+0000000000000000000000000000000000000000 5.8.0
+d1e67fbb11774d0a7ca3bd5761cf4ea11dbaa4b8 stock-5.8.0
+0000000000000000000000000000000000000000 6.0.0
+07499733ef86626acae2c8249ea02eb14ac4990f stock-6.0.0
+0000000000000000000000000000000000000000 6.0.1
+d2ee66917e7a025dbe0a45c5e20246921f88e3ab stock-6.0.1
+0000000000000000000000000000000000000000 6.0.10
+7eb0b3717a39da9388a90ed5aa6a84f68494c594 stock-6.0.10
+0000000000000000000000000000000000000000 6.0.11
+642a659e1017214dd9559d3c1ab97ffdd5457d79 stock-6.0.11
+0000000000000000000000000000000000000000 6.0.12
+a29dbdb162873ebdea451f6895f895b063b3bb07 stock-6.0.12
+0000000000000000000000000000000000000000 6.0.13
+b2feddae43b362b85b5b70908cefcff96ba1b0dd stock-6.0.13
+0000000000000000000000000000000000000000 6.0.14
+3688ec9159b359be2fbb3b3de8a8fce97e9effb6 stock-6.0.14
+0000000000000000000000000000000000000000 6.0.15
+0dd8675f2ca761e2f461cb96ba36ec5b841404b2 stock-6.0.15
+0000000000000000000000000000000000000000 6.0.16
+95767dcfed28d7257ca79b81157006aa8cd78c51 stock-6.0.16
+0000000000000000000000000000000000000000 6.0.17
+27b7111d95687f65648992b8c2bc09fdbc24aebe stock-6.0.17
+0000000000000000000000000000000000000000 6.0.18
+98b3979b26627af842f6552583a216346c4ece89 stock-6.0.18
+0000000000000000000000000000000000000000 6.0.2
+e0f26d2d46f0b8d2466f74c572e7b3eac747ef6d stock-6.0.2
+0000000000000000000000000000000000000000 6.0.3
+39ab9008e2b31f3067ca193e97e6b4182a97dbf1 stock-6.0.3
+0000000000000000000000000000000000000000 6.0.4
+c4559954273ed17956b9f424e506e004cad913a8 stock-6.0.4
+0000000000000000000000000000000000000000 6.0.5
+a231e37aa2b8074e0a5ddc4957decd74d528268b stock-6.0.5
+0000000000000000000000000000000000000000 6.0.6
+bdbcc38971c21643796423e4fe7af1d487d7abc6 stock-6.0.6
+0000000000000000000000000000000000000000 6.0.7
+95d6cbcf8e8e4c2661c872fbadfc031ed9294a57 stock-6.0.7
+0000000000000000000000000000000000000000 6.0.8
+046cf4bde35642bf0dfd9701a4cf2fcfbd0599a7 stock-6.0.8
+0000000000000000000000000000000000000000 6.0.9
+21767740f556a7cc537b4e1f39d2d709b7f5ea3a stock-6.0.9
+059c67523e52eda86c563a2414e2b6107b101a8d 1.2.0
+225b705164561d09d5fcae80b784da0fedd531fc 1.4.0
+185537801e5e1ed3b6a2f6719db0e999c0d805e1 1.6.0
+1e23789f77c3e731e73ddc789d8b9ce9f01efc70 1.8.0
+241ddb0a8f8ded2e160598d3efc2e2a00d64abc9 2.0.0
+739e08551f9b9d6e80619ad88d2a8e4e64e3c986 2.2.0
+0299558c412d8feb4db592e3f360fd4b0ecc52cc 2.4.0
+44e7cada1ccc7466f0c284505fd21c335cdb1f58 2.6.0
+f688494c52bc7de9316ae436d20441371a73b3ec 2.8.0
+931ee9f97e52351fc8c7dae24581168d1b3b8c18 3.0.0
+4870db0874d83c50955cbbca10af3ae5b26aae94 3.2.0
+154ea5fb86b75faffd363439f1d6e990d6936c68 3.4.0
+af2746cd736ea6c0d5deee681e9e6286513d2837 3.6.0
+cdc30282449ca7b4991228fde5f99d38673a4fd0 3.8.0
+2b15dc5cabb1156e41e49bcc64b55ae085f2e325 4.0.0
+f86b857b0aa3b56b09d5f574b3a4560b0b00502c 4.2.0
+b6f4180cc07450e9041db772ddfd0dca2f3134ef 4.4.0
+52b6e412dc583d0578df29abfb95cc3865cba4b2 4.6.0
+fc2aa3c75ba8fdb40273523e4fefb1777c4919f8 4.8.0
+bd5dc78969db8e574bef34ca69fa946e49c766ef 5.0.0
+9c0c444c4fda668a0ee25e016a67751a11b5e131 5.2.0
+639a8cb26974fca129c9d7bdae8bba88380c9efe 5.4.0
+dbced0dbb0ad20cf471c30cfafd2b0eee3cfe6d4 5.6.0
+ef5bc23acec6b070d72acd94a55539969f114699 5.8.0
+e5bea2a22f5042af86510ab283ef7f6a30276bfd 6.0.0
+0000000000000000000000000000000000000000 1.2.0
+059c67523e52eda86c563a2414e2b6107b101a8d stock_inventory_location-1.2.0
+0000000000000000000000000000000000000000 1.4.0
+225b705164561d09d5fcae80b784da0fedd531fc stock_inventory_location-1.4.0
+0000000000000000000000000000000000000000 1.6.0
+185537801e5e1ed3b6a2f6719db0e999c0d805e1 stock_inventory_location-1.6.0
+0000000000000000000000000000000000000000 1.8.0
+1e23789f77c3e731e73ddc789d8b9ce9f01efc70 stock_inventory_location-1.8.0
+0000000000000000000000000000000000000000 2.0.0
+241ddb0a8f8ded2e160598d3efc2e2a00d64abc9 stock_inventory_location-2.0.0
+0000000000000000000000000000000000000000 2.2.0
+739e08551f9b9d6e80619ad88d2a8e4e64e3c986 stock_inventory_location-2.2.0
+0000000000000000000000000000000000000000 2.4.0
+0299558c412d8feb4db592e3f360fd4b0ecc52cc stock_inventory_location-2.4.0
+0000000000000000000000000000000000000000 2.6.0
+44e7cada1ccc7466f0c284505fd21c335cdb1f58 stock_inventory_location-2.6.0
+0000000000000000000000000000000000000000 2.8.0
+f688494c52bc7de9316ae436d20441371a73b3ec stock_inventory_location-2.8.0
+0000000000000000000000000000000000000000 3.0.0
+931ee9f97e52351fc8c7dae24581168d1b3b8c18 stock_inventory_location-3.0.0
+0000000000000000000000000000000000000000 3.2.0
+4870db0874d83c50955cbbca10af3ae5b26aae94 stock_inventory_location-3.2.0
+0000000000000000000000000000000000000000 3.4.0
+154ea5fb86b75faffd363439f1d6e990d6936c68 stock_inventory_location-3.4.0
+0000000000000000000000000000000000000000 3.6.0
+af2746cd736ea6c0d5deee681e9e6286513d2837 stock_inventory_location-3.6.0
+0000000000000000000000000000000000000000 3.8.0
+cdc30282449ca7b4991228fde5f99d38673a4fd0 stock_inventory_location-3.8.0
+0000000000000000000000000000000000000000 4.0.0
+2b15dc5cabb1156e41e49bcc64b55ae085f2e325 stock_inventory_location-4.0.0
+0000000000000000000000000000000000000000 4.2.0
+f86b857b0aa3b56b09d5f574b3a4560b0b00502c stock_inventory_location-4.2.0
+0000000000000000000000000000000000000000 4.4.0
+b6f4180cc07450e9041db772ddfd0dca2f3134ef stock_inventory_location-4.4.0
+0000000000000000000000000000000000000000 4.6.0
+52b6e412dc583d0578df29abfb95cc3865cba4b2 stock_inventory_location-4.6.0
+0000000000000000000000000000000000000000 4.8.0
+fc2aa3c75ba8fdb40273523e4fefb1777c4919f8 stock_inventory_location-4.8.0
+0000000000000000000000000000000000000000 5.0.0
+bd5dc78969db8e574bef34ca69fa946e49c766ef stock_inventory_location-5.0.0
+0000000000000000000000000000000000000000 5.2.0
+9c0c444c4fda668a0ee25e016a67751a11b5e131 stock_inventory_location-5.2.0
+0000000000000000000000000000000000000000 5.4.0
+639a8cb26974fca129c9d7bdae8bba88380c9efe stock_inventory_location-5.4.0
+0000000000000000000000000000000000000000 5.6.0
+dbced0dbb0ad20cf471c30cfafd2b0eee3cfe6d4 stock_inventory_location-5.6.0
+0000000000000000000000000000000000000000 5.8.0
+ef5bc23acec6b070d72acd94a55539969f114699 stock_inventory_location-5.8.0
+0000000000000000000000000000000000000000 6.0.0
+e5bea2a22f5042af86510ab283ef7f6a30276bfd stock_inventory_location-6.0.0
+13bc032ce45aa856f7c929da56974ff13ff3b7f3 4.6.0
+c5757a882fa6b0f30a7bca1a2e232c59dbe8e997 4.8.0
+7712e9bf2ae5372165f1208c7fcf74caa77733b8 5.0.0
+9cadbedb76593e2b1046c483ff57a5cecb380a41 5.2.0
+061bb098401a21770b1f7d8491805fb2516d50b2 5.4.0
+35e0bc476e8e103ff133ab5797eed1d3979289b2 5.6.0
+a767051ad55af5437c1df4473f0d16251941bc79 5.8.0
+2657bcf38993689626952562bc1999027d0262cd 6.0.0
+0000000000000000000000000000000000000000 4.6.0
+13bc032ce45aa856f7c929da56974ff13ff3b7f3 stock_location_move-4.6.0
+0000000000000000000000000000000000000000 4.8.0
+c5757a882fa6b0f30a7bca1a2e232c59dbe8e997 stock_location_move-4.8.0
+0000000000000000000000000000000000000000 5.0.0
+7712e9bf2ae5372165f1208c7fcf74caa77733b8 stock_location_move-5.0.0
+0000000000000000000000000000000000000000 5.2.0
+9cadbedb76593e2b1046c483ff57a5cecb380a41 stock_location_move-5.2.0
+0000000000000000000000000000000000000000 5.4.0
+061bb098401a21770b1f7d8491805fb2516d50b2 stock_location_move-5.4.0
+0000000000000000000000000000000000000000 5.6.0
+35e0bc476e8e103ff133ab5797eed1d3979289b2 stock_location_move-5.6.0
+0000000000000000000000000000000000000000 5.8.0
+a767051ad55af5437c1df4473f0d16251941bc79 stock_location_move-5.8.0
+0000000000000000000000000000000000000000 6.0.0
+2657bcf38993689626952562bc1999027d0262cd stock_location_move-6.0.0
+b23baaf1166b3f28f7aaa55b16d8f0b50e7121ed 1.2.0
+d9f7fda1212e61153ce87ef5a7ebba1aa906d9f2 1.4.0
+926f70090196ceefd74450f182a8a9b053282600 1.6.0
+9eada792e0e9eda93b8719d4ec92590f2ff3dacf 1.8.0
+8a47bba1738af17af3c6702cc29bd7a6e268dcfb 2.0.0
+c66ac42308b219dd773e9a4f2b76e344cf913cc8 2.2.0
+9a792408dcb3f2902a0c6da0c71db3ad1692dbd9 2.4.0
+5d56a013f279fc4b31e9a73a6e5b4bb8991e25ef 2.6.0
+d0821f9f197cab6cbeb260b6c230e301def3daea 2.8.0
+0a8b7366a62a97d33c7cdc1b6938fccd4ad4104e 3.0.0
+7e56cda8de6b9e0384104bd68e200f467af001bf 3.2.0
+9befac1e3076f141972816af2f6fe8782125df85 3.4.0
+db721dd4b8e93902f4e1173ff0d9f12f92260802 3.6.0
+5e18316f6f636a5474949d3bc5cb66c153e3da4b 3.8.0
+e052747c31f40fd68e13b0ec450c3ffc502e5e66 4.0.0
+13d25c22e30033991a1aa9233b7ecce233ebc6ea 4.2.0
+8eac3ea1d980cb34c5bda3255bc764ec079fe60f 4.4.0
+809b3a45222dbc93dc22785adbb184705b24502a 4.6.0
+ec2b60415d119b35cf61b75247abaf5bb67a70b1 4.8.0
+907c38d009f3853cddeb21db3e569e681e60a82f 5.0.0
+777c5d8d0ccec1c866450b98973009de6a5e38a5 5.2.0
+4abcc1fb1039f1cde5ba1277efc6edb713d427af 5.4.0
+93240765ffba8fb10f1fcc8699db8c9f5d827e36 5.6.0
+119bb6dcafeffabbe80a5b9fcb872071e0f3c784 5.8.0
+1a8e026150a29d49f552c112f9795b1f2ad035b6 6.0.0
+0000000000000000000000000000000000000000 1.2.0
+b23baaf1166b3f28f7aaa55b16d8f0b50e7121ed stock_location_sequence-1.2.0
+0000000000000000000000000000000000000000 1.4.0
+d9f7fda1212e61153ce87ef5a7ebba1aa906d9f2 stock_location_sequence-1.4.0
+0000000000000000000000000000000000000000 1.6.0
+926f70090196ceefd74450f182a8a9b053282600 stock_location_sequence-1.6.0
+0000000000000000000000000000000000000000 1.8.0
+9eada792e0e9eda93b8719d4ec92590f2ff3dacf stock_location_sequence-1.8.0
+0000000000000000000000000000000000000000 2.0.0
+8a47bba1738af17af3c6702cc29bd7a6e268dcfb stock_location_sequence-2.0.0
+0000000000000000000000000000000000000000 2.2.0
+c66ac42308b219dd773e9a4f2b76e344cf913cc8 stock_location_sequence-2.2.0
+0000000000000000000000000000000000000000 2.4.0
+9a792408dcb3f2902a0c6da0c71db3ad1692dbd9 stock_location_sequence-2.4.0
+0000000000000000000000000000000000000000 2.6.0
+5d56a013f279fc4b31e9a73a6e5b4bb8991e25ef stock_location_sequence-2.6.0
+0000000000000000000000000000000000000000 2.8.0
+d0821f9f197cab6cbeb260b6c230e301def3daea stock_location_sequence-2.8.0
+0000000000000000000000000000000000000000 3.0.0
+0a8b7366a62a97d33c7cdc1b6938fccd4ad4104e stock_location_sequence-3.0.0
+0000000000000000000000000000000000000000 3.2.0
+7e56cda8de6b9e0384104bd68e200f467af001bf stock_location_sequence-3.2.0
+0000000000000000000000000000000000000000 3.4.0
+9befac1e3076f141972816af2f6fe8782125df85 stock_location_sequence-3.4.0
+0000000000000000000000000000000000000000 3.6.0
+db721dd4b8e93902f4e1173ff0d9f12f92260802 stock_location_sequence-3.6.0
+0000000000000000000000000000000000000000 3.8.0
+5e18316f6f636a5474949d3bc5cb66c153e3da4b stock_location_sequence-3.8.0
+0000000000000000000000000000000000000000 4.0.0
+e052747c31f40fd68e13b0ec450c3ffc502e5e66 stock_location_sequence-4.0.0
+0000000000000000000000000000000000000000 4.2.0
+13d25c22e30033991a1aa9233b7ecce233ebc6ea stock_location_sequence-4.2.0
+0000000000000000000000000000000000000000 4.4.0
+8eac3ea1d980cb34c5bda3255bc764ec079fe60f stock_location_sequence-4.4.0
+0000000000000000000000000000000000000000 4.6.0
+809b3a45222dbc93dc22785adbb184705b24502a stock_location_sequence-4.6.0
+0000000000000000000000000000000000000000 4.8.0
+ec2b60415d119b35cf61b75247abaf5bb67a70b1 stock_location_sequence-4.8.0
+0000000000000000000000000000000000000000 5.0.0
+907c38d009f3853cddeb21db3e569e681e60a82f stock_location_sequence-5.0.0
+0000000000000000000000000000000000000000 5.2.0
+777c5d8d0ccec1c866450b98973009de6a5e38a5 stock_location_sequence-5.2.0
+0000000000000000000000000000000000000000 5.4.0
+4abcc1fb1039f1cde5ba1277efc6edb713d427af stock_location_sequence-5.4.0
+0000000000000000000000000000000000000000 5.6.0
+93240765ffba8fb10f1fcc8699db8c9f5d827e36 stock_location_sequence-5.6.0
+0000000000000000000000000000000000000000 5.8.0
+119bb6dcafeffabbe80a5b9fcb872071e0f3c784 stock_location_sequence-5.8.0
+0000000000000000000000000000000000000000 6.0.0
+1a8e026150a29d49f552c112f9795b1f2ad035b6 stock_location_sequence-6.0.0
+f3daa4fc57a55e3f24f9430134a7db46b430d24a 2.4.0
+9bfebffac7ac532b86f50e1d93fc3b41d3921d77 2.6.0
+ac0210ea97cffd9aa37a5af53160243fbe0d7f56 2.8.0
+a358b629d083fbbe619614fcf3f26efaa21ff057 3.0.0
+2419d87bd5c29430664571dbd3376b556dc8ed83 3.2.0
+f72cb08228d56df2be724b462e5d9497dc700285 3.4.0
+8f644f057381856d5ab1834f34a981ff1b65fba3 3.6.0
+2918a530bb167f85c238e2dafe30ee6cf942ea70 3.8.0
+571f01b197f02ef5842c30e25e66515c9d1fa0c4 4.0.0
+e79c0e4b00b8455533c2992369e0ad78ce2fb4e0 4.2.0
+c5f89116f21e00e008b9dc515e82a291bc4a37a9 4.4.0
+e966c63314da859ecacd7e40356201e74d3bd715 4.6.0
+d6e8ca4264c50efb67ae4b0b4c2c7b6982612894 4.8.0
+a5722d02c1c5a5ccabf997d980a86bb6bd0160db 5.0.0
+0170b28fa1c9581bf0831a501469df19a3f7b302 5.2.0
+c77c42846d957aa443927c3eb3e0e489eabe3eeb 5.4.0
+4c6125ae5f16e2ded590b4a84c17ae9ab6f0e826 5.6.0
+6ccbea8c304a744066cefa9637aed2bb21ca5149 5.8.0
+2e05cf05ee95b78ad35fc10eeb51fc35a6b6bc9f 6.0.0
+0000000000000000000000000000000000000000 2.4.0
+f3daa4fc57a55e3f24f9430134a7db46b430d24a stock_lot-2.4.0
+0000000000000000000000000000000000000000 2.6.0
+9bfebffac7ac532b86f50e1d93fc3b41d3921d77 stock_lot-2.6.0
+0000000000000000000000000000000000000000 2.8.0
+ac0210ea97cffd9aa37a5af53160243fbe0d7f56 stock_lot-2.8.0
+0000000000000000000000000000000000000000 3.0.0
+a358b629d083fbbe619614fcf3f26efaa21ff057 stock_lot-3.0.0
+0000000000000000000000000000000000000000 3.2.0
+2419d87bd5c29430664571dbd3376b556dc8ed83 stock_lot-3.2.0
+0000000000000000000000000000000000000000 3.4.0
+f72cb08228d56df2be724b462e5d9497dc700285 stock_lot-3.4.0
+0000000000000000000000000000000000000000 3.6.0
+8f644f057381856d5ab1834f34a981ff1b65fba3 stock_lot-3.6.0
+0000000000000000000000000000000000000000 3.8.0
+2918a530bb167f85c238e2dafe30ee6cf942ea70 stock_lot-3.8.0
+0000000000000000000000000000000000000000 4.0.0
+571f01b197f02ef5842c30e25e66515c9d1fa0c4 stock_lot-4.0.0
+0000000000000000000000000000000000000000 4.2.0
+e79c0e4b00b8455533c2992369e0ad78ce2fb4e0 stock_lot-4.2.0
+0000000000000000000000000000000000000000 4.4.0
+c5f89116f21e00e008b9dc515e82a291bc4a37a9 stock_lot-4.4.0
+0000000000000000000000000000000000000000 4.6.0
+e966c63314da859ecacd7e40356201e74d3bd715 stock_lot-4.6.0
+0000000000000000000000000000000000000000 4.8.0
+d6e8ca4264c50efb67ae4b0b4c2c7b6982612894 stock_lot-4.8.0
+0000000000000000000000000000000000000000 5.0.0
+a5722d02c1c5a5ccabf997d980a86bb6bd0160db stock_lot-5.0.0
+0000000000000000000000000000000000000000 5.2.0
+0170b28fa1c9581bf0831a501469df19a3f7b302 stock_lot-5.2.0
+0000000000000000000000000000000000000000 5.4.0
+c77c42846d957aa443927c3eb3e0e489eabe3eeb stock_lot-5.4.0
+0000000000000000000000000000000000000000 5.6.0
+4c6125ae5f16e2ded590b4a84c17ae9ab6f0e826 stock_lot-5.6.0
+0000000000000000000000000000000000000000 5.8.0
+6ccbea8c304a744066cefa9637aed2bb21ca5149 stock_lot-5.8.0
+0000000000000000000000000000000000000000 6.0.0
+2e05cf05ee95b78ad35fc10eeb51fc35a6b6bc9f stock_lot-6.0.0
+f319ec0ab83850bfbc4dbf0c1e3f88923d4c6ba4 3.6.0
+086daa04833949d995472901fff5f58a5ad1ea7c 3.8.0
+f13eceee4f070ddd92d5bf3b4e37723989b25de5 4.0.0
+69a63fa91de5824e6c69c5283b7cc4a560faabde 4.2.0
+abbc7eac4114aeb9d1ec6aa43d7744d4df991431 4.4.0
+b8d5d4e6d18e736b29350b41559f86e1b552c496 4.6.0
+fea52fe8ed7b3233a42ceb4b4185d7db3adf359f 4.8.0
+7e17d7d28b28cf0e6be49af141ba094b802f9b0d 5.0.0
+9d45f2cfdb3983e8fe676177066f8d37f5a8d18d 5.2.0
+19f381cd840ef2196eddcbc954937b3f2b3db661 5.4.0
+d977882bd686aabe9cf7a56b08710358fb8d9960 5.6.0
+78740da434731b98192332919c0cad73f0553da6 5.8.0
+226bd337f659e121a6be8f9c01e5341c1d366a94 6.0.0
+0000000000000000000000000000000000000000 3.6.0
+f319ec0ab83850bfbc4dbf0c1e3f88923d4c6ba4 stock_lot_sled-3.6.0
+0000000000000000000000000000000000000000 3.8.0
+086daa04833949d995472901fff5f58a5ad1ea7c stock_lot_sled-3.8.0
+0000000000000000000000000000000000000000 4.0.0
+f13eceee4f070ddd92d5bf3b4e37723989b25de5 stock_lot_sled-4.0.0
+0000000000000000000000000000000000000000 4.2.0
+69a63fa91de5824e6c69c5283b7cc4a560faabde stock_lot_sled-4.2.0
+0000000000000000000000000000000000000000 4.4.0
+abbc7eac4114aeb9d1ec6aa43d7744d4df991431 stock_lot_sled-4.4.0
+0000000000000000000000000000000000000000 4.6.0
+b8d5d4e6d18e736b29350b41559f86e1b552c496 stock_lot_sled-4.6.0
+0000000000000000000000000000000000000000 4.8.0
+fea52fe8ed7b3233a42ceb4b4185d7db3adf359f stock_lot_sled-4.8.0
+0000000000000000000000000000000000000000 5.0.0
+7e17d7d28b28cf0e6be49af141ba094b802f9b0d stock_lot_sled-5.0.0
+0000000000000000000000000000000000000000 5.2.0
+9d45f2cfdb3983e8fe676177066f8d37f5a8d18d stock_lot_sled-5.2.0
+0000000000000000000000000000000000000000 5.4.0
+19f381cd840ef2196eddcbc954937b3f2b3db661 stock_lot_sled-5.4.0
+0000000000000000000000000000000000000000 5.6.0
+d977882bd686aabe9cf7a56b08710358fb8d9960 stock_lot_sled-5.6.0
+0000000000000000000000000000000000000000 5.8.0
+78740da434731b98192332919c0cad73f0553da6 stock_lot_sled-5.8.0
+0000000000000000000000000000000000000000 6.0.0
+226bd337f659e121a6be8f9c01e5341c1d366a94 stock_lot_sled-6.0.0
+7841e7ccbb5af34441c92e9b24caae751ca71194 5.0.0
+accb9a9e2eecea2c07521b46f81d22bbb13c6efc 5.2.0
+52a0d3ff69fa733416ddb698e73c99a17309ffe1 5.4.0
+fb5d9bead5daa2058a5d59f3ef18de584202b4d6 5.6.0
+703868576e2ab157fe5aadae42c7e6931098aa40 5.8.0
+cc2dd321d99fe14fe9251051eee46a6903c57bc4 6.0.0
+9a158d468bdaf917b6345ea9a6722f524bdb5274 6.0.1
+0000000000000000000000000000000000000000 5.0.0
+7841e7ccbb5af34441c92e9b24caae751ca71194 stock_lot_unit-5.0.0
+0000000000000000000000000000000000000000 5.2.0
+accb9a9e2eecea2c07521b46f81d22bbb13c6efc stock_lot_unit-5.2.0
+0000000000000000000000000000000000000000 5.4.0
+52a0d3ff69fa733416ddb698e73c99a17309ffe1 stock_lot_unit-5.4.0
+0000000000000000000000000000000000000000 5.6.0
+fb5d9bead5daa2058a5d59f3ef18de584202b4d6 stock_lot_unit-5.6.0
+0000000000000000000000000000000000000000 5.8.0
+703868576e2ab157fe5aadae42c7e6931098aa40 stock_lot_unit-5.8.0
+0000000000000000000000000000000000000000 6.0.0
+cc2dd321d99fe14fe9251051eee46a6903c57bc4 stock_lot_unit-6.0.0
+0000000000000000000000000000000000000000 6.0.1
+9a158d468bdaf917b6345ea9a6722f524bdb5274 stock_lot_unit-6.0.1
+2d95440ef29e4e6ae8bf7c513b4cced6038974ad 3.2.0
+5886452ff995b50071f07e05f519b2e4bb0526c9 3.4.0
+ed428643d547655cf08fd33ac6700bedc75308c6 3.6.0
+600f0b784df713a34b9c770622bc8dfd8a2a8c78 3.8.0
+e46734b4ac890bb0bf34bf08e261a6390fb7c3a8 4.0.0
+abf3fe276ee219d027e78dc72ec570add038899b 4.2.0
+e3764726bbbe93305d2e3e8bb20746cd0b33ae4f 4.4.0
+876b678e056f2ba5ae6108b10182c8e3b72184d1 4.6.0
+85793ff5a50a432be0fb45012478972b4c60e056 4.8.0
+6a0a6190312f634e8b64b6997fb1b37129532fbe 5.0.0
+d761efb2ac196534d0ff715146bd9b727c20bd40 5.2.0
+25ebab75a5457e2e00ed334edae56d5f5991a603 5.4.0
+3d96d408e7cb3cc3552ca3b99356990b889f78f6 5.6.0
+28f4106d4fc02d7c6d7f8735a58422031e3e3e1a 5.8.0
+a4cd8b29bbafd25dcf991704353b57b10e383f59 6.0.0
+30c33b19afd38febbe42c02c95b31b56155dc0e3 6.0.1
+0000000000000000000000000000000000000000 3.2.0
+2d95440ef29e4e6ae8bf7c513b4cced6038974ad stock_package-3.2.0
+0000000000000000000000000000000000000000 3.4.0
+5886452ff995b50071f07e05f519b2e4bb0526c9 stock_package-3.4.0
+0000000000000000000000000000000000000000 3.6.0
+ed428643d547655cf08fd33ac6700bedc75308c6 stock_package-3.6.0
+0000000000000000000000000000000000000000 3.8.0
+600f0b784df713a34b9c770622bc8dfd8a2a8c78 stock_package-3.8.0
+0000000000000000000000000000000000000000 4.0.0
+e46734b4ac890bb0bf34bf08e261a6390fb7c3a8 stock_package-4.0.0
+0000000000000000000000000000000000000000 4.2.0
+abf3fe276ee219d027e78dc72ec570add038899b stock_package-4.2.0
+0000000000000000000000000000000000000000 4.4.0
+e3764726bbbe93305d2e3e8bb20746cd0b33ae4f stock_package-4.4.0
+0000000000000000000000000000000000000000 4.6.0
+876b678e056f2ba5ae6108b10182c8e3b72184d1 stock_package-4.6.0
+0000000000000000000000000000000000000000 4.8.0
+85793ff5a50a432be0fb45012478972b4c60e056 stock_package-4.8.0
+0000000000000000000000000000000000000000 5.0.0
+6a0a6190312f634e8b64b6997fb1b37129532fbe stock_package-5.0.0
+0000000000000000000000000000000000000000 5.2.0
+d761efb2ac196534d0ff715146bd9b727c20bd40 stock_package-5.2.0
+0000000000000000000000000000000000000000 5.4.0
+25ebab75a5457e2e00ed334edae56d5f5991a603 stock_package-5.4.0
+0000000000000000000000000000000000000000 5.6.0
+3d96d408e7cb3cc3552ca3b99356990b889f78f6 stock_package-5.6.0
+0000000000000000000000000000000000000000 5.8.0
+28f4106d4fc02d7c6d7f8735a58422031e3e3e1a stock_package-5.8.0
+0000000000000000000000000000000000000000 6.0.0
+a4cd8b29bbafd25dcf991704353b57b10e383f59 stock_package-6.0.0
+0000000000000000000000000000000000000000 6.0.1
+30c33b19afd38febbe42c02c95b31b56155dc0e3 stock_package-6.0.1
+5352520b9e2d793f180c7338973c93eb2756c11a 4.2.0
+48eda81a2c3e4697d12b3ecd43d20cdffdf7f95d 4.4.0
+72b19785f7aefa42c43dbf7430b70393abfafdac 4.6.0
+a3fda5824dc2e831806bb3e54c4b554e28707d66 4.8.0
+c91e82164a66fa45b1e5f5c18f4eecb9666ff9f9 5.0.0
+1d75d725c02de30176404a116395f5cea1a8b15d 5.2.0
+f774a1f78ac021fd0dbe822bde61f5300f1ee672 5.4.0
+e9c1c8ee8d12182e14e0b7fda103035e43d957ef 5.6.0
+879357ee52cac15348178e8cba439074c7fcc206 5.8.0
+ba57075f760026b8388fb77bd0cc053601bd04b0 6.0.0
+09059a2547a75404f58b275ce0fd3918623bc1a7 6.0.1
+2b5ccfa32a5b93ce4f5ac2140fb71f7303b83f09 6.0.2
+4d29e0810a25db6762a820f6cb5e111493294a91 6.0.3
+4b3730e93b5f8671ef5dcf2f6cfa671bdad8dbcc 6.0.4
+0000000000000000000000000000000000000000 4.2.0
+5352520b9e2d793f180c7338973c93eb2756c11a stock_package_shipping_dpd-4.2.0
+0000000000000000000000000000000000000000 4.4.0
+48eda81a2c3e4697d12b3ecd43d20cdffdf7f95d stock_package_shipping_dpd-4.4.0
+0000000000000000000000000000000000000000 4.6.0
+72b19785f7aefa42c43dbf7430b70393abfafdac stock_package_shipping_dpd-4.6.0
+0000000000000000000000000000000000000000 4.8.0
+a3fda5824dc2e831806bb3e54c4b554e28707d66 stock_package_shipping_dpd-4.8.0
+0000000000000000000000000000000000000000 5.0.0
+c91e82164a66fa45b1e5f5c18f4eecb9666ff9f9 stock_package_shipping_dpd-5.0.0
+0000000000000000000000000000000000000000 5.2.0
+1d75d725c02de30176404a116395f5cea1a8b15d stock_package_shipping_dpd-5.2.0
+0000000000000000000000000000000000000000 5.4.0
+f774a1f78ac021fd0dbe822bde61f5300f1ee672 stock_package_shipping_dpd-5.4.0
+0000000000000000000000000000000000000000 5.6.0
+e9c1c8ee8d12182e14e0b7fda103035e43d957ef stock_package_shipping_dpd-5.6.0
+0000000000000000000000000000000000000000 5.8.0
+879357ee52cac15348178e8cba439074c7fcc206 stock_package_shipping_dpd-5.8.0
+0000000000000000000000000000000000000000 6.0.0
+ba57075f760026b8388fb77bd0cc053601bd04b0 stock_package_shipping_dpd-6.0.0
+0000000000000000000000000000000000000000 6.0.1
+09059a2547a75404f58b275ce0fd3918623bc1a7 stock_package_shipping_dpd-6.0.1
+0000000000000000000000000000000000000000 6.0.2
+2b5ccfa32a5b93ce4f5ac2140fb71f7303b83f09 stock_package_shipping_dpd-6.0.2
+0000000000000000000000000000000000000000 6.0.3
+4d29e0810a25db6762a820f6cb5e111493294a91 stock_package_shipping_dpd-6.0.3
+0000000000000000000000000000000000000000 6.0.4
+4b3730e93b5f8671ef5dcf2f6cfa671bdad8dbcc stock_package_shipping_dpd-6.0.4
+6d6ce7193b8fe468b131732a63d49ad51282feb4 4.2.0
+c92db1ac0cb7f23ec59451a1559ae587489e51cf 4.4.0
+896bda88b3e4e06011cc8274248a747c98ed5d8a 4.6.0
+12732a7de25ada586b597f5ceb95a61aca85c982 4.8.0
+d84a549ca4ce55c8b6f2c55e7b387111fe5d31f5 5.0.0
+dfa6486ca4ca8a505a1103a1966f252bfb76b0d5 5.2.0
+fc827a8182eeabea27b4107630814f58615a5093 5.4.0
+1e8a3c6dcb32eebb16c0135a83c6d24a178809a0 5.6.0
+4afae51825024fa5bdda4845018c68076e37f985 5.8.0
+4d757048f5cf112af97613ed3cd8c1d9747d5932 6.0.0
+0000000000000000000000000000000000000000 4.2.0
+6d6ce7193b8fe468b131732a63d49ad51282feb4 stock_package_shipping-4.2.0
+0000000000000000000000000000000000000000 4.4.0
+c92db1ac0cb7f23ec59451a1559ae587489e51cf stock_package_shipping-4.4.0
+0000000000000000000000000000000000000000 4.6.0
+896bda88b3e4e06011cc8274248a747c98ed5d8a stock_package_shipping-4.6.0
+0000000000000000000000000000000000000000 4.8.0
+12732a7de25ada586b597f5ceb95a61aca85c982 stock_package_shipping-4.8.0
+0000000000000000000000000000000000000000 5.0.0
+d84a549ca4ce55c8b6f2c55e7b387111fe5d31f5 stock_package_shipping-5.0.0
+0000000000000000000000000000000000000000 5.2.0
+dfa6486ca4ca8a505a1103a1966f252bfb76b0d5 stock_package_shipping-5.2.0
+0000000000000000000000000000000000000000 5.4.0
+fc827a8182eeabea27b4107630814f58615a5093 stock_package_shipping-5.4.0
+0000000000000000000000000000000000000000 5.6.0
+1e8a3c6dcb32eebb16c0135a83c6d24a178809a0 stock_package_shipping-5.6.0
+0000000000000000000000000000000000000000 5.8.0
+4afae51825024fa5bdda4845018c68076e37f985 stock_package_shipping-5.8.0
+0000000000000000000000000000000000000000 6.0.0
+4d757048f5cf112af97613ed3cd8c1d9747d5932 stock_package_shipping-6.0.0
+14873b27f47664b486aa92a3318081ee86d5cca7 4.2.0
+cd53d5490f327e9e13479e7d1540b47c111f4a23 4.4.0
+ca475eeb8c9c520c70346d799d444bb7225bd55b 4.6.0
+4437ebda9bc7470b4b98ee42370d12a6f942b1c3 4.8.0
+3e4c032cdadea2e021de270022e212eadb23c9d8 5.0.0
+4cde26523853d124058cc72a0bacc483c388c750 5.2.0
+84fdbd3bf2bccebc09b4216e01d9b93193d14daf 5.4.0
+7e0f69141e15402340c207ebefbb2e43083cf1ad 5.6.0
+c338db57b720be61b239b5f39f0080d062ee131e 5.8.0
+7c788a324e4e275dda49e425ab502fe792cc5bec 6.0.0
+c23f35d0e7f71821852b6243c3ad80116587a328 6.0.1
+f20add511e11bdfc0d27e65270e965111e91a831 6.0.2
+b54ffaf40ede8f5093dd3b31fcad9b7ef974fd92 6.0.3
+0000000000000000000000000000000000000000 4.2.0
+14873b27f47664b486aa92a3318081ee86d5cca7 stock_package_shipping_ups-4.2.0
+0000000000000000000000000000000000000000 4.4.0
+cd53d5490f327e9e13479e7d1540b47c111f4a23 stock_package_shipping_ups-4.4.0
+0000000000000000000000000000000000000000 4.6.0
+ca475eeb8c9c520c70346d799d444bb7225bd55b stock_package_shipping_ups-4.6.0
+0000000000000000000000000000000000000000 4.8.0
+4437ebda9bc7470b4b98ee42370d12a6f942b1c3 stock_package_shipping_ups-4.8.0
+0000000000000000000000000000000000000000 5.0.0
+3e4c032cdadea2e021de270022e212eadb23c9d8 stock_package_shipping_ups-5.0.0
+0000000000000000000000000000000000000000 5.2.0
+4cde26523853d124058cc72a0bacc483c388c750 stock_package_shipping_ups-5.2.0
+0000000000000000000000000000000000000000 5.4.0
+84fdbd3bf2bccebc09b4216e01d9b93193d14daf stock_package_shipping_ups-5.4.0
+0000000000000000000000000000000000000000 5.6.0
+7e0f69141e15402340c207ebefbb2e43083cf1ad stock_package_shipping_ups-5.6.0
+0000000000000000000000000000000000000000 5.8.0
+c338db57b720be61b239b5f39f0080d062ee131e stock_package_shipping_ups-5.8.0
+0000000000000000000000000000000000000000 6.0.0
+7c788a324e4e275dda49e425ab502fe792cc5bec stock_package_shipping_ups-6.0.0
+0000000000000000000000000000000000000000 6.0.1
+c23f35d0e7f71821852b6243c3ad80116587a328 stock_package_shipping_ups-6.0.1
+0000000000000000000000000000000000000000 6.0.2
+f20add511e11bdfc0d27e65270e965111e91a831 stock_package_shipping_ups-6.0.2
+0000000000000000000000000000000000000000 6.0.3
+b54ffaf40ede8f5093dd3b31fcad9b7ef974fd92 stock_package_shipping_ups-6.0.3
+2ea983f6240bd88f6b9abf2e4b7b857ce4bdf264 1.2.0
+ec24bd0ab6daa217e29753b68f9ae242f80062b7 1.4.0
+c560e70b18afce2d136cfbcc9f1ebf5756761882 1.6.0
+ab792b3468742c3a1f777165f8bdde4ebc96c1fd 1.8.0
+67d1514d90ff98a12865eaa025269914b15082b8 2.0.0
+53b4739836b0d10620038cce567d4d935f1a1363 2.2.0
+1922c46f7101f9397889c59c908bdd1e4489f70b 2.4.0
+b8e5502b8bd42741c92695a6540fade63bffbd43 2.6.0
+010a427751135ecb84ce3d7c13791ecf37edde23 2.8.0
+0dc520d1c9eeb9e242d5fb61fe2263ac28f5903f 3.0.0
+40cd13193206cc64a30dd7776fa954af1bceded9 3.2.0
+85c6a4a6a1d99d5c99228952115f1a57289856ba 3.4.0
+d2f9dbbcab386708468c523572888c7649e32851 3.6.0
+c540f2937c11c85591041fc8c2c4afd0ff53228f 3.8.0
+e8b3d84c1317eacc7b6b44b53b8ae70859b7977b 4.0.0
+b5442c0b44dc60bb6486bc308636bd37d1f5ff88 4.2.0
+ef4be934e362ed9336b2242ef1f3b799e724dfea 4.4.0
+3d5ef5ae2d89470391e2f59ae298312c670a93fa 4.6.0
+a41145e1e25e6348642c3fef1fb37d68142afc57 4.8.0
+1ea4345152b56228edf41029cf33318c5090cf29 5.0.0
+c10048ef95077f6c48ec1a3dd2cda9b29a55d9ef 5.2.0
+361b17eb46d869242083f3b2d269bc584bc17579 5.4.0
+a02f09f5837245a86c17ca480d069694b85d8214 5.6.0
+dfea61949c69f6013213cc92528fcfbc62e0a0f6 5.8.0
+25101e7ec2d7d8322005ae0e70f3d78256223ebe 6.0.0
+0000000000000000000000000000000000000000 1.2.0
+2ea983f6240bd88f6b9abf2e4b7b857ce4bdf264 stock_product_location-1.2.0
+0000000000000000000000000000000000000000 1.4.0
+ec24bd0ab6daa217e29753b68f9ae242f80062b7 stock_product_location-1.4.0
+0000000000000000000000000000000000000000 1.6.0
+c560e70b18afce2d136cfbcc9f1ebf5756761882 stock_product_location-1.6.0
+0000000000000000000000000000000000000000 1.8.0
+ab792b3468742c3a1f777165f8bdde4ebc96c1fd stock_product_location-1.8.0
+0000000000000000000000000000000000000000 2.0.0
+67d1514d90ff98a12865eaa025269914b15082b8 stock_product_location-2.0.0
+0000000000000000000000000000000000000000 2.2.0
+53b4739836b0d10620038cce567d4d935f1a1363 stock_product_location-2.2.0
+0000000000000000000000000000000000000000 2.4.0
+1922c46f7101f9397889c59c908bdd1e4489f70b stock_product_location-2.4.0
+0000000000000000000000000000000000000000 2.6.0
+b8e5502b8bd42741c92695a6540fade63bffbd43 stock_product_location-2.6.0
+0000000000000000000000000000000000000000 2.8.0
+010a427751135ecb84ce3d7c13791ecf37edde23 stock_product_location-2.8.0
+0000000000000000000000000000000000000000 3.0.0
+0dc520d1c9eeb9e242d5fb61fe2263ac28f5903f stock_product_location-3.0.0
+0000000000000000000000000000000000000000 3.2.0
+40cd13193206cc64a30dd7776fa954af1bceded9 stock_product_location-3.2.0
+0000000000000000000000000000000000000000 3.4.0
+85c6a4a6a1d99d5c99228952115f1a57289856ba stock_product_location-3.4.0
+0000000000000000000000000000000000000000 3.6.0
+d2f9dbbcab386708468c523572888c7649e32851 stock_product_location-3.6.0
+0000000000000000000000000000000000000000 3.8.0
+c540f2937c11c85591041fc8c2c4afd0ff53228f stock_product_location-3.8.0
+0000000000000000000000000000000000000000 4.0.0
+e8b3d84c1317eacc7b6b44b53b8ae70859b7977b stock_product_location-4.0.0
+0000000000000000000000000000000000000000 4.2.0
+b5442c0b44dc60bb6486bc308636bd37d1f5ff88 stock_product_location-4.2.0
+0000000000000000000000000000000000000000 4.4.0
+ef4be934e362ed9336b2242ef1f3b799e724dfea stock_product_location-4.4.0
+0000000000000000000000000000000000000000 4.6.0
+3d5ef5ae2d89470391e2f59ae298312c670a93fa stock_product_location-4.6.0
+0000000000000000000000000000000000000000 4.8.0
+a41145e1e25e6348642c3fef1fb37d68142afc57 stock_product_location-4.8.0
+0000000000000000000000000000000000000000 5.0.0
+1ea4345152b56228edf41029cf33318c5090cf29 stock_product_location-5.0.0
+0000000000000000000000000000000000000000 5.2.0
+c10048ef95077f6c48ec1a3dd2cda9b29a55d9ef stock_product_location-5.2.0
+0000000000000000000000000000000000000000 5.4.0
+361b17eb46d869242083f3b2d269bc584bc17579 stock_product_location-5.4.0
+0000000000000000000000000000000000000000 5.6.0
+a02f09f5837245a86c17ca480d069694b85d8214 stock_product_location-5.6.0
+0000000000000000000000000000000000000000 5.8.0
+dfea61949c69f6013213cc92528fcfbc62e0a0f6 stock_product_location-5.8.0
+0000000000000000000000000000000000000000 6.0.0
+25101e7ec2d7d8322005ae0e70f3d78256223ebe stock_product_location-6.0.0
+790271308b23a4856ade0be330ee59b5d69e7e75 6.0.0
+0d690f1867acdf63432b947bbe732d414e407bdd 6.0.1
+c72689d153af662a5cb470842229d8c0a77c7373 6.0.2
+0000000000000000000000000000000000000000 6.0.0
+790271308b23a4856ade0be330ee59b5d69e7e75 stock_quantity_early_planning-6.0.0
+0000000000000000000000000000000000000000 6.0.1
+0d690f1867acdf63432b947bbe732d414e407bdd stock_quantity_early_planning-6.0.1
+0000000000000000000000000000000000000000 6.0.2
+c72689d153af662a5cb470842229d8c0a77c7373 stock_quantity_early_planning-6.0.2
+8c7dc4a68eb44600a2e57f380b7fb39e7d4c9bd7 6.0.0
+97abbb580f15c3bfed62d2229bfba49506d8d5f5 6.0.1
+178ac9fc9cef1e3cf07a6e199a5279ab0f369c87 6.0.2
+37ac933fb3458735fed361ad53724bede8e0c050 6.0.3
+0000000000000000000000000000000000000000 6.0.0
+8c7dc4a68eb44600a2e57f380b7fb39e7d4c9bd7 stock_quantity_issue-6.0.0
+0000000000000000000000000000000000000000 6.0.1
+97abbb580f15c3bfed62d2229bfba49506d8d5f5 stock_quantity_issue-6.0.1
+0000000000000000000000000000000000000000 6.0.2
+178ac9fc9cef1e3cf07a6e199a5279ab0f369c87 stock_quantity_issue-6.0.2
+0000000000000000000000000000000000000000 6.0.3
+37ac933fb3458735fed361ad53724bede8e0c050 stock_quantity_issue-6.0.3
+5e63bae17297495d2b63041be081e6bb8a69be2e 5.4.0
+83b28ed660ea0a02ba4cbaea22f495f2b3038615 5.6.0
+d7e3a25d15aa72096b29d985483e3caeb1fc4a43 5.8.0
+e55605b40ed71ec25e3079bb9c8b473bf879af58 6.0.0
+0000000000000000000000000000000000000000 5.4.0
+5e63bae17297495d2b63041be081e6bb8a69be2e stock_secondary_unit-5.4.0
+0000000000000000000000000000000000000000 5.6.0
+83b28ed660ea0a02ba4cbaea22f495f2b3038615 stock_secondary_unit-5.6.0
+0000000000000000000000000000000000000000 5.8.0
+d7e3a25d15aa72096b29d985483e3caeb1fc4a43 stock_secondary_unit-5.8.0
+0000000000000000000000000000000000000000 6.0.0
+e55605b40ed71ec25e3079bb9c8b473bf879af58 stock_secondary_unit-6.0.0
+e2d7e4135cc43091843e096a227cb69ded3b425a 6.0.0
+a98c4d2bb4d071c619d81c97184764d17f146898 6.0.1
+25169494e1beb8a9a36b6f4f0e02996db373046d 6.0.2
+0000000000000000000000000000000000000000 6.0.0
+e2d7e4135cc43091843e096a227cb69ded3b425a stock_shipment_cost-6.0.0
+0000000000000000000000000000000000000000 6.0.1
+a98c4d2bb4d071c619d81c97184764d17f146898 stock_shipment_cost-6.0.1
+0000000000000000000000000000000000000000 6.0.2
+25169494e1beb8a9a36b6f4f0e02996db373046d stock_shipment_cost-6.0.2
+b11be33a256e6e18c5e478831f2eecdb6cc55b56 4.4.0
+a8fa5ceb9134b53a902c8b860e8d910ab36267bd 4.6.0
+55fcd1727648050cba394388bb31ce0a70b74371 4.8.0
+568b1d3a4957cc66a2023eb3853555fd8b2b313a 5.0.0
+df952bd9a9312169cce9a3559a6808fd15ce729f 5.2.0
+135db8a22874fd324ea9ca94b2f47c5f9d1671f7 5.4.0
+8e1fe403bf2728fcd47d00652c985dbb86b4840c 5.6.0
+5900e412e77ddf587a4ce0d69cde3a3a1e4c5fa3 5.8.0
+5fa8a7ad24a9d9c5726f08a174c22696480bb3c9 6.0.0
+421aeff2cfde33cdaa789d706a265827407b325b 6.0.1
+0000000000000000000000000000000000000000 4.4.0
+b11be33a256e6e18c5e478831f2eecdb6cc55b56 stock_shipment_measurements-4.4.0
+0000000000000000000000000000000000000000 4.6.0
+a8fa5ceb9134b53a902c8b860e8d910ab36267bd stock_shipment_measurements-4.6.0
+0000000000000000000000000000000000000000 4.8.0
+55fcd1727648050cba394388bb31ce0a70b74371 stock_shipment_measurements-4.8.0
+0000000000000000000000000000000000000000 5.0.0
+568b1d3a4957cc66a2023eb3853555fd8b2b313a stock_shipment_measurements-5.0.0
+0000000000000000000000000000000000000000 5.2.0
+df952bd9a9312169cce9a3559a6808fd15ce729f stock_shipment_measurements-5.2.0
+0000000000000000000000000000000000000000 5.4.0
+135db8a22874fd324ea9ca94b2f47c5f9d1671f7 stock_shipment_measurements-5.4.0
+0000000000000000000000000000000000000000 5.6.0
+8e1fe403bf2728fcd47d00652c985dbb86b4840c stock_shipment_measurements-5.6.0
+0000000000000000000000000000000000000000 5.8.0
+5900e412e77ddf587a4ce0d69cde3a3a1e4c5fa3 stock_shipment_measurements-5.8.0
+0000000000000000000000000000000000000000 6.0.0
+5fa8a7ad24a9d9c5726f08a174c22696480bb3c9 stock_shipment_measurements-6.0.0
+0000000000000000000000000000000000000000 6.0.1
+421aeff2cfde33cdaa789d706a265827407b325b stock_shipment_measurements-6.0.1
+28368573eba198c3524a0ef44c5d1318a71a25b6 2.4.0
+04196701d026d86eb57f91c6e38cddecf257d63f 2.6.0
+099647a527ee5b315f03850b900f656bd10d759f 2.8.0
+06bc610a6f9a26c456050fd61c273bd012a21f04 3.0.0
+e793ef3ca432a0e409aa49bc846bd2c572f3a5ee 3.2.0
+99999433d0e31e2b6f1eb2f589844e835d7b2953 3.4.0
+4c27a1322efba12ae02f1299e7989460ffe8af09 3.6.0
+cca693a2c563e30e5f10fefeca30c49101eb3495 3.8.0
+d961a4a36143eae4ff23dc2c8f7b49c83a8e6b9a 4.0.0
+10eb3100612be23bcac20f5c1036e58aaef76ed7 4.2.0
+d73f07a6109ae14f711d9ac9efe316a4595d3ffa 4.4.0
+893b0270a268be94790a68facfb745cc188d7a93 4.6.0
+eef7e68926b3f9c34ae5dc12bcd0ec6884918c09 4.8.0
+fd97dee9a2f6c5fc4c3ddd7298fdcf4c917ef5d9 5.0.0
+c07759c9b8d3b7733620789a050e7b6de418cf99 5.2.0
+160bbe8565f066ff2e7565fd8a9aceec2c3a0bed 5.4.0
+51f597bea6844c61a7dd658329a0e55e011e5327 5.6.0
+f13147d0020a5a42a7420db6678d2472ccf79bd3 5.8.0
+69d98ca60d7117c6ea722ea3d69fb7896859614b 6.0.0
+0000000000000000000000000000000000000000 2.4.0
+28368573eba198c3524a0ef44c5d1318a71a25b6 stock_split-2.4.0
+0000000000000000000000000000000000000000 2.6.0
+04196701d026d86eb57f91c6e38cddecf257d63f stock_split-2.6.0
+0000000000000000000000000000000000000000 2.8.0
+099647a527ee5b315f03850b900f656bd10d759f stock_split-2.8.0
+0000000000000000000000000000000000000000 3.0.0
+06bc610a6f9a26c456050fd61c273bd012a21f04 stock_split-3.0.0
+0000000000000000000000000000000000000000 3.2.0
+e793ef3ca432a0e409aa49bc846bd2c572f3a5ee stock_split-3.2.0
+0000000000000000000000000000000000000000 3.4.0
+99999433d0e31e2b6f1eb2f589844e835d7b2953 stock_split-3.4.0
+0000000000000000000000000000000000000000 3.6.0
+4c27a1322efba12ae02f1299e7989460ffe8af09 stock_split-3.6.0
+0000000000000000000000000000000000000000 3.8.0
+cca693a2c563e30e5f10fefeca30c49101eb3495 stock_split-3.8.0
+0000000000000000000000000000000000000000 4.0.0
+d961a4a36143eae4ff23dc2c8f7b49c83a8e6b9a stock_split-4.0.0
+0000000000000000000000000000000000000000 4.2.0
+10eb3100612be23bcac20f5c1036e58aaef76ed7 stock_split-4.2.0
+0000000000000000000000000000000000000000 4.4.0
+d73f07a6109ae14f711d9ac9efe316a4595d3ffa stock_split-4.4.0
+0000000000000000000000000000000000000000 4.6.0
+893b0270a268be94790a68facfb745cc188d7a93 stock_split-4.6.0
+0000000000000000000000000000000000000000 4.8.0
+eef7e68926b3f9c34ae5dc12bcd0ec6884918c09 stock_split-4.8.0
+0000000000000000000000000000000000000000 5.0.0
+fd97dee9a2f6c5fc4c3ddd7298fdcf4c917ef5d9 stock_split-5.0.0
+0000000000000000000000000000000000000000 5.2.0
+c07759c9b8d3b7733620789a050e7b6de418cf99 stock_split-5.2.0
+0000000000000000000000000000000000000000 5.4.0
+160bbe8565f066ff2e7565fd8a9aceec2c3a0bed stock_split-5.4.0
+0000000000000000000000000000000000000000 5.6.0
+51f597bea6844c61a7dd658329a0e55e011e5327 stock_split-5.6.0
+0000000000000000000000000000000000000000 5.8.0
+f13147d0020a5a42a7420db6678d2472ccf79bd3 stock_split-5.8.0
+0000000000000000000000000000000000000000 6.0.0
+69d98ca60d7117c6ea722ea3d69fb7896859614b stock_split-6.0.0
+2c1e13c8dd3396c1cd8e638111aac955de3ebc00 1.2.0
+5295eef207dc90e5cd3667c3883675e05726ef57 1.4.0
+2dfd00186d72076cf13379297e19c076884078d9 1.6.0
+056794451985f57a11e3cd7eba52f596ee9ec735 1.8.0
+bd08fecfa2cf0e7e3580c85090f62e1711fcfb88 2.0.0
+fe083045a79de94717fd58ecfa407f9662d05445 2.2.0
+926d98699fe8374bf591a6a21561cb51af46b3cb 2.4.0
+5169c4780f85a719ae92808f229620867a6756ca 2.6.0
+bc954fb77cc0651892cdfe10fb52fda48c238a98 2.8.0
+bb15a9f03156fea571be3216d502e5d4dc92439c 3.0.0
+7887dba041046609d589e9db4d3d6cf154d84865 3.2.0
+13c061d1e265b64a17a67ab05b2419ea17a10e7b 3.4.0
+8cd9280b5c4df641c5c969f020cec2d7d291082e 3.6.0
+3cd313fcfb1603d6ba340e254fc09ac6cfd1c420 3.8.0
+f36bf15e0049da995257277971560f979e534808 4.0.0
+a0f86fdcff3f7146eba32e4c06107cbadf7e52e5 4.2.0
+33bc557f7dde9e3ed40d6cc8e11b98eda63239a5 4.4.0
+32bafb5576e02e637109040302e14ff20f32e3a4 4.6.0
+1567de11c58a7052bba71f735826f332ece9ef35 4.8.0
+30611743f9cfe3c23bf8d252b971b011ea54ad53 5.0.0
+39be3138aa4546c555cf9ca5d800bb4ec3c3d7cb 5.2.0
+91f140df04060667e5faab3bf8d1095cab3f5528 5.4.0
+dbec1eac9dc4167e1307adbc62ef72bc7937d5ef 5.6.0
+00c0bad66396daf07d8c5f78dd8dae4ed0e421a4 5.8.0
+5a0e8f4810783920576928b183e3733693959da8 6.0.0
+0000000000000000000000000000000000000000 1.2.0
+2c1e13c8dd3396c1cd8e638111aac955de3ebc00 stock_supply_day-1.2.0
+0000000000000000000000000000000000000000 1.4.0
+5295eef207dc90e5cd3667c3883675e05726ef57 stock_supply_day-1.4.0
+0000000000000000000000000000000000000000 1.6.0
+2dfd00186d72076cf13379297e19c076884078d9 stock_supply_day-1.6.0
+0000000000000000000000000000000000000000 1.8.0
+056794451985f57a11e3cd7eba52f596ee9ec735 stock_supply_day-1.8.0
+0000000000000000000000000000000000000000 2.0.0
+bd08fecfa2cf0e7e3580c85090f62e1711fcfb88 stock_supply_day-2.0.0
+0000000000000000000000000000000000000000 2.2.0
+fe083045a79de94717fd58ecfa407f9662d05445 stock_supply_day-2.2.0
+0000000000000000000000000000000000000000 2.4.0
+926d98699fe8374bf591a6a21561cb51af46b3cb stock_supply_day-2.4.0
+0000000000000000000000000000000000000000 2.6.0
+5169c4780f85a719ae92808f229620867a6756ca stock_supply_day-2.6.0
+0000000000000000000000000000000000000000 2.8.0
+bc954fb77cc0651892cdfe10fb52fda48c238a98 stock_supply_day-2.8.0
+0000000000000000000000000000000000000000 3.0.0
+bb15a9f03156fea571be3216d502e5d4dc92439c stock_supply_day-3.0.0
+0000000000000000000000000000000000000000 3.2.0
+7887dba041046609d589e9db4d3d6cf154d84865 stock_supply_day-3.2.0
+0000000000000000000000000000000000000000 3.4.0
+13c061d1e265b64a17a67ab05b2419ea17a10e7b stock_supply_day-3.4.0
+0000000000000000000000000000000000000000 3.6.0
+8cd9280b5c4df641c5c969f020cec2d7d291082e stock_supply_day-3.6.0
+0000000000000000000000000000000000000000 3.8.0
+3cd313fcfb1603d6ba340e254fc09ac6cfd1c420 stock_supply_day-3.8.0
+0000000000000000000000000000000000000000 4.0.0
+f36bf15e0049da995257277971560f979e534808 stock_supply_day-4.0.0
+0000000000000000000000000000000000000000 4.2.0
+a0f86fdcff3f7146eba32e4c06107cbadf7e52e5 stock_supply_day-4.2.0
+0000000000000000000000000000000000000000 4.4.0
+33bc557f7dde9e3ed40d6cc8e11b98eda63239a5 stock_supply_day-4.4.0
+0000000000000000000000000000000000000000 4.6.0
+32bafb5576e02e637109040302e14ff20f32e3a4 stock_supply_day-4.6.0
+0000000000000000000000000000000000000000 4.8.0
+1567de11c58a7052bba71f735826f332ece9ef35 stock_supply_day-4.8.0
+0000000000000000000000000000000000000000 5.0.0
+30611743f9cfe3c23bf8d252b971b011ea54ad53 stock_supply_day-5.0.0
+0000000000000000000000000000000000000000 5.2.0
+39be3138aa4546c555cf9ca5d800bb4ec3c3d7cb stock_supply_day-5.2.0
+0000000000000000000000000000000000000000 5.4.0
+91f140df04060667e5faab3bf8d1095cab3f5528 stock_supply_day-5.4.0
+0000000000000000000000000000000000000000 5.6.0
+dbec1eac9dc4167e1307adbc62ef72bc7937d5ef stock_supply_day-5.6.0
+0000000000000000000000000000000000000000 5.8.0
+00c0bad66396daf07d8c5f78dd8dae4ed0e421a4 stock_supply_day-5.8.0
+0000000000000000000000000000000000000000 6.0.0
+5a0e8f4810783920576928b183e3733693959da8 stock_supply_day-6.0.0
+0834d76da22334e9c2b1e9d89ba50ac38bd3907f 2.2.0
+3c285f5f45031efbf9966541ace27b80fa45129d 2.4.0
+850476a6cbe95cf9bead5fdfaf094231908623ae 2.6.0
+3e0634468842969d6b2ee5e0f0c69a5aa75088e0 2.8.0
+3a26b77c883afebe780e59cd591c85f86248479c 3.0.0
+e6944d53c9579ff7d529f2fcadc021dc5a96d76c 3.2.0
+749efb5e0a4e86fb5ce3d5f181e73bc61ccd40e8 3.4.0
+370823db908f443f81bae475974c57af6281236b 3.6.0
+ba552f7b9b5297a6cde2372eebc523945d535c93 3.8.0
+0c88f450cac4029d9aaa81e94bc24457aec7c54a 4.0.0
+f0df25bfdb09fc1875f336bb870aa140a3247bcd 4.2.0
+afc2f1896f1c22b4591147b48f03743886e390f2 4.4.0
+5d6cdbfbb2b37451d4875ff9e789bf1350e75ab7 4.6.0
+df25bbcc27ede6b2a09868c7239732c3cd5e2c2a 4.8.0
+df42ccdd98a6fb0b4f55cc24e94f077fec1ffeb2 5.0.0
+d8a1fdd9db7f020437f2d5f02311ab29fe0cbab4 5.2.0
+c4c090246916fe2e00d67a26cb9859ea0a7106b5 5.4.0
+b89599b1cef0267371ce55e1b41cb1958d3312ba 5.6.0
+757b5e5484dd448afcbec95e87c21ecfad938b5f 5.8.0
+579edbea3863be427cfc1bb76cec03d061732d90 6.0.0
+0000000000000000000000000000000000000000 2.2.0
+0834d76da22334e9c2b1e9d89ba50ac38bd3907f stock_supply_forecast-2.2.0
+0000000000000000000000000000000000000000 2.4.0
+3c285f5f45031efbf9966541ace27b80fa45129d stock_supply_forecast-2.4.0
+0000000000000000000000000000000000000000 2.6.0
+850476a6cbe95cf9bead5fdfaf094231908623ae stock_supply_forecast-2.6.0
+0000000000000000000000000000000000000000 2.8.0
+3e0634468842969d6b2ee5e0f0c69a5aa75088e0 stock_supply_forecast-2.8.0
+0000000000000000000000000000000000000000 3.0.0
+3a26b77c883afebe780e59cd591c85f86248479c stock_supply_forecast-3.0.0
+0000000000000000000000000000000000000000 3.2.0
+e6944d53c9579ff7d529f2fcadc021dc5a96d76c stock_supply_forecast-3.2.0
+0000000000000000000000000000000000000000 3.4.0
+749efb5e0a4e86fb5ce3d5f181e73bc61ccd40e8 stock_supply_forecast-3.4.0
+0000000000000000000000000000000000000000 3.6.0
+370823db908f443f81bae475974c57af6281236b stock_supply_forecast-3.6.0
+0000000000000000000000000000000000000000 3.8.0
+ba552f7b9b5297a6cde2372eebc523945d535c93 stock_supply_forecast-3.8.0
+0000000000000000000000000000000000000000 4.0.0
+0c88f450cac4029d9aaa81e94bc24457aec7c54a stock_supply_forecast-4.0.0
+0000000000000000000000000000000000000000 4.2.0
+f0df25bfdb09fc1875f336bb870aa140a3247bcd stock_supply_forecast-4.2.0
+0000000000000000000000000000000000000000 4.4.0
+afc2f1896f1c22b4591147b48f03743886e390f2 stock_supply_forecast-4.4.0
+0000000000000000000000000000000000000000 4.6.0
+5d6cdbfbb2b37451d4875ff9e789bf1350e75ab7 stock_supply_forecast-4.6.0
+0000000000000000000000000000000000000000 4.8.0
+df25bbcc27ede6b2a09868c7239732c3cd5e2c2a stock_supply_forecast-4.8.0
+0000000000000000000000000000000000000000 5.0.0
+df42ccdd98a6fb0b4f55cc24e94f077fec1ffeb2 stock_supply_forecast-5.0.0
+0000000000000000000000000000000000000000 5.2.0
+d8a1fdd9db7f020437f2d5f02311ab29fe0cbab4 stock_supply_forecast-5.2.0
+0000000000000000000000000000000000000000 5.4.0
+c4c090246916fe2e00d67a26cb9859ea0a7106b5 stock_supply_forecast-5.4.0
+0000000000000000000000000000000000000000 5.6.0
+b89599b1cef0267371ce55e1b41cb1958d3312ba stock_supply_forecast-5.6.0
+0000000000000000000000000000000000000000 5.8.0
+757b5e5484dd448afcbec95e87c21ecfad938b5f stock_supply_forecast-5.8.0
+0000000000000000000000000000000000000000 6.0.0
+579edbea3863be427cfc1bb76cec03d061732d90 stock_supply_forecast-6.0.0
+bb2bb6af62f06218b0c8c689b24dd16f43307ca1 1.0.0
+5b0a8261963f167230f23a1b97c8b38519428143 1.2.0
+396ad2807deb26c6c353eb119dc50fd4fdcbb28a 1.4.0
+b44aa993ce24453fdb2362187e201a9375bcaa09 1.6.0
+f76056df60f581f803c7a7e4cec81397e4bbbb9c 1.8.0
+354dfc672c4b3ee2609a4051f6d8d431dd087231 2.0.0
+0881ad5cb82f3f00ec1eea276fa100a957691982 2.2.0
+5eb0f23e5774dddbf43cafe34bf527e1cd78d619 2.4.0
+6cd5f943826cb858bc34d20074bfd81b715114f8 2.6.0
+69f57817f6f0ed6ee0788cfab959a9321fcb45bb 2.8.0
+2ebe2636b804a2f7635d0af5b1030ced08de7a37 3.0.0
+c466a41ecc7586e898f0f4f2341c2e74b41ea816 3.2.0
+ddd6516306dd09e3049fb95ff94b4ce48687e200 3.4.0
+e122da9f78841562722820efbf4d64e4c390e8af 3.6.0
+5dcc2dd84f2145e78882af143cad5111c31f09b6 3.8.0
+c0a58dc8306d6885126b9613ad4b36e0a95b75f0 4.0.0
+afc53d87c88438c9c8e56629e994836844e32dbe 4.2.0
+7bbc6abdafa0642baf4095654151d70c9e5482c4 4.4.0
+99eaaa78814833e4d21e9d96e8c110f061f0edfa 4.6.0
+3b5c655f3c26831a505bd74493f108425d42bc62 4.8.0
+1c163e9beae826b96a72cd0d2c59bf4899241f82 5.0.0
+c139a716d188bf7fbf46574fa84a473133b8bee2 5.2.0
+9264fc010a2d2acb3128d9208977bd6b77fb5160 5.4.0
+2d2feece662966a006078304aa61b695447cef2f 5.6.0
+5756606b07d016272254398e15ae07873a72c230 5.8.0
+d527c60bfe0bc723779200d118179faa7f96ba4a 6.0.0
+7c13addfa07217e498c00f83117517b179d33f1b 6.0.1
+47e2a56c3eb9cd49ad460d35fc16dab4c334384b 6.0.2
+aeafed90f31c18b914b74cfd675f897dc41ca6cd 6.0.3
+0000000000000000000000000000000000000000 1.0.0
+bb2bb6af62f06218b0c8c689b24dd16f43307ca1 stock_supply-1.0.0
+0000000000000000000000000000000000000000 1.2.0
+5b0a8261963f167230f23a1b97c8b38519428143 stock_supply-1.2.0
+0000000000000000000000000000000000000000 1.4.0
+396ad2807deb26c6c353eb119dc50fd4fdcbb28a stock_supply-1.4.0
+0000000000000000000000000000000000000000 1.6.0
+b44aa993ce24453fdb2362187e201a9375bcaa09 stock_supply-1.6.0
+0000000000000000000000000000000000000000 1.8.0
+f76056df60f581f803c7a7e4cec81397e4bbbb9c stock_supply-1.8.0
+0000000000000000000000000000000000000000 2.0.0
+354dfc672c4b3ee2609a4051f6d8d431dd087231 stock_supply-2.0.0
+0000000000000000000000000000000000000000 2.2.0
+0881ad5cb82f3f00ec1eea276fa100a957691982 stock_supply-2.2.0
+0000000000000000000000000000000000000000 2.4.0
+5eb0f23e5774dddbf43cafe34bf527e1cd78d619 stock_supply-2.4.0
+0000000000000000000000000000000000000000 2.6.0
+6cd5f943826cb858bc34d20074bfd81b715114f8 stock_supply-2.6.0
+0000000000000000000000000000000000000000 2.8.0
+69f57817f6f0ed6ee0788cfab959a9321fcb45bb stock_supply-2.8.0
+0000000000000000000000000000000000000000 3.0.0
+2ebe2636b804a2f7635d0af5b1030ced08de7a37 stock_supply-3.0.0
+0000000000000000000000000000000000000000 3.2.0
+c466a41ecc7586e898f0f4f2341c2e74b41ea816 stock_supply-3.2.0
+0000000000000000000000000000000000000000 3.4.0
+ddd6516306dd09e3049fb95ff94b4ce48687e200 stock_supply-3.4.0
+0000000000000000000000000000000000000000 3.6.0
+e122da9f78841562722820efbf4d64e4c390e8af stock_supply-3.6.0
+0000000000000000000000000000000000000000 3.8.0
+5dcc2dd84f2145e78882af143cad5111c31f09b6 stock_supply-3.8.0
+0000000000000000000000000000000000000000 4.0.0
+c0a58dc8306d6885126b9613ad4b36e0a95b75f0 stock_supply-4.0.0
+0000000000000000000000000000000000000000 4.2.0
+afc53d87c88438c9c8e56629e994836844e32dbe stock_supply-4.2.0
+0000000000000000000000000000000000000000 4.4.0
+7bbc6abdafa0642baf4095654151d70c9e5482c4 stock_supply-4.4.0
+0000000000000000000000000000000000000000 4.6.0
+99eaaa78814833e4d21e9d96e8c110f061f0edfa stock_supply-4.6.0
+0000000000000000000000000000000000000000 4.8.0
+3b5c655f3c26831a505bd74493f108425d42bc62 stock_supply-4.8.0
+0000000000000000000000000000000000000000 5.0.0
+1c163e9beae826b96a72cd0d2c59bf4899241f82 stock_supply-5.0.0
+0000000000000000000000000000000000000000 5.2.0
+c139a716d188bf7fbf46574fa84a473133b8bee2 stock_supply-5.2.0
+0000000000000000000000000000000000000000 5.4.0
+9264fc010a2d2acb3128d9208977bd6b77fb5160 stock_supply-5.4.0
+0000000000000000000000000000000000000000 5.6.0
+2d2feece662966a006078304aa61b695447cef2f stock_supply-5.6.0
+0000000000000000000000000000000000000000 5.8.0
+5756606b07d016272254398e15ae07873a72c230 stock_supply-5.8.0
+0000000000000000000000000000000000000000 6.0.0
+d527c60bfe0bc723779200d118179faa7f96ba4a stock_supply-6.0.0
+0000000000000000000000000000000000000000 6.0.1
+7c13addfa07217e498c00f83117517b179d33f1b stock_supply-6.0.1
+0000000000000000000000000000000000000000 6.0.2
+47e2a56c3eb9cd49ad460d35fc16dab4c334384b stock_supply-6.0.2
+0000000000000000000000000000000000000000 6.0.3
+aeafed90f31c18b914b74cfd675f897dc41ca6cd stock_supply-6.0.3
+ec2752f736f671fea3f95f881fa19e7cbfcc88c2 2.4.0
+4541105a8fc9586b5c65f581d70dd6906c41a730 2.6.0
+c0a9cb20a609d38ecf4facd08ffe55b2020e38ad 2.8.0
+ddf4cfa5af01e368d995885606d572d53d36cd7b 3.0.0
+81e986b99d1b16b26e8c7ae69684225bfa252603 3.2.0
+808383c0929c8dda2fab252418dbf31b46c2dffc 3.4.0
+bf11ecaa1d599160a62a02f46639955aaaa472a3 3.6.0
+07c3ef01edffc285a49cb969e18737dfac67bfdc 3.8.0
+d41ca7fbc924d4f73aff1c8377d2f700abe06f2d 4.0.0
+b58e60f41b662ac3d58c7502c4a6b4d5018797f4 4.2.0
+52078228f2c56880ac08f6987e8383c08a8043fd 4.4.0
+5df3455491d72296ada960cb45f72a276433a45d 4.6.0
+769117cd528a585fda8ea67bad5b54bf6fe5f6a6 4.8.0
+25c05b49d46071031d53a7798a711246789d6973 5.0.0
+24c941bdf02946e4bc130135508158dcb9817c39 5.2.0
+d4b5b3fa95da83bb9439320e69f4df43b9360f9c 5.4.0
+0b460de8ca80a58dc7b4d4528c6c4587fa0d16eb 5.6.0
+f0209c41aa97aaf6a1c8da050e47f24ad289aa38 5.8.0
+6f70ee75254fa62addab73552b06b39a2e151e66 6.0.0
+4b8288280406ba3d9a4bfb3c96a84a29ddcb9e23 6.0.1
+0000000000000000000000000000000000000000 2.4.0
+ec2752f736f671fea3f95f881fa19e7cbfcc88c2 stock_supply_production-2.4.0
+0000000000000000000000000000000000000000 2.6.0
+4541105a8fc9586b5c65f581d70dd6906c41a730 stock_supply_production-2.6.0
+0000000000000000000000000000000000000000 2.8.0
+c0a9cb20a609d38ecf4facd08ffe55b2020e38ad stock_supply_production-2.8.0
+0000000000000000000000000000000000000000 3.0.0
+ddf4cfa5af01e368d995885606d572d53d36cd7b stock_supply_production-3.0.0
+0000000000000000000000000000000000000000 3.2.0
+81e986b99d1b16b26e8c7ae69684225bfa252603 stock_supply_production-3.2.0
+0000000000000000000000000000000000000000 3.4.0
+808383c0929c8dda2fab252418dbf31b46c2dffc stock_supply_production-3.4.0
+0000000000000000000000000000000000000000 3.6.0
+bf11ecaa1d599160a62a02f46639955aaaa472a3 stock_supply_production-3.6.0
+0000000000000000000000000000000000000000 3.8.0
+07c3ef01edffc285a49cb969e18737dfac67bfdc stock_supply_production-3.8.0
+0000000000000000000000000000000000000000 4.0.0
+d41ca7fbc924d4f73aff1c8377d2f700abe06f2d stock_supply_production-4.0.0
+0000000000000000000000000000000000000000 4.2.0
+b58e60f41b662ac3d58c7502c4a6b4d5018797f4 stock_supply_production-4.2.0
+0000000000000000000000000000000000000000 4.4.0
+52078228f2c56880ac08f6987e8383c08a8043fd stock_supply_production-4.4.0
+0000000000000000000000000000000000000000 4.6.0
+5df3455491d72296ada960cb45f72a276433a45d stock_supply_production-4.6.0
+0000000000000000000000000000000000000000 4.8.0
+769117cd528a585fda8ea67bad5b54bf6fe5f6a6 stock_supply_production-4.8.0
+0000000000000000000000000000000000000000 5.0.0
+25c05b49d46071031d53a7798a711246789d6973 stock_supply_production-5.0.0
+0000000000000000000000000000000000000000 5.2.0
+24c941bdf02946e4bc130135508158dcb9817c39 stock_supply_production-5.2.0
+0000000000000000000000000000000000000000 5.4.0
+d4b5b3fa95da83bb9439320e69f4df43b9360f9c stock_supply_production-5.4.0
+0000000000000000000000000000000000000000 5.6.0
+0b460de8ca80a58dc7b4d4528c6c4587fa0d16eb stock_supply_production-5.6.0
+0000000000000000000000000000000000000000 5.8.0
+f0209c41aa97aaf6a1c8da050e47f24ad289aa38 stock_supply_production-5.8.0
+0000000000000000000000000000000000000000 6.0.0
+6f70ee75254fa62addab73552b06b39a2e151e66 stock_supply_production-6.0.0
+0000000000000000000000000000000000000000 6.0.1
+4b8288280406ba3d9a4bfb3c96a84a29ddcb9e23 stock_supply_production-6.0.1
+b9082c1aa7e6cc8316754bca8f2b29c7018ef9fc 3.0.0
+1dbac5dcf15dc3f17fb4865387a9e171dd20fc70 3.2.0
+db5b4bb6b6b098dd55089c2923e3eb5e1b8ec56b 3.4.0
+b7cb20ab4ec3b50821983ed8c0b034f30752a6ec 3.6.0
+7961a5a68240535525babbcdf496952107a480bf 3.8.0
+615333cf31aa9cc78cba9d7e20c515752e448fdb 4.0.0
+eaf2542a8adbf470a3249429f44cd5c70fa6a986 4.2.0
+6bd47a06f582784dfca255c49c7877d614adec51 4.4.0
+486b4928c849a93beb92d3bdfecfc8f622a38956 4.6.0
+03ded560c597cabf1a3e7df1fb586ecde33c1529 4.8.0
+7fcc5447286ed6be08252a52014a229fb21e706b 5.0.0
+25dfcaa29bcd9d57cdf019b3cae55b6226c355f6 5.2.0
+d4b86ad1ba39b874c39da9a5a007690489f4e15f 5.4.0
+f55c3c6bdd16d4b2ce85c8d691e9cafa71ce3d1f 5.6.0
+74c459fcf1a4a1237e25c4e3a63adbed65a7d1a8 5.8.0
+71a5bc1d16dc5b2b613ab21d94116f74d3b99320 6.0.0
+0000000000000000000000000000000000000000 3.0.0
+b9082c1aa7e6cc8316754bca8f2b29c7018ef9fc timesheet_cost-3.0.0
+0000000000000000000000000000000000000000 3.2.0
+1dbac5dcf15dc3f17fb4865387a9e171dd20fc70 timesheet_cost-3.2.0
+0000000000000000000000000000000000000000 3.4.0
+db5b4bb6b6b098dd55089c2923e3eb5e1b8ec56b timesheet_cost-3.4.0
+0000000000000000000000000000000000000000 3.6.0
+b7cb20ab4ec3b50821983ed8c0b034f30752a6ec timesheet_cost-3.6.0
+0000000000000000000000000000000000000000 3.8.0
+7961a5a68240535525babbcdf496952107a480bf timesheet_cost-3.8.0
+0000000000000000000000000000000000000000 4.0.0
+615333cf31aa9cc78cba9d7e20c515752e448fdb timesheet_cost-4.0.0
+0000000000000000000000000000000000000000 4.2.0
+eaf2542a8adbf470a3249429f44cd5c70fa6a986 timesheet_cost-4.2.0
+0000000000000000000000000000000000000000 4.4.0
+6bd47a06f582784dfca255c49c7877d614adec51 timesheet_cost-4.4.0
+0000000000000000000000000000000000000000 4.6.0
+486b4928c849a93beb92d3bdfecfc8f622a38956 timesheet_cost-4.6.0
+0000000000000000000000000000000000000000 4.8.0
+03ded560c597cabf1a3e7df1fb586ecde33c1529 timesheet_cost-4.8.0
+0000000000000000000000000000000000000000 5.0.0
+7fcc5447286ed6be08252a52014a229fb21e706b timesheet_cost-5.0.0
+0000000000000000000000000000000000000000 5.2.0
+25dfcaa29bcd9d57cdf019b3cae55b6226c355f6 timesheet_cost-5.2.0
+0000000000000000000000000000000000000000 5.4.0
+d4b86ad1ba39b874c39da9a5a007690489f4e15f timesheet_cost-5.4.0
+0000000000000000000000000000000000000000 5.6.0
+f55c3c6bdd16d4b2ce85c8d691e9cafa71ce3d1f timesheet_cost-5.6.0
+0000000000000000000000000000000000000000 5.8.0
+74c459fcf1a4a1237e25c4e3a63adbed65a7d1a8 timesheet_cost-5.8.0
+0000000000000000000000000000000000000000 6.0.0
+71a5bc1d16dc5b2b613ab21d94116f74d3b99320 timesheet_cost-6.0.0
+a32068d131a6872da6c87812f3fda96c5ad076bb 1.4.0
+3d405f7a2a43e41869b7f438203d3a945b1d68f9 1.6.0
+65577163f1e51a0e1385155cae93eb2900866f3b 1.8.0
+24d03108a830bc2b71924432ebcb32dfd6f5b2e0 2.0.0
+1d020661487e0ddc14d2825aa66ec6772e66010c 2.2.0
+7b90dcce007c3fc93a9b409f54f379f8182728ee 2.4.0
+549128cae2441f891c24176c1f6a67777962e3d3 2.6.0
+8c69d08939dbc773d89f4c637ce6a8d8cadcb866 2.8.0
+4e635a95118453b2ff0ec533a70ac50d4dacc3cb 3.0.0
+5f4ed300d4966e0c16c4497428a130b19a6209f3 3.2.0
+a4e84c96f4735bd710e02a0364af0947ba44d4b7 3.4.0
+728c1ee800a32fdd4856e86998a32c3c929d262d 3.6.0
+1924468dda905272353c147edc625a3496b3421e 3.8.0
+ae80ff03e20174f8ed595b9fa47893598c13f91f 4.0.0
+dd6dfdad58d95b23dab3c1ff906f2e18c634b474 4.2.0
+05cf4e50160ca0801ef2aa7c93d2b9b9c4a41071 4.4.0
+4ad8501eef3e1b47ccf54ecabf5cedbb0bebe99b 4.6.0
+bd8398d102d53692be26bd76171c23b85676304c 4.8.0
+f22152a613c52f8ffece522ec3a1f30e46637e3a 5.0.0
+ae0426e8137939d8d4e14f0d6717b46e0bd6ff3a 5.2.0
+41c1f6178f3f039bc62dd85ebd1fa6f92212c9ec 5.4.0
+f9ad969ee981b3b7cd11723d471d4ed3d0fff873 5.6.0
+a874b70acc06493a4b64edc59ec3be3cba8503a6 5.8.0
+779126589e978c55a09cc15d7854a08fff370416 6.0.0
+8603d8d89e44cb5ad8a8c9efc403db90cd214028 6.0.1
+d2f9bdfd51c32bc1c67d14357acab16782dedb07 6.0.2
+0000000000000000000000000000000000000000 1.4.0
+a32068d131a6872da6c87812f3fda96c5ad076bb timesheet-1.4.0
+0000000000000000000000000000000000000000 1.6.0
+3d405f7a2a43e41869b7f438203d3a945b1d68f9 timesheet-1.6.0
+0000000000000000000000000000000000000000 1.8.0
+65577163f1e51a0e1385155cae93eb2900866f3b timesheet-1.8.0
+0000000000000000000000000000000000000000 2.0.0
+24d03108a830bc2b71924432ebcb32dfd6f5b2e0 timesheet-2.0.0
+0000000000000000000000000000000000000000 2.2.0
+1d020661487e0ddc14d2825aa66ec6772e66010c timesheet-2.2.0
+0000000000000000000000000000000000000000 2.4.0
+7b90dcce007c3fc93a9b409f54f379f8182728ee timesheet-2.4.0
+0000000000000000000000000000000000000000 2.6.0
+549128cae2441f891c24176c1f6a67777962e3d3 timesheet-2.6.0
+0000000000000000000000000000000000000000 2.8.0
+8c69d08939dbc773d89f4c637ce6a8d8cadcb866 timesheet-2.8.0
+0000000000000000000000000000000000000000 3.0.0
+4e635a95118453b2ff0ec533a70ac50d4dacc3cb timesheet-3.0.0
+0000000000000000000000000000000000000000 3.2.0
+5f4ed300d4966e0c16c4497428a130b19a6209f3 timesheet-3.2.0
+0000000000000000000000000000000000000000 3.4.0
+a4e84c96f4735bd710e02a0364af0947ba44d4b7 timesheet-3.4.0
+0000000000000000000000000000000000000000 3.6.0
+728c1ee800a32fdd4856e86998a32c3c929d262d timesheet-3.6.0
+0000000000000000000000000000000000000000 3.8.0
+1924468dda905272353c147edc625a3496b3421e timesheet-3.8.0
+0000000000000000000000000000000000000000 4.0.0
+ae80ff03e20174f8ed595b9fa47893598c13f91f timesheet-4.0.0
+0000000000000000000000000000000000000000 4.2.0
+dd6dfdad58d95b23dab3c1ff906f2e18c634b474 timesheet-4.2.0
+0000000000000000000000000000000000000000 4.4.0
+05cf4e50160ca0801ef2aa7c93d2b9b9c4a41071 timesheet-4.4.0
+0000000000000000000000000000000000000000 4.6.0
+4ad8501eef3e1b47ccf54ecabf5cedbb0bebe99b timesheet-4.6.0
+0000000000000000000000000000000000000000 4.8.0
+bd8398d102d53692be26bd76171c23b85676304c timesheet-4.8.0
+0000000000000000000000000000000000000000 5.0.0
+f22152a613c52f8ffece522ec3a1f30e46637e3a timesheet-5.0.0
+0000000000000000000000000000000000000000 5.2.0
+ae0426e8137939d8d4e14f0d6717b46e0bd6ff3a timesheet-5.2.0
+0000000000000000000000000000000000000000 5.4.0
+41c1f6178f3f039bc62dd85ebd1fa6f92212c9ec timesheet-5.4.0
+0000000000000000000000000000000000000000 5.6.0
+f9ad969ee981b3b7cd11723d471d4ed3d0fff873 timesheet-5.6.0
+0000000000000000000000000000000000000000 5.8.0
+a874b70acc06493a4b64edc59ec3be3cba8503a6 timesheet-5.8.0
+0000000000000000000000000000000000000000 6.0.0
+779126589e978c55a09cc15d7854a08fff370416 timesheet-6.0.0
+0000000000000000000000000000000000000000 6.0.1
+8603d8d89e44cb5ad8a8c9efc403db90cd214028 timesheet-6.0.1
+0000000000000000000000000000000000000000 6.0.2
+d2f9bdfd51c32bc1c67d14357acab16782dedb07 timesheet-6.0.2
+0f3d5527aad7e83e07c84b19983b86f5b580d9b9 5.2.0
+32c3f6707c841e89eaa8e1200b4ed4b4b8c2510d 5.4.0
+65a1ddcc0b7d681c785f9260aa11e9c9a9b3f74b 5.6.0
+8766a61dd6f885faa2bed9eaa21c307412674989 5.8.0
+5c50392d0b77f4f5c1f76ece0997ec73591e887c 6.0.0
+0000000000000000000000000000000000000000 5.2.0
+0f3d5527aad7e83e07c84b19983b86f5b580d9b9 user_role-5.2.0
+0000000000000000000000000000000000000000 5.4.0
+32c3f6707c841e89eaa8e1200b4ed4b4b8c2510d user_role-5.4.0
+0000000000000000000000000000000000000000 5.6.0
+65a1ddcc0b7d681c785f9260aa11e9c9a9b3f74b user_role-5.6.0
+0000000000000000000000000000000000000000 5.8.0
+8766a61dd6f885faa2bed9eaa21c307412674989 user_role-5.8.0
+0000000000000000000000000000000000000000 6.0.0
+5c50392d0b77f4f5c1f76ece0997ec73591e887c user_role-6.0.0
+cc6273db844d391455840a0cb63fbd8e78b704c7 5.8.0
+4020d5ca9497c14dfc273676d49363650eb8da80 6.0.0
+0050d9a729746f753fbd3029ff635a459e458e07 6.0.1
+64b26bac37642e1dcff5f8d9590250cbff8fbc94 6.0.2
+247fec368df174a2cc186065669462b198b3fd62 6.0.3
+0000000000000000000000000000000000000000 5.8.0
+cc6273db844d391455840a0cb63fbd8e78b704c7 web_shop-5.8.0
+0000000000000000000000000000000000000000 6.0.0
+4020d5ca9497c14dfc273676d49363650eb8da80 web_shop-6.0.0
+0000000000000000000000000000000000000000 6.0.1
+0050d9a729746f753fbd3029ff635a459e458e07 web_shop-6.0.1
+0000000000000000000000000000000000000000 6.0.2
+64b26bac37642e1dcff5f8d9590250cbff8fbc94 web_shop-6.0.2
+0000000000000000000000000000000000000000 6.0.3
+247fec368df174a2cc186065669462b198b3fd62 web_shop-6.0.3
+bfc8e45097fc0e414744408e96708fdf5d2b33a1 5.8.0
+2efa183d80e356d0c11731819456b8dd9bc586db 6.0.0
+1f0c1ae839cf3df054309a0aa60e6e7fcdbdc926 6.0.1
+c1149124f1c8206c8b3d787dc9d7f41e61c0fe20 6.0.2
+255623f33107cd9f26a00f89c727634bb01cf1a9 6.0.3
+33f7271faaeccb49772f3ce8dc6e35036d7aec61 6.0.4
+2af6bbee8a75aaca6a213f722f1e4b49d98c551e 6.0.5
+0000000000000000000000000000000000000000 5.8.0
+bfc8e45097fc0e414744408e96708fdf5d2b33a1 web_shop_vue_storefront-5.8.0
+0000000000000000000000000000000000000000 6.0.0
+2efa183d80e356d0c11731819456b8dd9bc586db web_shop_vue_storefront-6.0.0
+0000000000000000000000000000000000000000 6.0.1
+1f0c1ae839cf3df054309a0aa60e6e7fcdbdc926 web_shop_vue_storefront-6.0.1
+0000000000000000000000000000000000000000 6.0.2
+c1149124f1c8206c8b3d787dc9d7f41e61c0fe20 web_shop_vue_storefront-6.0.2
+0000000000000000000000000000000000000000 6.0.3
+255623f33107cd9f26a00f89c727634bb01cf1a9 web_shop_vue_storefront-6.0.3
+0000000000000000000000000000000000000000 6.0.4
+33f7271faaeccb49772f3ce8dc6e35036d7aec61 web_shop_vue_storefront-6.0.4
+0000000000000000000000000000000000000000 6.0.5
+2af6bbee8a75aaca6a213f722f1e4b49d98c551e web_shop_vue_storefront-6.0.5
+0a5ab9e8e526e89b69c1aadb73127da0759edc27 5.8.0
+4b01e563d74ede2cd6ac3c0ae8bd597a963c21a3 6.0.0
+c418c973cfc6b60e495a3376cd632035b9a1a7d8 6.0.1
+0000000000000000000000000000000000000000 5.8.0
+0a5ab9e8e526e89b69c1aadb73127da0759edc27 web_shop_vue_storefront_stripe-5.8.0
+0000000000000000000000000000000000000000 6.0.0
+4b01e563d74ede2cd6ac3c0ae8bd597a963c21a3 web_shop_vue_storefront_stripe-6.0.0
+0000000000000000000000000000000000000000 6.0.1
+c418c973cfc6b60e495a3376cd632035b9a1a7d8 web_shop_vue_storefront_stripe-6.0.1
+d1340478469878c66528aac5cec001841d14ca5a 5.2.0
+bed84c6dd812463897dc9cca5b7909f6ea4651a4 5.4.0
+e37a9b2291b9b60d453a9eabc894d21b5aeca097 5.6.0
+c3046a83c61339a6310b8cf56c2e4dddd59a0675 5.8.0
+0d2662846f667e44e2831a271becf86f8868c9a5 6.0.0
+f5cdb780a081fb87e0ebcb77b71e5b1c9f7233df 6.0.1
+0000000000000000000000000000000000000000 5.2.0
+d1340478469878c66528aac5cec001841d14ca5a web_shortener-5.2.0
+0000000000000000000000000000000000000000 5.4.0
+bed84c6dd812463897dc9cca5b7909f6ea4651a4 web_shortener-5.4.0
+0000000000000000000000000000000000000000 5.6.0
+e37a9b2291b9b60d453a9eabc894d21b5aeca097 web_shortener-5.6.0
+0000000000000000000000000000000000000000 5.8.0
+c3046a83c61339a6310b8cf56c2e4dddd59a0675 web_shortener-5.8.0
+0000000000000000000000000000000000000000 6.0.0
+0d2662846f667e44e2831a271becf86f8868c9a5 web_shortener-6.0.0
+0000000000000000000000000000000000000000 6.0.1
+f5cdb780a081fb87e0ebcb77b71e5b1c9f7233df web_shortener-6.0.1
+99f99784b341ce8bb34bd70d89f51aa45c24f1f7 4.2.0
+a6661fddc44d1cee9c5697d983e8fb38deb73225 4.4.0
+d5c1f780f492de8ab82da98a577a5685bb513d9b 4.6.0
+9ad3bd829ad68cd69806533416aadc50f5eb6794 4.8.0
+ca21f3a99b42b088c6588c36f5e105dae713f775 5.0.0
+c2ef0488218d9d3ee59514b744e2145bbd0147b3 5.2.0
+cb5da130470815adfd7b3681fa2803feed934f45 5.4.0
+b95009d0a58dd058440cc0cd7537e5c4499ea16a 5.6.0
+166c1e4c476baeb36b21cef7963b87b5ca07f71e 5.8.0
+ec9a4f3e26f796c12a267e4b3af717fd2a35c066 6.0.0
+0000000000000000000000000000000000000000 4.2.0
+99f99784b341ce8bb34bd70d89f51aa45c24f1f7 web_user-4.2.0
+0000000000000000000000000000000000000000 4.4.0
+a6661fddc44d1cee9c5697d983e8fb38deb73225 web_user-4.4.0
+0000000000000000000000000000000000000000 4.6.0
+d5c1f780f492de8ab82da98a577a5685bb513d9b web_user-4.6.0
+0000000000000000000000000000000000000000 4.8.0
+9ad3bd829ad68cd69806533416aadc50f5eb6794 web_user-4.8.0
+0000000000000000000000000000000000000000 5.0.0
+ca21f3a99b42b088c6588c36f5e105dae713f775 web_user-5.0.0
+0000000000000000000000000000000000000000 5.2.0
+c2ef0488218d9d3ee59514b744e2145bbd0147b3 web_user-5.2.0
+0000000000000000000000000000000000000000 5.4.0
+cb5da130470815adfd7b3681fa2803feed934f45 web_user-5.4.0
+0000000000000000000000000000000000000000 5.6.0
+b95009d0a58dd058440cc0cd7537e5c4499ea16a web_user-5.6.0
+0000000000000000000000000000000000000000 5.8.0
+166c1e4c476baeb36b21cef7963b87b5ca07f71e web_user-5.8.0
+0000000000000000000000000000000000000000 6.0.0
+ec9a4f3e26f796c12a267e4b3af717fd2a35c066 web_user-6.0.0
+3974f546b848d4ac59551db9f733d8ed62946dfd 1.8.0
+c8fdae3b2338b744fce709572958884a95de87b3 2.0.0
+120d0435125cf3a3c28280321962571924ad422f 2.2.0
+ef9846cb18afe62182de446d8e4fa7b8393f7168 2.4.0
+648c43939fd698988bde5b54f7a1dff9d47922af 2.6.0
+5625ce03643f9f2b69659907754e5b0e924c689f 2.8.0
+31740f7e08a0c449ce6715e1ef15392fb6326ce9 3.0.0
+40affcdda4629de37997d0e5c7d3fe9ca2806b12 3.2.0
+61013c4482fc95a61d2a15a8b21574a706755b10 3.4.0
+2a2503ebd25887ff3668d470809c00c5bcf2c6c7 3.6.0
+1e741a18e2a1f29fcc66e9ab4878554a4e63a355 3.8.0
+403f21dd1bb7059a0928c46c8b21a97c14f9c720 4.0.0
+d5b1e8f047748526d9a2cd354da0e86d617ec4c7 4.2.0
+365af7e74c2baae38e96bc0afb1deae2d2b44ac0 4.4.0
+cd4731fb373698d480a625a286de776a0b9bdc6e 4.6.0
+3867b51d50056fda52882150a017a9dce6811264 4.8.0
+e86f9d540f29dfcd39e8f198b50940c8b91250d6 5.0.0
+f4a0b0e282f39c013c44e5012e6b85e4b8a4ae40 5.2.0
+03daaf3994610fde107d98d8458b2731e03c5306 5.4.0
+a8061a1d268776766c44ceb97094d229dbe31962 5.6.0
+8bc88e82ff9edc33725d08bc0c6f2862f221a127 5.8.0
+ac15e7f1881fd78d30eac0d7c772638265830c77 6.0.0
+14cd94a3e75463a9e4ab4c562cce82470070731b 6.0.1
+b579da9fa80282eaf0657e6d2826147c2c6c2f3d 6.0.2
+dc3d781b552d24dcfb7b0ced4322b1ba17e6ca09 6.0.3
+8e6d0969604981e6d024b203424b1b3f0bcd4cb3 6.0.4
+c20749d242200840432ab0b87ce7c0072ee1be34 6.0.5
+b279acacc05c6df60ca9833a3eb6e22b9f9fa488 6.0.6
+8a5195f7cece07c1baceade758e1e783170abe32 6.0.7
+0000000000000000000000000000000000000000 1.8.0
+3974f546b848d4ac59551db9f733d8ed62946dfd proteus-1.8.0
+0000000000000000000000000000000000000000 2.0.0
+c8fdae3b2338b744fce709572958884a95de87b3 proteus-2.0.0
+0000000000000000000000000000000000000000 2.2.0
+120d0435125cf3a3c28280321962571924ad422f proteus-2.2.0
+0000000000000000000000000000000000000000 2.4.0
+ef9846cb18afe62182de446d8e4fa7b8393f7168 proteus-2.4.0
+0000000000000000000000000000000000000000 2.6.0
+648c43939fd698988bde5b54f7a1dff9d47922af proteus-2.6.0
+0000000000000000000000000000000000000000 2.8.0
+5625ce03643f9f2b69659907754e5b0e924c689f proteus-2.8.0
+0000000000000000000000000000000000000000 3.0.0
+31740f7e08a0c449ce6715e1ef15392fb6326ce9 proteus-3.0.0
+0000000000000000000000000000000000000000 3.2.0
+40affcdda4629de37997d0e5c7d3fe9ca2806b12 proteus-3.2.0
+0000000000000000000000000000000000000000 3.4.0
+61013c4482fc95a61d2a15a8b21574a706755b10 proteus-3.4.0
+0000000000000000000000000000000000000000 3.6.0
+2a2503ebd25887ff3668d470809c00c5bcf2c6c7 proteus-3.6.0
+0000000000000000000000000000000000000000 3.8.0
+1e741a18e2a1f29fcc66e9ab4878554a4e63a355 proteus-3.8.0
+0000000000000000000000000000000000000000 4.0.0
+403f21dd1bb7059a0928c46c8b21a97c14f9c720 proteus-4.0.0
+0000000000000000000000000000000000000000 4.2.0
+d5b1e8f047748526d9a2cd354da0e86d617ec4c7 proteus-4.2.0
+0000000000000000000000000000000000000000 4.4.0
+365af7e74c2baae38e96bc0afb1deae2d2b44ac0 proteus-4.4.0
+0000000000000000000000000000000000000000 4.6.0
+cd4731fb373698d480a625a286de776a0b9bdc6e proteus-4.6.0
+0000000000000000000000000000000000000000 4.8.0
+3867b51d50056fda52882150a017a9dce6811264 proteus-4.8.0
+0000000000000000000000000000000000000000 5.0.0
+e86f9d540f29dfcd39e8f198b50940c8b91250d6 proteus-5.0.0
+0000000000000000000000000000000000000000 5.2.0
+f4a0b0e282f39c013c44e5012e6b85e4b8a4ae40 proteus-5.2.0
+0000000000000000000000000000000000000000 5.4.0
+03daaf3994610fde107d98d8458b2731e03c5306 proteus-5.4.0
+0000000000000000000000000000000000000000 5.6.0
+a8061a1d268776766c44ceb97094d229dbe31962 proteus-5.6.0
+0000000000000000000000000000000000000000 5.8.0
+8bc88e82ff9edc33725d08bc0c6f2862f221a127 proteus-5.8.0
+0000000000000000000000000000000000000000 6.0.0
+ac15e7f1881fd78d30eac0d7c772638265830c77 proteus-6.0.0
+0000000000000000000000000000000000000000 6.0.1
+14cd94a3e75463a9e4ab4c562cce82470070731b proteus-6.0.1
+0000000000000000000000000000000000000000 6.0.2
+b579da9fa80282eaf0657e6d2826147c2c6c2f3d proteus-6.0.2
+0000000000000000000000000000000000000000 6.0.3
+dc3d781b552d24dcfb7b0ced4322b1ba17e6ca09 proteus-6.0.3
+0000000000000000000000000000000000000000 6.0.4
+8e6d0969604981e6d024b203424b1b3f0bcd4cb3 proteus-6.0.4
+0000000000000000000000000000000000000000 6.0.5
+c20749d242200840432ab0b87ce7c0072ee1be34 proteus-6.0.5
+0000000000000000000000000000000000000000 6.0.6
+b279acacc05c6df60ca9833a3eb6e22b9f9fa488 proteus-6.0.6
+0000000000000000000000000000000000000000 6.0.7
+8a5195f7cece07c1baceade758e1e783170abe32 proteus-6.0.7
+c835144ba5fd172c9aa8714683e69ca60bc894bc 3.8.0
+20712dc81634af43f9e0ebb41b0dcea50ccffdd2 4.0.0
+963504a30207af5877c11368ac5dadbc5d28fee1 4.2.0
+1fea2b717dd8d57d0a233c19d7f1eec35bdde0fa 4.4.0
+16a536201007ba66d36040a34e79a8998c4051f8 4.6.0
+08b000057b0b5a69f4034f2e1f5c7f2f7f23276f 4.8.0
+47edb75271514576ea775d28dc286a120675aa32 5.0.0
+4074fcefe73deec0b4dcd8b2e29f6c3c8eade611 5.2.0
+2d6d3a648c1dc1711adcc7bd3ff0930949b3076a 5.4.0
+513d2f77dc3bb1f5335af4faf233ccaa1711ac82 5.6.0
+e013e9930e2f27e5205b93f39d49f3604ae07901 5.8.0
+031cd536bd9f4e89345876c2d438626c57fbb33c 6.0.0
+ca49dcd87a916c997b5fe8bfc79c3195766bd4be 6.0.1
+a8121f01d452fd877749cf304dd691618553fccb 6.0.2
+90177ab7f46ac9703f9130f36f87d696774506be 6.0.3
+c1b6c469704c89d22f838a7c387f8ce2db6c04e8 6.0.4
+d37b211c91cc908fb3dbdc3ea8b52af50ef325a2 6.0.5
+76abf46e661d7f2b5d95bf13fddf107f31d47105 6.0.6
+722e116a59f5a1ba61aede38920e03a05a7d7ce4 6.0.7
+262af554d965998030b6b5b9441bc9469dab2311 6.0.8
+caafedc5aba43c65c49eeddf28ee41d8d35d2108 6.0.9
+a29aac850db9e9d55cc33f3ef1fff7af05043fc8 6.0.10
+c1f4671012217e27ee6fedb519da6eecb6b164d8 6.0.11
+2d40a627f2215c62800149562d033a18d550eabc 6.0.12
+31cb176af93153cff7f9b0ad024ce2d3ecac44c1 6.0.13
+440b2885e1659393f469358808a8b83ccb08c12c 6.0.14
+845114a2dc0253d6cb66883089996adffed70188 6.0.15
+89d9b0b02548363e7dfc984e594d09eff061e29c 6.0.16
+f95deaf6c5404e617fe522d98520c1ba829c64b3 6.0.17
+056876b48b55163bfb276ed713fbc8d3c7ec3209 6.0.18
+3fc2510a1f70752c9489a924727c11951eb5171f 6.0.19
+1491afc63d061116473998f40335b1901c62f7c8 6.0.20
+8f4439b7d4a4908f44c9e6d93b3a45fd8fd39350 6.0.21
+0263312e30f850a6637f1c920dbff1c929bf9ded 6.0.22
+5b249c3acf2243f294089418a325bbdcab7c57ad 6.0.23
+7fd7e8a5ae84dab88f322e900d26cbd2e7115292 6.0.24
+0000000000000000000000000000000000000000 3.8.0
+c835144ba5fd172c9aa8714683e69ca60bc894bc sao-3.8.0
+0000000000000000000000000000000000000000 4.0.0
+20712dc81634af43f9e0ebb41b0dcea50ccffdd2 sao-4.0.0
+0000000000000000000000000000000000000000 4.2.0
+963504a30207af5877c11368ac5dadbc5d28fee1 sao-4.2.0
+0000000000000000000000000000000000000000 4.4.0
+1fea2b717dd8d57d0a233c19d7f1eec35bdde0fa sao-4.4.0
+0000000000000000000000000000000000000000 4.6.0
+16a536201007ba66d36040a34e79a8998c4051f8 sao-4.6.0
+0000000000000000000000000000000000000000 4.8.0
+08b000057b0b5a69f4034f2e1f5c7f2f7f23276f sao-4.8.0
+0000000000000000000000000000000000000000 5.0.0
+47edb75271514576ea775d28dc286a120675aa32 sao-5.0.0
+0000000000000000000000000000000000000000 5.2.0
+4074fcefe73deec0b4dcd8b2e29f6c3c8eade611 sao-5.2.0
+0000000000000000000000000000000000000000 5.4.0
+2d6d3a648c1dc1711adcc7bd3ff0930949b3076a sao-5.4.0
+0000000000000000000000000000000000000000 5.6.0
+513d2f77dc3bb1f5335af4faf233ccaa1711ac82 sao-5.6.0
+0000000000000000000000000000000000000000 5.8.0
+e013e9930e2f27e5205b93f39d49f3604ae07901 sao-5.8.0
+0000000000000000000000000000000000000000 6.0.0
+031cd536bd9f4e89345876c2d438626c57fbb33c sao-6.0.0
+0000000000000000000000000000000000000000 6.0.1
+ca49dcd87a916c997b5fe8bfc79c3195766bd4be sao-6.0.1
+0000000000000000000000000000000000000000 6.0.10
+a29aac850db9e9d55cc33f3ef1fff7af05043fc8 sao-6.0.10
+0000000000000000000000000000000000000000 6.0.11
+c1f4671012217e27ee6fedb519da6eecb6b164d8 sao-6.0.11
+0000000000000000000000000000000000000000 6.0.12
+2d40a627f2215c62800149562d033a18d550eabc sao-6.0.12
+0000000000000000000000000000000000000000 6.0.13
+31cb176af93153cff7f9b0ad024ce2d3ecac44c1 sao-6.0.13
+0000000000000000000000000000000000000000 6.0.14
+440b2885e1659393f469358808a8b83ccb08c12c sao-6.0.14
+0000000000000000000000000000000000000000 6.0.15
+845114a2dc0253d6cb66883089996adffed70188 sao-6.0.15
+0000000000000000000000000000000000000000 6.0.16
+89d9b0b02548363e7dfc984e594d09eff061e29c sao-6.0.16
+0000000000000000000000000000000000000000 6.0.17
+f95deaf6c5404e617fe522d98520c1ba829c64b3 sao-6.0.17
+0000000000000000000000000000000000000000 6.0.18
+056876b48b55163bfb276ed713fbc8d3c7ec3209 sao-6.0.18
+0000000000000000000000000000000000000000 6.0.19
+3fc2510a1f70752c9489a924727c11951eb5171f sao-6.0.19
+0000000000000000000000000000000000000000 6.0.2
+a8121f01d452fd877749cf304dd691618553fccb sao-6.0.2
+0000000000000000000000000000000000000000 6.0.20
+1491afc63d061116473998f40335b1901c62f7c8 sao-6.0.20
+0000000000000000000000000000000000000000 6.0.21
+8f4439b7d4a4908f44c9e6d93b3a45fd8fd39350 sao-6.0.21
+0000000000000000000000000000000000000000 6.0.22
+0263312e30f850a6637f1c920dbff1c929bf9ded sao-6.0.22
+0000000000000000000000000000000000000000 6.0.23
+5b249c3acf2243f294089418a325bbdcab7c57ad sao-6.0.23
+0000000000000000000000000000000000000000 6.0.24
+7fd7e8a5ae84dab88f322e900d26cbd2e7115292 sao-6.0.24
+0000000000000000000000000000000000000000 6.0.3
+90177ab7f46ac9703f9130f36f87d696774506be sao-6.0.3
+0000000000000000000000000000000000000000 6.0.4
+c1b6c469704c89d22f838a7c387f8ce2db6c04e8 sao-6.0.4
+0000000000000000000000000000000000000000 6.0.5
+d37b211c91cc908fb3dbdc3ea8b52af50ef325a2 sao-6.0.5
+0000000000000000000000000000000000000000 6.0.6
+76abf46e661d7f2b5d95bf13fddf107f31d47105 sao-6.0.6
+0000000000000000000000000000000000000000 6.0.7
+722e116a59f5a1ba61aede38920e03a05a7d7ce4 sao-6.0.7
+0000000000000000000000000000000000000000 6.0.8
+262af554d965998030b6b5b9441bc9469dab2311 sao-6.0.8
+0000000000000000000000000000000000000000 6.0.9
+caafedc5aba43c65c49eeddf28ee41d8d35d2108 sao-6.0.9
+4b876ac37410e223bc3628256425d80398d051c6 4.8.0
+144f9950fba568bd77ac0eecd02c7b0d0a98ba87 5.0.0
+ed88584857aa1b39459a420270c0253d460cfe48 5.2.0
+ed46c63b027820aa6e605bb53040f4ed4d133813 5.4.0
+d2db68823a8225ff32842da4e948c1c01197e5cc 5.6.0
+eeab3256f17f6b9bc111d74d6d7f984e75d70f17 5.8.0
+4d33daf649c10711b782ef82b71e49d1a725ccee 6.0.0
+ed86455b7bf99bb7a18309e809adc54e6a4864d8 6.0.1
+0000000000000000000000000000000000000000 4.8.0
+4b876ac37410e223bc3628256425d80398d051c6 trytond-gis-4.8.0
+0000000000000000000000000000000000000000 5.0.0
+144f9950fba568bd77ac0eecd02c7b0d0a98ba87 trytond-gis-5.0.0
+0000000000000000000000000000000000000000 5.2.0
+ed88584857aa1b39459a420270c0253d460cfe48 trytond-gis-5.2.0
+0000000000000000000000000000000000000000 5.4.0
+ed46c63b027820aa6e605bb53040f4ed4d133813 trytond-gis-5.4.0
+0000000000000000000000000000000000000000 5.6.0
+d2db68823a8225ff32842da4e948c1c01197e5cc trytond-gis-5.6.0
+0000000000000000000000000000000000000000 5.8.0
+eeab3256f17f6b9bc111d74d6d7f984e75d70f17 trytond-gis-5.8.0
+0000000000000000000000000000000000000000 6.0.0
+4d33daf649c10711b782ef82b71e49d1a725ccee trytond-gis-6.0.0
+0000000000000000000000000000000000000000 6.0.1
+ed86455b7bf99bb7a18309e809adc54e6a4864d8 trytond-gis-6.0.1
+951bb3311b916cb893adc5294cfb3216d2940169 1.0.0
+9f5ce178a7c403a0865fd4b6c1a82a911df0e998 1.2.0
+e2d31d59de7745de70199b7c340d78b7c4775723 1.4.0
+64691214959ac19983f3b3d1dbb89ff693d1545c 1.6.0
+af3a6063b46bf8739a513a06400fbb9858b5869b 1.8.0
+3475040a8fe081b1b8609350186b779cc640fba4 2.0.0
+1df3f0702c621e65279af52d1f87725747ae8fa4 2.2.0
+640af4420c8eace7ee59a432bec54692f4808b20 2.4.0
+36530840a1d0dce354bbaa58ec849a409d306d83 2.6.0
+2893d6c3efd6df3759ab09a28ea16773a160118e 2.8.0
+759c6ff44b90b8c685e9d9a4124bcd85af204649 3.0.0
+b3d84aa2c3a6ed3b76bfb58a40fc687f68824c29 3.2.0
+f0a9fa755cde703be54efd747f376b096ea8316c 3.4.0
+1e4ba5a3f16e6afd59131b49841eb004e706619d 3.6.0
+0a29a9dba7f56fbdef067772eea3f037934999c9 3.8.0
+49a0caa894dae201ed4ec707f277d9859b5521fb 4.0.0
+eb8949ec5bcedba563b5799f1315a0cecfee61f6 4.2.0
+f253ce8ed02f4c46a69b8b2f29311ad8959698be 4.4.0
+e7a6d0e8002237f624ecc8a45a6a472f7baadd08 4.6.0
+321b0104a732419c11aa4926785502e0615b89c9 4.8.0
+e8cadc044d59edff8a2ca73932c723d507517ec8 5.0.0
+ef34e4e92d45ab2b2b2956bbb6aa8b3ca259eb13 5.2.0
+32170ff46339dbc8609225791ab737a0f3eb0291 5.4.0
+5738a22adbb45390167194e4089adc46c6b638a3 5.6.0
+e21456b81972188261b8a6fc876afc18f641c85b 5.8.0
+2164597ffa5f4f0443e4804944b30f5491070990 6.0.0
+12a321529713d3e0b04fa94883baf66bddf76b75 6.0.1
+10e05cdf4fb3fcd545d8b47d03df8cfb78b38a76 6.0.2
+7b3f3676cf9d72147edcdb0cd477b77b1af7af9e 6.0.3
+68ea8ab81fc3d67e3efe925c3694644a46b7c111 6.0.4
+133f0b26de213e0b5668ae891e176de8f79025fc 6.0.5
+1719ce1a669285333424c02c9e3e45fd636b995c 6.0.6
+67fe2d478dbf413873c0919cfd5d6f3f6f4c2275 6.0.7
+ed230154446f04aed350b7fd0d416a80145645ee 6.0.8
+df3e4a189c249ff54e118a4943c03ecaab5fee60 6.0.9
+32f14e8a77caa727f2dfcec93aa15e05f45ad0b6 6.0.10
+6cb11cbdabc3b93d9698fc17653e8cb24b8154d4 6.0.11
+f34c0f0f0010e95ba38d3378f2e86d7e7a966516 6.0.12
+c1e2890b414d6d9c0bae303577fb784c8e8c715b 6.0.13
+78607bfea2986fe335c98a6ef87905cded1f5b2d 6.0.14
+26fba5237ff3ec9aed2d8aebdc1115e595e76c0b 6.0.15
+c4cf78bb401aec7d52a007eb7bda958658edaf95 6.0.16
+246ad7a2addde11a7b3e828ace36cf5fb1bc6696 6.0.17
+ca63f7f2eef1998de82eae76636c00211f0e3a80 6.0.18
+2973349bc8ca02dc5aba4fbf6a2e4ba270af9780 6.0.19
+9d5f5e04e2b0105bf4ca644bf98811d267054514 6.0.20
+221212011e95b8004c93ec76d21f5ffa12e866ee 6.0.21
+3ff41e43408ddccd4ce91170b6536a2f5cd0112b 6.0.22
+7d81a0faef794489d63fb164d0fb2ba2196c878b 6.0.23
+9b36d68c67a48a2203ef3598f5379d708781dc9e 6.0.24
+0000000000000000000000000000000000000000 1.0.0
+951bb3311b916cb893adc5294cfb3216d2940169 trytond-1.0.0
+0000000000000000000000000000000000000000 1.2.0
+9f5ce178a7c403a0865fd4b6c1a82a911df0e998 trytond-1.2.0
+0000000000000000000000000000000000000000 1.4.0
+e2d31d59de7745de70199b7c340d78b7c4775723 trytond-1.4.0
+0000000000000000000000000000000000000000 1.6.0
+64691214959ac19983f3b3d1dbb89ff693d1545c trytond-1.6.0
+0000000000000000000000000000000000000000 1.8.0
+af3a6063b46bf8739a513a06400fbb9858b5869b trytond-1.8.0
+0000000000000000000000000000000000000000 2.0.0
+3475040a8fe081b1b8609350186b779cc640fba4 trytond-2.0.0
+0000000000000000000000000000000000000000 2.2.0
+1df3f0702c621e65279af52d1f87725747ae8fa4 trytond-2.2.0
+0000000000000000000000000000000000000000 2.4.0
+640af4420c8eace7ee59a432bec54692f4808b20 trytond-2.4.0
+0000000000000000000000000000000000000000 2.6.0
+36530840a1d0dce354bbaa58ec849a409d306d83 trytond-2.6.0
+0000000000000000000000000000000000000000 2.8.0
+2893d6c3efd6df3759ab09a28ea16773a160118e trytond-2.8.0
+0000000000000000000000000000000000000000 3.0.0
+759c6ff44b90b8c685e9d9a4124bcd85af204649 trytond-3.0.0
+0000000000000000000000000000000000000000 3.2.0
+b3d84aa2c3a6ed3b76bfb58a40fc687f68824c29 trytond-3.2.0
+0000000000000000000000000000000000000000 3.4.0
+f0a9fa755cde703be54efd747f376b096ea8316c trytond-3.4.0
+0000000000000000000000000000000000000000 3.6.0
+1e4ba5a3f16e6afd59131b49841eb004e706619d trytond-3.6.0
+0000000000000000000000000000000000000000 3.8.0
+0a29a9dba7f56fbdef067772eea3f037934999c9 trytond-3.8.0
+0000000000000000000000000000000000000000 4.0.0
+49a0caa894dae201ed4ec707f277d9859b5521fb trytond-4.0.0
+0000000000000000000000000000000000000000 4.2.0
+eb8949ec5bcedba563b5799f1315a0cecfee61f6 trytond-4.2.0
+0000000000000000000000000000000000000000 4.4.0
+f253ce8ed02f4c46a69b8b2f29311ad8959698be trytond-4.4.0
+0000000000000000000000000000000000000000 4.6.0
+e7a6d0e8002237f624ecc8a45a6a472f7baadd08 trytond-4.6.0
+0000000000000000000000000000000000000000 4.8.0
+321b0104a732419c11aa4926785502e0615b89c9 trytond-4.8.0
+0000000000000000000000000000000000000000 5.0.0
+e8cadc044d59edff8a2ca73932c723d507517ec8 trytond-5.0.0
+0000000000000000000000000000000000000000 5.2.0
+ef34e4e92d45ab2b2b2956bbb6aa8b3ca259eb13 trytond-5.2.0
+0000000000000000000000000000000000000000 5.4.0
+32170ff46339dbc8609225791ab737a0f3eb0291 trytond-5.4.0
+0000000000000000000000000000000000000000 5.6.0
+5738a22adbb45390167194e4089adc46c6b638a3 trytond-5.6.0
+0000000000000000000000000000000000000000 5.8.0
+e21456b81972188261b8a6fc876afc18f641c85b trytond-5.8.0
+0000000000000000000000000000000000000000 6.0.0
+2164597ffa5f4f0443e4804944b30f5491070990 trytond-6.0.0
+0000000000000000000000000000000000000000 6.0.1
+12a321529713d3e0b04fa94883baf66bddf76b75 trytond-6.0.1
+0000000000000000000000000000000000000000 6.0.10
+32f14e8a77caa727f2dfcec93aa15e05f45ad0b6 trytond-6.0.10
+0000000000000000000000000000000000000000 6.0.11
+6cb11cbdabc3b93d9698fc17653e8cb24b8154d4 trytond-6.0.11
+0000000000000000000000000000000000000000 6.0.12
+f34c0f0f0010e95ba38d3378f2e86d7e7a966516 trytond-6.0.12
+0000000000000000000000000000000000000000 6.0.13
+c1e2890b414d6d9c0bae303577fb784c8e8c715b trytond-6.0.13
+0000000000000000000000000000000000000000 6.0.14
+78607bfea2986fe335c98a6ef87905cded1f5b2d trytond-6.0.14
+0000000000000000000000000000000000000000 6.0.15
+26fba5237ff3ec9aed2d8aebdc1115e595e76c0b trytond-6.0.15
+0000000000000000000000000000000000000000 6.0.16
+c4cf78bb401aec7d52a007eb7bda958658edaf95 trytond-6.0.16
+0000000000000000000000000000000000000000 6.0.17
+246ad7a2addde11a7b3e828ace36cf5fb1bc6696 trytond-6.0.17
+0000000000000000000000000000000000000000 6.0.18
+ca63f7f2eef1998de82eae76636c00211f0e3a80 trytond-6.0.18
+0000000000000000000000000000000000000000 6.0.19
+2973349bc8ca02dc5aba4fbf6a2e4ba270af9780 trytond-6.0.19
+0000000000000000000000000000000000000000 6.0.2
+10e05cdf4fb3fcd545d8b47d03df8cfb78b38a76 trytond-6.0.2
+0000000000000000000000000000000000000000 6.0.20
+9d5f5e04e2b0105bf4ca644bf98811d267054514 trytond-6.0.20
+0000000000000000000000000000000000000000 6.0.21
+221212011e95b8004c93ec76d21f5ffa12e866ee trytond-6.0.21
+0000000000000000000000000000000000000000 6.0.22
+3ff41e43408ddccd4ce91170b6536a2f5cd0112b trytond-6.0.22
+0000000000000000000000000000000000000000 6.0.23
+7d81a0faef794489d63fb164d0fb2ba2196c878b trytond-6.0.23
+0000000000000000000000000000000000000000 6.0.24
+9b36d68c67a48a2203ef3598f5379d708781dc9e trytond-6.0.24
+0000000000000000000000000000000000000000 6.0.3
+7b3f3676cf9d72147edcdb0cd477b77b1af7af9e trytond-6.0.3
+0000000000000000000000000000000000000000 6.0.4
+68ea8ab81fc3d67e3efe925c3694644a46b7c111 trytond-6.0.4
+0000000000000000000000000000000000000000 6.0.5
+133f0b26de213e0b5668ae891e176de8f79025fc trytond-6.0.5
+0000000000000000000000000000000000000000 6.0.6
+1719ce1a669285333424c02c9e3e45fd636b995c trytond-6.0.6
+0000000000000000000000000000000000000000 6.0.7
+67fe2d478dbf413873c0919cfd5d6f3f6f4c2275 trytond-6.0.7
+0000000000000000000000000000000000000000 6.0.8
+ed230154446f04aed350b7fd0d416a80145645ee trytond-6.0.8
+0000000000000000000000000000000000000000 6.0.9
+df3e4a189c249ff54e118a4943c03ecaab5fee60 trytond-6.0.9
+923b3073b686c6dc5a921d0561c934adf3eeb879 1.0.0
+9a6434d63616f46520b6fa1b2be31906ff6f4f6a 1.2.0
+de84c1443d4bad908eabb99c381578b988c2117f 1.4.0
+3976912b23dfc5db2525d4c2e55d17f099d9492d 1.6.0
+8aa050da53cbdfabe1353a37da91c011b7fff549 1.8.0
+1876747b3f963ba6011b4bcf6968e681624c6e24 2.0.0
+5364f8ca6cd2cccfb5f7f39c69bb20bae2b5f495 2.2.0
+fe15da23f7333e0e90d2693aadddf6bed53ed602 2.4.0
+d069f9f1cdc3fea39e71415268582abb2b333ea1 2.6.0
+21fbf8bd36096d926c472acfecd3963369204af8 2.8.0
+9197d90b0257ec7c4576a38092fd592b3e87f7a4 3.0.0
+9721289ee2fdaab8b990de9327c3eab87363c88c 3.2.0
+8e5cba59137f9d0a063fa6d7855e09a51bc5889c 3.4.0
+1ac658605d42d82988cfb232afebfe359aba7776 3.6.0
+f4b9c8a84cf61935afec788c3c639982731452ef 3.8.0
+44d8ed92ff90cf98c4c01d37f12d344d9d66e7f1 4.0.0
+94037cff031ef897c9533a579356977c8a3cf695 4.2.0
+763dc5d8e1d7e483edbf9977dd96afc114555555 4.4.0
+d7ed5002e47249d019fbc546f6ac562db44c54f2 4.6.0
+2a2b48ea60fbb5201ea12443000d3a106a2fa27c 4.8.0
+70ade9d1fe04c734fe2dd7d35dd75b13f1af902a 5.0.0
+d5652dee45a43fccc1f33d39050af6e00e073273 5.2.0
+9f3fbb33df184ca19350cc71054dd9afd55f1cb7 5.4.0
+45d3f736ffb4396ee0dac0e2110fcc17237337ba 5.6.0
+df9de0ceeb27b38b165da7526accad0ad6682e86 5.8.0
+d18d03f0c540dfd2aae81dfaac048378a62c0ef6 6.0.0
+6cdc11292120ffb6df929721adfd738c4916a594 6.0.1
+23df79b60988e64c45be329933d803e0add7ae20 6.0.2
+5ab29a68b330847559add6204df341aeec38c223 6.0.3
+4493ce6c2dfcebde5701360689c635dbd6253d10 6.0.4
+0a8b71b80cc781e88f6a5a7467be9cdb3de50562 6.0.5
+be96d41f66a7bae727ecaf072a955ada01cd73e8 6.0.6
+0d0d910f4edfa1e493d8526dea6bc5f2ad78c30e 6.0.7
+1f7935eb899fb1ccdd363a085ba3a7a24349a3be 6.0.8
+375c664763440caa3f3ac4cdff2f694eedab7f7c 6.0.9
+a8f9ff596e3476c4fa73002524a78011b62b7fb8 6.0.10
+986c3f1e1d5ee57983adf34bf84c348abdba5b42 6.0.11
+e2cd492204aa2dd300eaaad5caca022b0114bea2 6.0.12
+1cbf7901b52d92f993ceba19357085386475c08d 6.0.13
+1474928ec1aa12d34e5fd79675bb284890bafd76 6.0.14
+0ee8d81a43a12bdd3064bcc100ef4a35ab86bfdb 6.0.15
+d1f3f6a0d5722332cddd2cb0837a266e5f5a1881 6.0.16
+dd458525c9d4c92eca991b832f06ec46a639c3a4 6.0.17
+40c3f7f6d487197698ac644ef28fa09dbce7e46a 6.0.18
+bd7b3f9a3c2f9cda09c2d5f89ed1c1f92dd78ff3 6.0.19
+4b448222df4c6c37b0223112c0c2c14f09675d34 6.0.20
+90566b9897fd57fb36e427dd7d8f2bbfa0a9ed5f 6.0.21
+0000000000000000000000000000000000000000 1.0.0
+923b3073b686c6dc5a921d0561c934adf3eeb879 tryton-1.0.0
+0000000000000000000000000000000000000000 1.2.0
+9a6434d63616f46520b6fa1b2be31906ff6f4f6a tryton-1.2.0
+0000000000000000000000000000000000000000 1.4.0
+de84c1443d4bad908eabb99c381578b988c2117f tryton-1.4.0
+0000000000000000000000000000000000000000 1.6.0
+3976912b23dfc5db2525d4c2e55d17f099d9492d tryton-1.6.0
+0000000000000000000000000000000000000000 1.8.0
+8aa050da53cbdfabe1353a37da91c011b7fff549 tryton-1.8.0
+0000000000000000000000000000000000000000 2.0.0
+1876747b3f963ba6011b4bcf6968e681624c6e24 tryton-2.0.0
+0000000000000000000000000000000000000000 2.2.0
+5364f8ca6cd2cccfb5f7f39c69bb20bae2b5f495 tryton-2.2.0
+0000000000000000000000000000000000000000 2.4.0
+fe15da23f7333e0e90d2693aadddf6bed53ed602 tryton-2.4.0
+0000000000000000000000000000000000000000 2.6.0
+d069f9f1cdc3fea39e71415268582abb2b333ea1 tryton-2.6.0
+0000000000000000000000000000000000000000 2.8.0
+21fbf8bd36096d926c472acfecd3963369204af8 tryton-2.8.0
+0000000000000000000000000000000000000000 3.0.0
+9197d90b0257ec7c4576a38092fd592b3e87f7a4 tryton-3.0.0
+0000000000000000000000000000000000000000 3.2.0
+9721289ee2fdaab8b990de9327c3eab87363c88c tryton-3.2.0
+0000000000000000000000000000000000000000 3.4.0
+8e5cba59137f9d0a063fa6d7855e09a51bc5889c tryton-3.4.0
+0000000000000000000000000000000000000000 3.6.0
+1ac658605d42d82988cfb232afebfe359aba7776 tryton-3.6.0
+0000000000000000000000000000000000000000 3.8.0
+f4b9c8a84cf61935afec788c3c639982731452ef tryton-3.8.0
+0000000000000000000000000000000000000000 4.0.0
+44d8ed92ff90cf98c4c01d37f12d344d9d66e7f1 tryton-4.0.0
+0000000000000000000000000000000000000000 4.2.0
+94037cff031ef897c9533a579356977c8a3cf695 tryton-4.2.0
+0000000000000000000000000000000000000000 4.4.0
+763dc5d8e1d7e483edbf9977dd96afc114555555 tryton-4.4.0
+0000000000000000000000000000000000000000 4.6.0
+d7ed5002e47249d019fbc546f6ac562db44c54f2 tryton-4.6.0
+0000000000000000000000000000000000000000 4.8.0
+2a2b48ea60fbb5201ea12443000d3a106a2fa27c tryton-4.8.0
+0000000000000000000000000000000000000000 5.0.0
+70ade9d1fe04c734fe2dd7d35dd75b13f1af902a tryton-5.0.0
+0000000000000000000000000000000000000000 5.2.0
+d5652dee45a43fccc1f33d39050af6e00e073273 tryton-5.2.0
+0000000000000000000000000000000000000000 5.4.0
+9f3fbb33df184ca19350cc71054dd9afd55f1cb7 tryton-5.4.0
+0000000000000000000000000000000000000000 5.6.0
+45d3f736ffb4396ee0dac0e2110fcc17237337ba tryton-5.6.0
+0000000000000000000000000000000000000000 5.8.0
+df9de0ceeb27b38b165da7526accad0ad6682e86 tryton-5.8.0
+0000000000000000000000000000000000000000 6.0.0
+d18d03f0c540dfd2aae81dfaac048378a62c0ef6 tryton-6.0.0
+0000000000000000000000000000000000000000 6.0.1
+6cdc11292120ffb6df929721adfd738c4916a594 tryton-6.0.1
+0000000000000000000000000000000000000000 6.0.10
+a8f9ff596e3476c4fa73002524a78011b62b7fb8 tryton-6.0.10
+0000000000000000000000000000000000000000 6.0.11
+986c3f1e1d5ee57983adf34bf84c348abdba5b42 tryton-6.0.11
+0000000000000000000000000000000000000000 6.0.12
+e2cd492204aa2dd300eaaad5caca022b0114bea2 tryton-6.0.12
+0000000000000000000000000000000000000000 6.0.13
+1cbf7901b52d92f993ceba19357085386475c08d tryton-6.0.13
+0000000000000000000000000000000000000000 6.0.14
+1474928ec1aa12d34e5fd79675bb284890bafd76 tryton-6.0.14
+0000000000000000000000000000000000000000 6.0.15
+0ee8d81a43a12bdd3064bcc100ef4a35ab86bfdb tryton-6.0.15
+0000000000000000000000000000000000000000 6.0.16
+d1f3f6a0d5722332cddd2cb0837a266e5f5a1881 tryton-6.0.16
+0000000000000000000000000000000000000000 6.0.17
+dd458525c9d4c92eca991b832f06ec46a639c3a4 tryton-6.0.17
+0000000000000000000000000000000000000000 6.0.18
+40c3f7f6d487197698ac644ef28fa09dbce7e46a tryton-6.0.18
+0000000000000000000000000000000000000000 6.0.19
+bd7b3f9a3c2f9cda09c2d5f89ed1c1f92dd78ff3 tryton-6.0.19
+0000000000000000000000000000000000000000 6.0.2
+23df79b60988e64c45be329933d803e0add7ae20 tryton-6.0.2
+0000000000000000000000000000000000000000 6.0.20
+4b448222df4c6c37b0223112c0c2c14f09675d34 tryton-6.0.20
+0000000000000000000000000000000000000000 6.0.21
+90566b9897fd57fb36e427dd7d8f2bbfa0a9ed5f tryton-6.0.21
+0000000000000000000000000000000000000000 6.0.3
+5ab29a68b330847559add6204df341aeec38c223 tryton-6.0.3
+0000000000000000000000000000000000000000 6.0.4
+4493ce6c2dfcebde5701360689c635dbd6253d10 tryton-6.0.4
+0000000000000000000000000000000000000000 6.0.5
+0a8b71b80cc781e88f6a5a7467be9cdb3de50562 tryton-6.0.5
+0000000000000000000000000000000000000000 6.0.6
+be96d41f66a7bae727ecaf072a955ada01cd73e8 tryton-6.0.6
+0000000000000000000000000000000000000000 6.0.7
+0d0d910f4edfa1e493d8526dea6bc5f2ad78c30e tryton-6.0.7
+0000000000000000000000000000000000000000 6.0.8
+1f7935eb899fb1ccdd363a085ba3a7a24349a3be tryton-6.0.8
+0000000000000000000000000000000000000000 6.0.9
+375c664763440caa3f3ac4cdff2f694eedab7f7c tryton-6.0.9
diff --git a/modules/purchase_shipment_cost/.drone.yml b/modules/purchase_shipment_cost/.drone.yml
new file mode 100644
index 0000000000..2049d30a49
--- /dev/null
+++ b/modules/purchase_shipment_cost/.drone.yml
@@ -0,0 +1,68 @@
+clone:
+ hg:
+ image: plugins/hg
+ environment:
+ - HG_SHARE_POOL=/root/.cache/hg
+ volumes:
+ - cache:/root/.cache
+
+pipeline:
+ tox:
+ image: ${IMAGE}
+ environment:
+ - CFLAGS=-O0
+ - DB_CACHE=/cache
+ - TOX_TESTENV_PASSENV=CFLAGS DB_CACHE CI_BUILD_NUMBER CI_JOB_NUMBER CI_JOB_ID
+ - POSTGRESQL_URI=postgresql://postgres@postgresql:5432/
+ commands:
+ - echo "[extensions]" >> /root/.hgrc
+ - echo "hgext.share =" >> /root/.hgrc
+ - echo "[share]" >> /root/.hgrc
+ - echo "pool = /root/.cache/hg" >> /root/.hgrc
+ - pip install tox
+ - tox -e "${TOXENV}-${DATABASE}"
+ volumes:
+ - cache:/root/.cache
+ check_dist:
+ image: ${IMAGE}
+ commands:
+ - pip install twine
+ - python setup.py sdist
+ - twine check dist/*
+
+services:
+ postgresql:
+ image: postgres
+ environment:
+ - POSTGRES_HOST_AUTH_METHOD=trust
+ command: "-c fsync=off -c synchronous_commit=off -c full_page_writes=off"
+ when:
+ matrix:
+ DATABASE: postgresql
+
+matrix:
+ include:
+ - IMAGE: python:3.6
+ TOXENV: py36
+ DATABASE: sqlite
+ - IMAGE: python:3.6
+ TOXENV: py36
+ DATABASE: postgresql
+ - IMAGE: python:3.7
+ TOXENV: py37
+ DATABASE: sqlite
+ - IMAGE: python:3.7
+ TOXENV: py37
+ DATABASE: postgresql
+ - IMAGE: python:3.8
+ TOXENV: py38
+ DATABASE: sqlite
+ - IMAGE: python:3.8
+ TOXENV: py38
+ DATABASE: postgresql
+ - IMAGE: python:3.9
+ TOXENV: py39
+ DATABASE: sqlite
+ - IMAGE: python:3.9
+ TOXENV: py39
+ DATABASE: postgresql
diff --git a/modules/purchase_shipment_cost/.flake8 b/modules/purchase_shipment_cost/.flake8
new file mode 100644
index 0000000000..fa6b4f66d1
--- /dev/null
+++ b/modules/purchase_shipment_cost/.flake8
@@ -0,0 +1,2 @@
+[flake8]
+ignore=E123,E124,E126,E128,E741,W503
diff --git a/modules/purchase_shipment_cost/CHANGELOG b/modules/purchase_shipment_cost/CHANGELOG
new file mode 100644
index 0000000000..e8c2f58cb2
--- /dev/null
+++ b/modules/purchase_shipment_cost/CHANGELOG
@@ -0,0 +1,60 @@
+Version 6.0.0 - 2021-05-03
+* Bug fixes (see mercurial logs for details)
+* Simplify manual alteration of shipment cost
+
+Version 5.8.0 - 2020-11-02
+* Bug fixes (see mercurial logs for details)
+* Remove support for Python 3.5
+
+Version 5.6.0 - 2020-05-04
+* Bug fixes (see mercurial logs for details)
+
+Version 5.4.0 - 2019-11-04
+* Bug fixes (see mercurial logs for details)
+
+Version 5.2.0 - 2019-05-06
+* Bug fixes (see mercurial logs for details)
+
+Version 5.0.0 - 2018-10-01
+* Bug fixes (see mercurial logs for details)
+* Remove support for Python 2.7
+
+Version 4.8.0 - 2018-04-23
+* Bug fixes (see mercurial logs for details)
+
+Version 4.6.0 - 2017-10-30
+* Bug fixes (see mercurial logs for details)
+
+Version 4.4.0 - 2017-05-01
+* Bug fixes (see mercurial logs for details)
+
+Version 4.2.0 - 2016-11-28
+* Bug fixes (see mercurial logs for details)
+
+Version 4.0.0 - 2016-05-02
+* Bug fixes (see mercurial logs for details)
+* Add Python3 support
+
+Version 3.8.0 - 2015-11-02
+* Bug fixes (see mercurial logs for details)
+
+Version 3.6.0 - 2015-04-20
+* Bug fixes (see mercurial logs for details)
+* Add support for PyPy
+Version 3.4.0 - 2014-10-20
+* Bug fixes (see mercurial logs for details)
+
+Version 3.2.0 - 2014-04-21
+* Bug fixes (see mercurial logs for details)
+
+Version 3.0.0 - 2013-10-21
+* Bug fixes (see mercurial logs for details)
+
+Version 2.8.0 - 2013-04-22
+* Bug fixes (see mercurial logs for details)
+
+Version 2.6.0 - 2012-10-22
+* Bug fixes (see mercurial logs for details)
+
+Version 2.4.0 - 2012-04-24
+* Initial release
diff --git a/modules/purchase_shipment_cost/COPYRIGHT b/modules/purchase_shipment_cost/COPYRIGHT
new file mode 100644
index 0000000000..12f6702805
--- /dev/null
+++ b/modules/purchase_shipment_cost/COPYRIGHT
@@ -0,0 +1,17 @@
+Copyright (C) 2011-2021 Cédric Krier.
+Copyright (C) 2011-2020 Bertrand Chenal.
+Copyright (C) 2011-2020 Nicolas Évrard.
+Copyright (C) 2011-2021 B2CK SPRL.
+
+This program is free software: you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation, either version 3 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program. If not, see .
diff --git a/modules/purchase_shipment_cost/LICENSE b/modules/purchase_shipment_cost/LICENSE
new file mode 100644
index 0000000000..94a9ed024d
--- /dev/null
+++ b/modules/purchase_shipment_cost/LICENSE
@@ -0,0 +1,674 @@
+ GNU GENERAL PUBLIC LICENSE
+ Version 3, 29 June 2007
+
+ Copyright (C) 2007 Free Software Foundation, Inc.
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+ Preamble
+
+ The GNU General Public License is a free, copyleft license for
+software and other kinds of works.
+
+ The licenses for most software and other practical works are designed
+to take away your freedom to share and change the works. By contrast,
+the GNU General Public License is intended to guarantee your freedom to
+share and change all versions of a program--to make sure it remains free
+software for all its users. We, the Free Software Foundation, use the
+GNU General Public License for most of our software; it applies also to
+any other work released this way by its authors. You can apply it to
+your programs, too.
+
+ When we speak of free software, we are referring to freedom, not
+price. Our General Public Licenses are designed to make sure that you
+have the freedom to distribute copies of free software (and charge for
+them if you wish), that you receive source code or can get it if you
+want it, that you can change the software or use pieces of it in new
+free programs, and that you know you can do these things.
+
+ To protect your rights, we need to prevent others from denying you
+these rights or asking you to surrender the rights. Therefore, you have
+certain responsibilities if you distribute copies of the software, or if
+you modify it: responsibilities to respect the freedom of others.
+
+ For example, if you distribute copies of such a program, whether
+gratis or for a fee, you must pass on to the recipients the same
+freedoms that you received. You must make sure that they, too, receive
+or can get the source code. And you must show them these terms so they
+know their rights.
+
+ Developers that use the GNU GPL protect your rights with two steps:
+(1) assert copyright on the software, and (2) offer you this License
+giving you legal permission to copy, distribute and/or modify it.
+
+ For the developers' and authors' protection, the GPL clearly explains
+that there is no warranty for this free software. For both users' and
+authors' sake, the GPL requires that modified versions be marked as
+changed, so that their problems will not be attributed erroneously to
+authors of previous versions.
+
+ Some devices are designed to deny users access to install or run
+modified versions of the software inside them, although the manufacturer
+can do so. This is fundamentally incompatible with the aim of
+protecting users' freedom to change the software. The systematic
+pattern of such abuse occurs in the area of products for individuals to
+use, which is precisely where it is most unacceptable. Therefore, we
+have designed this version of the GPL to prohibit the practice for those
+products. If such problems arise substantially in other domains, we
+stand ready to extend this provision to those domains in future versions
+of the GPL, as needed to protect the freedom of users.
+
+ Finally, every program is threatened constantly by software patents.
+States should not allow patents to restrict development and use of
+software on general-purpose computers, but in those that do, we wish to
+avoid the special danger that patents applied to a free program could
+make it effectively proprietary. To prevent this, the GPL assures that
+patents cannot be used to render the program non-free.
+
+ The precise terms and conditions for copying, distribution and
+modification follow.
+
+ TERMS AND CONDITIONS
+
+ 0. Definitions.
+
+ "This License" refers to version 3 of the GNU General Public License.
+
+ "Copyright" also means copyright-like laws that apply to other kinds of
+works, such as semiconductor masks.
+
+ "The Program" refers to any copyrightable work licensed under this
+License. Each licensee is addressed as "you". "Licensees" and
+"recipients" may be individuals or organizations.
+
+ To "modify" a work means to copy from or adapt all or part of the work
+in a fashion requiring copyright permission, other than the making of an
+exact copy. The resulting work is called a "modified version" of the
+earlier work or a work "based on" the earlier work.
+
+ A "covered work" means either the unmodified Program or a work based
+on the Program.
+
+ To "propagate" a work means to do anything with it that, without
+permission, would make you directly or secondarily liable for
+infringement under applicable copyright law, except executing it on a
+computer or modifying a private copy. Propagation includes copying,
+distribution (with or without modification), making available to the
+public, and in some countries other activities as well.
+
+ To "convey" a work means any kind of propagation that enables other
+parties to make or receive copies. Mere interaction with a user through
+a computer network, with no transfer of a copy, is not conveying.
+
+ An interactive user interface displays "Appropriate Legal Notices"
+to the extent that it includes a convenient and prominently visible
+feature that (1) displays an appropriate copyright notice, and (2)
+tells the user that there is no warranty for the work (except to the
+extent that warranties are provided), that licensees may convey the
+work under this License, and how to view a copy of this License. If
+the interface presents a list of user commands or options, such as a
+menu, a prominent item in the list meets this criterion.
+
+ 1. Source Code.
+
+ The "source code" for a work means the preferred form of the work
+for making modifications to it. "Object code" means any non-source
+form of a work.
+
+ A "Standard Interface" means an interface that either is an official
+standard defined by a recognized standards body, or, in the case of
+interfaces specified for a particular programming language, one that
+is widely used among developers working in that language.
+
+ The "System Libraries" of an executable work include anything, other
+than the work as a whole, that (a) is included in the normal form of
+packaging a Major Component, but which is not part of that Major
+Component, and (b) serves only to enable use of the work with that
+Major Component, or to implement a Standard Interface for which an
+implementation is available to the public in source code form. A
+"Major Component", in this context, means a major essential component
+(kernel, window system, and so on) of the specific operating system
+(if any) on which the executable work runs, or a compiler used to
+produce the work, or an object code interpreter used to run it.
+
+ The "Corresponding Source" for a work in object code form means all
+the source code needed to generate, install, and (for an executable
+work) run the object code and to modify the work, including scripts to
+control those activities. However, it does not include the work's
+System Libraries, or general-purpose tools or generally available free
+programs which are used unmodified in performing those activities but
+which are not part of the work. For example, Corresponding Source
+includes interface definition files associated with source files for
+the work, and the source code for shared libraries and dynamically
+linked subprograms that the work is specifically designed to require,
+such as by intimate data communication or control flow between those
+subprograms and other parts of the work.
+
+ The Corresponding Source need not include anything that users
+can regenerate automatically from other parts of the Corresponding
+Source.
+
+ The Corresponding Source for a work in source code form is that
+same work.
+
+ 2. Basic Permissions.
+
+ All rights granted under this License are granted for the term of
+copyright on the Program, and are irrevocable provided the stated
+conditions are met. This License explicitly affirms your unlimited
+permission to run the unmodified Program. The output from running a
+covered work is covered by this License only if the output, given its
+content, constitutes a covered work. This License acknowledges your
+rights of fair use or other equivalent, as provided by copyright law.
+
+ You may make, run and propagate covered works that you do not
+convey, without conditions so long as your license otherwise remains
+in force. You may convey covered works to others for the sole purpose
+of having them make modifications exclusively for you, or provide you
+with facilities for running those works, provided that you comply with
+the terms of this License in conveying all material for which you do
+not control copyright. Those thus making or running the covered works
+for you must do so exclusively on your behalf, under your direction
+and control, on terms that prohibit them from making any copies of
+your copyrighted material outside their relationship with you.
+
+ Conveying under any other circumstances is permitted solely under
+the conditions stated below. Sublicensing is not allowed; section 10
+makes it unnecessary.
+
+ 3. Protecting Users' Legal Rights From Anti-Circumvention Law.
+
+ No covered work shall be deemed part of an effective technological
+measure under any applicable law fulfilling obligations under article
+11 of the WIPO copyright treaty adopted on 20 December 1996, or
+similar laws prohibiting or restricting circumvention of such
+measures.
+
+ When you convey a covered work, you waive any legal power to forbid
+circumvention of technological measures to the extent such circumvention
+is effected by exercising rights under this License with respect to
+the covered work, and you disclaim any intention to limit operation or
+modification of the work as a means of enforcing, against the work's
+users, your or third parties' legal rights to forbid circumvention of
+technological measures.
+
+ 4. Conveying Verbatim Copies.
+
+ You may convey verbatim copies of the Program's source code as you
+receive it, in any medium, provided that you conspicuously and
+appropriately publish on each copy an appropriate copyright notice;
+keep intact all notices stating that this License and any
+non-permissive terms added in accord with section 7 apply to the code;
+keep intact all notices of the absence of any warranty; and give all
+recipients a copy of this License along with the Program.
+
+ You may charge any price or no price for each copy that you convey,
+and you may offer support or warranty protection for a fee.
+
+ 5. Conveying Modified Source Versions.
+
+ You may convey a work based on the Program, or the modifications to
+produce it from the Program, in the form of source code under the
+terms of section 4, provided that you also meet all of these conditions:
+
+ a) The work must carry prominent notices stating that you modified
+ it, and giving a relevant date.
+
+ b) The work must carry prominent notices stating that it is
+ released under this License and any conditions added under section
+ 7. This requirement modifies the requirement in section 4 to
+ "keep intact all notices".
+
+ c) You must license the entire work, as a whole, under this
+ License to anyone who comes into possession of a copy. This
+ License will therefore apply, along with any applicable section 7
+ additional terms, to the whole of the work, and all its parts,
+ regardless of how they are packaged. This License gives no
+ permission to license the work in any other way, but it does not
+ invalidate such permission if you have separately received it.
+
+ d) If the work has interactive user interfaces, each must display
+ Appropriate Legal Notices; however, if the Program has interactive
+ interfaces that do not display Appropriate Legal Notices, your
+ work need not make them do so.
+
+ A compilation of a covered work with other separate and independent
+works, which are not by their nature extensions of the covered work,
+and which are not combined with it such as to form a larger program,
+in or on a volume of a storage or distribution medium, is called an
+"aggregate" if the compilation and its resulting copyright are not
+used to limit the access or legal rights of the compilation's users
+beyond what the individual works permit. Inclusion of a covered work
+in an aggregate does not cause this License to apply to the other
+parts of the aggregate.
+
+ 6. Conveying Non-Source Forms.
+
+ You may convey a covered work in object code form under the terms
+of sections 4 and 5, provided that you also convey the
+machine-readable Corresponding Source under the terms of this License,
+in one of these ways:
+
+ a) Convey the object code in, or embodied in, a physical product
+ (including a physical distribution medium), accompanied by the
+ Corresponding Source fixed on a durable physical medium
+ customarily used for software interchange.
+
+ b) Convey the object code in, or embodied in, a physical product
+ (including a physical distribution medium), accompanied by a
+ written offer, valid for at least three years and valid for as
+ long as you offer spare parts or customer support for that product
+ model, to give anyone who possesses the object code either (1) a
+ copy of the Corresponding Source for all the software in the
+ product that is covered by this License, on a durable physical
+ medium customarily used for software interchange, for a price no
+ more than your reasonable cost of physically performing this
+ conveying of source, or (2) access to copy the
+ Corresponding Source from a network server at no charge.
+
+ c) Convey individual copies of the object code with a copy of the
+ written offer to provide the Corresponding Source. This
+ alternative is allowed only occasionally and noncommercially, and
+ only if you received the object code with such an offer, in accord
+ with subsection 6b.
+
+ d) Convey the object code by offering access from a designated
+ place (gratis or for a charge), and offer equivalent access to the
+ Corresponding Source in the same way through the same place at no
+ further charge. You need not require recipients to copy the
+ Corresponding Source along with the object code. If the place to
+ copy the object code is a network server, the Corresponding Source
+ may be on a different server (operated by you or a third party)
+ that supports equivalent copying facilities, provided you maintain
+ clear directions next to the object code saying where to find the
+ Corresponding Source. Regardless of what server hosts the
+ Corresponding Source, you remain obligated to ensure that it is
+ available for as long as needed to satisfy these requirements.
+
+ e) Convey the object code using peer-to-peer transmission, provided
+ you inform other peers where the object code and Corresponding
+ Source of the work are being offered to the general public at no
+ charge under subsection 6d.
+
+ A separable portion of the object code, whose source code is excluded
+from the Corresponding Source as a System Library, need not be
+included in conveying the object code work.
+
+ A "User Product" is either (1) a "consumer product", which means any
+tangible personal property which is normally used for personal, family,
+or household purposes, or (2) anything designed or sold for incorporation
+into a dwelling. In determining whether a product is a consumer product,
+doubtful cases shall be resolved in favor of coverage. For a particular
+product received by a particular user, "normally used" refers to a
+typical or common use of that class of product, regardless of the status
+of the particular user or of the way in which the particular user
+actually uses, or expects or is expected to use, the product. A product
+is a consumer product regardless of whether the product has substantial
+commercial, industrial or non-consumer uses, unless such uses represent
+the only significant mode of use of the product.
+
+ "Installation Information" for a User Product means any methods,
+procedures, authorization keys, or other information required to install
+and execute modified versions of a covered work in that User Product from
+a modified version of its Corresponding Source. The information must
+suffice to ensure that the continued functioning of the modified object
+code is in no case prevented or interfered with solely because
+modification has been made.
+
+ If you convey an object code work under this section in, or with, or
+specifically for use in, a User Product, and the conveying occurs as
+part of a transaction in which the right of possession and use of the
+User Product is transferred to the recipient in perpetuity or for a
+fixed term (regardless of how the transaction is characterized), the
+Corresponding Source conveyed under this section must be accompanied
+by the Installation Information. But this requirement does not apply
+if neither you nor any third party retains the ability to install
+modified object code on the User Product (for example, the work has
+been installed in ROM).
+
+ The requirement to provide Installation Information does not include a
+requirement to continue to provide support service, warranty, or updates
+for a work that has been modified or installed by the recipient, or for
+the User Product in which it has been modified or installed. Access to a
+network may be denied when the modification itself materially and
+adversely affects the operation of the network or violates the rules and
+protocols for communication across the network.
+
+ Corresponding Source conveyed, and Installation Information provided,
+in accord with this section must be in a format that is publicly
+documented (and with an implementation available to the public in
+source code form), and must require no special password or key for
+unpacking, reading or copying.
+
+ 7. Additional Terms.
+
+ "Additional permissions" are terms that supplement the terms of this
+License by making exceptions from one or more of its conditions.
+Additional permissions that are applicable to the entire Program shall
+be treated as though they were included in this License, to the extent
+that they are valid under applicable law. If additional permissions
+apply only to part of the Program, that part may be used separately
+under those permissions, but the entire Program remains governed by
+this License without regard to the additional permissions.
+
+ When you convey a copy of a covered work, you may at your option
+remove any additional permissions from that copy, or from any part of
+it. (Additional permissions may be written to require their own
+removal in certain cases when you modify the work.) You may place
+additional permissions on material, added by you to a covered work,
+for which you have or can give appropriate copyright permission.
+
+ Notwithstanding any other provision of this License, for material you
+add to a covered work, you may (if authorized by the copyright holders of
+that material) supplement the terms of this License with terms:
+
+ a) Disclaiming warranty or limiting liability differently from the
+ terms of sections 15 and 16 of this License; or
+
+ b) Requiring preservation of specified reasonable legal notices or
+ author attributions in that material or in the Appropriate Legal
+ Notices displayed by works containing it; or
+
+ c) Prohibiting misrepresentation of the origin of that material, or
+ requiring that modified versions of such material be marked in
+ reasonable ways as different from the original version; or
+
+ d) Limiting the use for publicity purposes of names of licensors or
+ authors of the material; or
+
+ e) Declining to grant rights under trademark law for use of some
+ trade names, trademarks, or service marks; or
+
+ f) Requiring indemnification of licensors and authors of that
+ material by anyone who conveys the material (or modified versions of
+ it) with contractual assumptions of liability to the recipient, for
+ any liability that these contractual assumptions directly impose on
+ those licensors and authors.
+
+ All other non-permissive additional terms are considered "further
+restrictions" within the meaning of section 10. If the Program as you
+received it, or any part of it, contains a notice stating that it is
+governed by this License along with a term that is a further
+restriction, you may remove that term. If a license document contains
+a further restriction but permits relicensing or conveying under this
+License, you may add to a covered work material governed by the terms
+of that license document, provided that the further restriction does
+not survive such relicensing or conveying.
+
+ If you add terms to a covered work in accord with this section, you
+must place, in the relevant source files, a statement of the
+additional terms that apply to those files, or a notice indicating
+where to find the applicable terms.
+
+ Additional terms, permissive or non-permissive, may be stated in the
+form of a separately written license, or stated as exceptions;
+the above requirements apply either way.
+
+ 8. Termination.
+
+ You may not propagate or modify a covered work except as expressly
+provided under this License. Any attempt otherwise to propagate or
+modify it is void, and will automatically terminate your rights under
+this License (including any patent licenses granted under the third
+paragraph of section 11).
+
+ However, if you cease all violation of this License, then your
+license from a particular copyright holder is reinstated (a)
+provisionally, unless and until the copyright holder explicitly and
+finally terminates your license, and (b) permanently, if the copyright
+holder fails to notify you of the violation by some reasonable means
+prior to 60 days after the cessation.
+
+ Moreover, your license from a particular copyright holder is
+reinstated permanently if the copyright holder notifies you of the
+violation by some reasonable means, this is the first time you have
+received notice of violation of this License (for any work) from that
+copyright holder, and you cure the violation prior to 30 days after
+your receipt of the notice.
+
+ Termination of your rights under this section does not terminate the
+licenses of parties who have received copies or rights from you under
+this License. If your rights have been terminated and not permanently
+reinstated, you do not qualify to receive new licenses for the same
+material under section 10.
+
+ 9. Acceptance Not Required for Having Copies.
+
+ You are not required to accept this License in order to receive or
+run a copy of the Program. Ancillary propagation of a covered work
+occurring solely as a consequence of using peer-to-peer transmission
+to receive a copy likewise does not require acceptance. However,
+nothing other than this License grants you permission to propagate or
+modify any covered work. These actions infringe copyright if you do
+not accept this License. Therefore, by modifying or propagating a
+covered work, you indicate your acceptance of this License to do so.
+
+ 10. Automatic Licensing of Downstream Recipients.
+
+ Each time you convey a covered work, the recipient automatically
+receives a license from the original licensors, to run, modify and
+propagate that work, subject to this License. You are not responsible
+for enforcing compliance by third parties with this License.
+
+ An "entity transaction" is a transaction transferring control of an
+organization, or substantially all assets of one, or subdividing an
+organization, or merging organizations. If propagation of a covered
+work results from an entity transaction, each party to that
+transaction who receives a copy of the work also receives whatever
+licenses to the work the party's predecessor in interest had or could
+give under the previous paragraph, plus a right to possession of the
+Corresponding Source of the work from the predecessor in interest, if
+the predecessor has it or can get it with reasonable efforts.
+
+ You may not impose any further restrictions on the exercise of the
+rights granted or affirmed under this License. For example, you may
+not impose a license fee, royalty, or other charge for exercise of
+rights granted under this License, and you may not initiate litigation
+(including a cross-claim or counterclaim in a lawsuit) alleging that
+any patent claim is infringed by making, using, selling, offering for
+sale, or importing the Program or any portion of it.
+
+ 11. Patents.
+
+ A "contributor" is a copyright holder who authorizes use under this
+License of the Program or a work on which the Program is based. The
+work thus licensed is called the contributor's "contributor version".
+
+ A contributor's "essential patent claims" are all patent claims
+owned or controlled by the contributor, whether already acquired or
+hereafter acquired, that would be infringed by some manner, permitted
+by this License, of making, using, or selling its contributor version,
+but do not include claims that would be infringed only as a
+consequence of further modification of the contributor version. For
+purposes of this definition, "control" includes the right to grant
+patent sublicenses in a manner consistent with the requirements of
+this License.
+
+ Each contributor grants you a non-exclusive, worldwide, royalty-free
+patent license under the contributor's essential patent claims, to
+make, use, sell, offer for sale, import and otherwise run, modify and
+propagate the contents of its contributor version.
+
+ In the following three paragraphs, a "patent license" is any express
+agreement or commitment, however denominated, not to enforce a patent
+(such as an express permission to practice a patent or covenant not to
+sue for patent infringement). To "grant" such a patent license to a
+party means to make such an agreement or commitment not to enforce a
+patent against the party.
+
+ If you convey a covered work, knowingly relying on a patent license,
+and the Corresponding Source of the work is not available for anyone
+to copy, free of charge and under the terms of this License, through a
+publicly available network server or other readily accessible means,
+then you must either (1) cause the Corresponding Source to be so
+available, or (2) arrange to deprive yourself of the benefit of the
+patent license for this particular work, or (3) arrange, in a manner
+consistent with the requirements of this License, to extend the patent
+license to downstream recipients. "Knowingly relying" means you have
+actual knowledge that, but for the patent license, your conveying the
+covered work in a country, or your recipient's use of the covered work
+in a country, would infringe one or more identifiable patents in that
+country that you have reason to believe are valid.
+
+ If, pursuant to or in connection with a single transaction or
+arrangement, you convey, or propagate by procuring conveyance of, a
+covered work, and grant a patent license to some of the parties
+receiving the covered work authorizing them to use, propagate, modify
+or convey a specific copy of the covered work, then the patent license
+you grant is automatically extended to all recipients of the covered
+work and works based on it.
+
+ A patent license is "discriminatory" if it does not include within
+the scope of its coverage, prohibits the exercise of, or is
+conditioned on the non-exercise of one or more of the rights that are
+specifically granted under this License. You may not convey a covered
+work if you are a party to an arrangement with a third party that is
+in the business of distributing software, under which you make payment
+to the third party based on the extent of your activity of conveying
+the work, and under which the third party grants, to any of the
+parties who would receive the covered work from you, a discriminatory
+patent license (a) in connection with copies of the covered work
+conveyed by you (or copies made from those copies), or (b) primarily
+for and in connection with specific products or compilations that
+contain the covered work, unless you entered into that arrangement,
+or that patent license was granted, prior to 28 March 2007.
+
+ Nothing in this License shall be construed as excluding or limiting
+any implied license or other defenses to infringement that may
+otherwise be available to you under applicable patent law.
+
+ 12. No Surrender of Others' Freedom.
+
+ If conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License. If you cannot convey a
+covered work so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you may
+not convey it at all. For example, if you agree to terms that obligate you
+to collect a royalty for further conveying from those to whom you convey
+the Program, the only way you could satisfy both those terms and this
+License would be to refrain entirely from conveying the Program.
+
+ 13. Use with the GNU Affero General Public License.
+
+ Notwithstanding any other provision of this License, you have
+permission to link or combine any covered work with a work licensed
+under version 3 of the GNU Affero General Public License into a single
+combined work, and to convey the resulting work. The terms of this
+License will continue to apply to the part which is the covered work,
+but the special requirements of the GNU Affero General Public License,
+section 13, concerning interaction through a network will apply to the
+combination as such.
+
+ 14. Revised Versions of this License.
+
+ The Free Software Foundation may publish revised and/or new versions of
+the GNU General Public License from time to time. Such new versions will
+be similar in spirit to the present version, but may differ in detail to
+address new problems or concerns.
+
+ Each version is given a distinguishing version number. If the
+Program specifies that a certain numbered version of the GNU General
+Public License "or any later version" applies to it, you have the
+option of following the terms and conditions either of that numbered
+version or of any later version published by the Free Software
+Foundation. If the Program does not specify a version number of the
+GNU General Public License, you may choose any version ever published
+by the Free Software Foundation.
+
+ If the Program specifies that a proxy can decide which future
+versions of the GNU General Public License can be used, that proxy's
+public statement of acceptance of a version permanently authorizes you
+to choose that version for the Program.
+
+ Later license versions may give you additional or different
+permissions. However, no additional obligations are imposed on any
+author or copyright holder as a result of your choosing to follow a
+later version.
+
+ 15. Disclaimer of Warranty.
+
+ THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY
+APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT
+HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY
+OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO,
+THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM
+IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF
+ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
+
+ 16. Limitation of Liability.
+
+ IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS
+THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY
+GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE
+USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF
+DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD
+PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS),
+EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF
+SUCH DAMAGES.
+
+ 17. Interpretation of Sections 15 and 16.
+
+ If the disclaimer of warranty and limitation of liability provided
+above cannot be given local legal effect according to their terms,
+reviewing courts shall apply local law that most closely approximates
+an absolute waiver of all civil liability in connection with the
+Program, unless a warranty or assumption of liability accompanies a
+copy of the Program in return for a fee.
+
+ END OF TERMS AND CONDITIONS
+
+ How to Apply These Terms to Your New Programs
+
+ If you develop a new program, and you want it to be of the greatest
+possible use to the public, the best way to achieve this is to make it
+free software which everyone can redistribute and change under these terms.
+
+ To do so, attach the following notices to the program. It is safest
+to attach them to the start of each source file to most effectively
+state the exclusion of warranty; and each file should have at least
+the "copyright" line and a pointer to where the full notice is found.
+
+
+ Copyright (C)
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see .
+
+Also add information on how to contact you by electronic and paper mail.
+
+ If the program does terminal interaction, make it output a short
+notice like this when it starts in an interactive mode:
+
+ Copyright (C)
+ This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
+ This is free software, and you are welcome to redistribute it
+ under certain conditions; type `show c' for details.
+
+The hypothetical commands `show w' and `show c' should show the appropriate
+parts of the General Public License. Of course, your program's commands
+might be different; for a GUI interface, you would use an "about box".
+
+ You should also get your employer (if you work as a programmer) or school,
+if any, to sign a "copyright disclaimer" for the program, if necessary.
+For more information on this, and how to apply and follow the GNU GPL, see
+.
+
+ The GNU General Public License does not permit incorporating your program
+into proprietary programs. If your program is a subroutine library, you
+may consider it more useful to permit linking proprietary applications with
+the library. If this is what you want to do, use the GNU Lesser General
+Public License instead of this License. But first, please read
+.
diff --git a/modules/purchase_shipment_cost/MANIFEST.in b/modules/purchase_shipment_cost/MANIFEST.in
new file mode 100644
index 0000000000..e88b2348a3
--- /dev/null
+++ b/modules/purchase_shipment_cost/MANIFEST.in
@@ -0,0 +1,5 @@
+include CHANGELOG
+include COPYRIGHT
+include LICENSE
+include README.rst
+include doc/*
diff --git a/modules/purchase_shipment_cost/README.rst b/modules/purchase_shipment_cost/README.rst
new file mode 120000
index 0000000000..176d9c2695
--- /dev/null
+++ b/modules/purchase_shipment_cost/README.rst
@@ -0,0 +1 @@
+doc/index.rst
\ No newline at end of file
diff --git a/modules/purchase_shipment_cost/__init__.py b/modules/purchase_shipment_cost/__init__.py
new file mode 100644
index 0000000000..36b119010f
--- /dev/null
+++ b/modules/purchase_shipment_cost/__init__.py
@@ -0,0 +1,14 @@
+# This file is part of Tryton. The COPYRIGHT file at the top level of
+# this repository contains the full copyright notices and license terms.
+
+from trytond.pool import Pool
+from . import stock
+from . import carrier
+
+
+def register():
+ Pool.register(
+ stock.ShipmentIn,
+ stock.Move,
+ carrier.Carrier,
+ module='purchase_shipment_cost', type_='model')
diff --git a/modules/purchase_shipment_cost/carrier.py b/modules/purchase_shipment_cost/carrier.py
new file mode 100644
index 0000000000..f27ffaf366
--- /dev/null
+++ b/modules/purchase_shipment_cost/carrier.py
@@ -0,0 +1,15 @@
+# This file is part of Tryton. The COPYRIGHT file at the top level of
+# this repository contains the full copyright notices and license terms.
+from trytond.model import fields
+from trytond.pool import PoolMeta
+
+
+class Carrier(metaclass=PoolMeta):
+ __name__ = 'carrier'
+ carrier_cost_allocation_method = fields.Selection([
+ ('value', 'By Value'),
+ ], 'Carrier Cost Allocation Method', required=True)
+
+ @staticmethod
+ def default_carrier_cost_allocation_method():
+ return 'value'
diff --git a/modules/purchase_shipment_cost/carrier.xml b/modules/purchase_shipment_cost/carrier.xml
new file mode 100644
index 0000000000..80374272cd
--- /dev/null
+++ b/modules/purchase_shipment_cost/carrier.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+ carrier
+
+
+ carrier_form
+
+
+
diff --git a/modules/purchase_shipment_cost/doc/index.rst b/modules/purchase_shipment_cost/doc/index.rst
new file mode 100644
index 0000000000..8b9900c142
--- /dev/null
+++ b/modules/purchase_shipment_cost/doc/index.rst
@@ -0,0 +1,21 @@
+Purchase Shipment Cost Module
+#############################
+
+The purchase_shipment_cost module adds shipment cost to *Supplier Shipment*.
+
+One field is added to *Carrier*:
+
+- *Carrier Cost Allocation Method*: The method used to allocate the cost on
+ each lines of the shipment.
+
+ - *By Value*: The cost will be allocated according to the value of each
+ line. (The value is: *Quantity* * *Unit Price*)
+
+Three new fields are added to *Supplier Shipment*:
+
+- *Carrier*: The carrier used for the shipment.
+- *Cost*: The cost of the shipment.
+- *Cost Currency*: The currency of the cost.
+
+At the reception of the shipment, the unit price of each incoming moves will be
+updated according to the allocation of the cost.
diff --git a/modules/purchase_shipment_cost/locale/bg.po b/modules/purchase_shipment_cost/locale/bg.po
new file mode 100644
index 0000000000..d4b615c36a
--- /dev/null
+++ b/modules/purchase_shipment_cost/locale/bg.po
@@ -0,0 +1,46 @@
+#
+msgid ""
+msgstr "Content-Type: text/plain; charset=utf-8\n"
+
+msgctxt "field:carrier,carrier_cost_allocation_method:"
+msgid "Carrier Cost Allocation Method"
+msgstr "Начин на разпределяне на остойностяване на превоз"
+
+msgctxt "field:stock.move,unit_shipment_cost:"
+msgid "Unit Shipment Cost"
+msgstr "Остойностяване на доставка на единица"
+
+msgctxt "field:stock.shipment.in,carrier:"
+msgid "Carrier"
+msgstr "Превозвач"
+
+msgctxt "field:stock.shipment.in,cost:"
+msgid "Cost"
+msgstr "Разход"
+
+msgctxt "field:stock.shipment.in,cost_currency:"
+msgid "Cost Currency"
+msgstr "Валута при разход"
+
+#, fuzzy
+msgctxt "field:stock.shipment.in,cost_currency_used:"
+msgid "Cost Currency"
+msgstr "Валута при разход"
+
+#, fuzzy
+msgctxt "field:stock.shipment.in,cost_edit:"
+msgid "Edit Cost"
+msgstr "Разход"
+
+#, fuzzy
+msgctxt "field:stock.shipment.in,cost_used:"
+msgid "Cost"
+msgstr "Разход"
+
+msgctxt "help:stock.shipment.in,cost_edit:"
+msgid "Check to edit the cost."
+msgstr ""
+
+msgctxt "selection:carrier,carrier_cost_allocation_method:"
+msgid "By Value"
+msgstr "По стойност"
diff --git a/modules/purchase_shipment_cost/locale/ca.po b/modules/purchase_shipment_cost/locale/ca.po
new file mode 100644
index 0000000000..95aff8fdae
--- /dev/null
+++ b/modules/purchase_shipment_cost/locale/ca.po
@@ -0,0 +1,43 @@
+#
+msgid ""
+msgstr "Content-Type: text/plain; charset=utf-8\n"
+
+msgctxt "field:carrier,carrier_cost_allocation_method:"
+msgid "Carrier Cost Allocation Method"
+msgstr "Mètode d'assignació cost transportista"
+
+msgctxt "field:stock.move,unit_shipment_cost:"
+msgid "Unit Shipment Cost"
+msgstr "Cost unitat enviament"
+
+msgctxt "field:stock.shipment.in,carrier:"
+msgid "Carrier"
+msgstr "Transportista"
+
+msgctxt "field:stock.shipment.in,cost:"
+msgid "Cost"
+msgstr "Cost"
+
+msgctxt "field:stock.shipment.in,cost_currency:"
+msgid "Cost Currency"
+msgstr "Moneda cost"
+
+msgctxt "field:stock.shipment.in,cost_currency_used:"
+msgid "Cost Currency"
+msgstr "Moneda cost"
+
+msgctxt "field:stock.shipment.in,cost_edit:"
+msgid "Edit Cost"
+msgstr "Edita cost"
+
+msgctxt "field:stock.shipment.in,cost_used:"
+msgid "Cost"
+msgstr "Cost"
+
+msgctxt "help:stock.shipment.in,cost_edit:"
+msgid "Check to edit the cost."
+msgstr "Marca per editar el cost."
+
+msgctxt "selection:carrier,carrier_cost_allocation_method:"
+msgid "By Value"
+msgstr "Per valor"
diff --git a/modules/purchase_shipment_cost/locale/cs.po b/modules/purchase_shipment_cost/locale/cs.po
new file mode 100644
index 0000000000..c692aa18d2
--- /dev/null
+++ b/modules/purchase_shipment_cost/locale/cs.po
@@ -0,0 +1,43 @@
+#
+msgid ""
+msgstr "Content-Type: text/plain; charset=utf-8\n"
+
+msgctxt "field:carrier,carrier_cost_allocation_method:"
+msgid "Carrier Cost Allocation Method"
+msgstr ""
+
+msgctxt "field:stock.move,unit_shipment_cost:"
+msgid "Unit Shipment Cost"
+msgstr ""
+
+msgctxt "field:stock.shipment.in,carrier:"
+msgid "Carrier"
+msgstr ""
+
+msgctxt "field:stock.shipment.in,cost:"
+msgid "Cost"
+msgstr ""
+
+msgctxt "field:stock.shipment.in,cost_currency:"
+msgid "Cost Currency"
+msgstr ""
+
+msgctxt "field:stock.shipment.in,cost_currency_used:"
+msgid "Cost Currency"
+msgstr ""
+
+msgctxt "field:stock.shipment.in,cost_edit:"
+msgid "Edit Cost"
+msgstr ""
+
+msgctxt "field:stock.shipment.in,cost_used:"
+msgid "Cost"
+msgstr ""
+
+msgctxt "help:stock.shipment.in,cost_edit:"
+msgid "Check to edit the cost."
+msgstr ""
+
+msgctxt "selection:carrier,carrier_cost_allocation_method:"
+msgid "By Value"
+msgstr ""
diff --git a/modules/purchase_shipment_cost/locale/de.po b/modules/purchase_shipment_cost/locale/de.po
new file mode 100644
index 0000000000..1f7e2bed5c
--- /dev/null
+++ b/modules/purchase_shipment_cost/locale/de.po
@@ -0,0 +1,43 @@
+#
+msgid ""
+msgstr "Content-Type: text/plain; charset=utf-8\n"
+
+msgctxt "field:carrier,carrier_cost_allocation_method:"
+msgid "Carrier Cost Allocation Method"
+msgstr "Zuordnungsmethode Versandkosten"
+
+msgctxt "field:stock.move,unit_shipment_cost:"
+msgid "Unit Shipment Cost"
+msgstr "Einheit Lieferpostenkosten"
+
+msgctxt "field:stock.shipment.in,carrier:"
+msgid "Carrier"
+msgstr "Versanddienstleister"
+
+msgctxt "field:stock.shipment.in,cost:"
+msgid "Cost"
+msgstr "Kosten"
+
+msgctxt "field:stock.shipment.in,cost_currency:"
+msgid "Cost Currency"
+msgstr "Währung Kosten"
+
+msgctxt "field:stock.shipment.in,cost_currency_used:"
+msgid "Cost Currency"
+msgstr "Währung Kosten"
+
+msgctxt "field:stock.shipment.in,cost_edit:"
+msgid "Edit Cost"
+msgstr "Kosten Bearbeiten"
+
+msgctxt "field:stock.shipment.in,cost_used:"
+msgid "Cost"
+msgstr "Kosten"
+
+msgctxt "help:stock.shipment.in,cost_edit:"
+msgid "Check to edit the cost."
+msgstr "Aktivieren um die Kosten zu bearbeiten."
+
+msgctxt "selection:carrier,carrier_cost_allocation_method:"
+msgid "By Value"
+msgstr "Nach Wert"
diff --git a/modules/purchase_shipment_cost/locale/es.po b/modules/purchase_shipment_cost/locale/es.po
new file mode 100644
index 0000000000..cf1846d0fd
--- /dev/null
+++ b/modules/purchase_shipment_cost/locale/es.po
@@ -0,0 +1,43 @@
+#
+msgid ""
+msgstr "Content-Type: text/plain; charset=utf-8\n"
+
+msgctxt "field:carrier,carrier_cost_allocation_method:"
+msgid "Carrier Cost Allocation Method"
+msgstr "Método asignación coste del transportista"
+
+msgctxt "field:stock.move,unit_shipment_cost:"
+msgid "Unit Shipment Cost"
+msgstr "Coste unidad envío"
+
+msgctxt "field:stock.shipment.in,carrier:"
+msgid "Carrier"
+msgstr "Transportista"
+
+msgctxt "field:stock.shipment.in,cost:"
+msgid "Cost"
+msgstr "Coste"
+
+msgctxt "field:stock.shipment.in,cost_currency:"
+msgid "Cost Currency"
+msgstr "Moneda coste"
+
+msgctxt "field:stock.shipment.in,cost_currency_used:"
+msgid "Cost Currency"
+msgstr "Moneda coste"
+
+msgctxt "field:stock.shipment.in,cost_edit:"
+msgid "Edit Cost"
+msgstr "Editar coste"
+
+msgctxt "field:stock.shipment.in,cost_used:"
+msgid "Cost"
+msgstr "Coste"
+
+msgctxt "help:stock.shipment.in,cost_edit:"
+msgid "Check to edit the cost."
+msgstr "Marcar para editar el coste."
+
+msgctxt "selection:carrier,carrier_cost_allocation_method:"
+msgid "By Value"
+msgstr "Por valor"
diff --git a/modules/purchase_shipment_cost/locale/es_419.po b/modules/purchase_shipment_cost/locale/es_419.po
new file mode 100644
index 0000000000..de5ad1c7d6
--- /dev/null
+++ b/modules/purchase_shipment_cost/locale/es_419.po
@@ -0,0 +1,46 @@
+#
+msgid ""
+msgstr "Content-Type: text/plain; charset=utf-8\n"
+
+msgctxt "field:carrier,carrier_cost_allocation_method:"
+msgid "Carrier Cost Allocation Method"
+msgstr "Método de asignación de costo del transportista"
+
+msgctxt "field:stock.move,unit_shipment_cost:"
+msgid "Unit Shipment Cost"
+msgstr "Costo unitario de envío"
+
+msgctxt "field:stock.shipment.in,carrier:"
+msgid "Carrier"
+msgstr ""
+
+msgctxt "field:stock.shipment.in,cost:"
+msgid "Cost"
+msgstr "Costo"
+
+msgctxt "field:stock.shipment.in,cost_currency:"
+msgid "Cost Currency"
+msgstr "Moneda de costo"
+
+#, fuzzy
+msgctxt "field:stock.shipment.in,cost_currency_used:"
+msgid "Cost Currency"
+msgstr "Moneda de costo"
+
+#, fuzzy
+msgctxt "field:stock.shipment.in,cost_edit:"
+msgid "Edit Cost"
+msgstr "Costo"
+
+#, fuzzy
+msgctxt "field:stock.shipment.in,cost_used:"
+msgid "Cost"
+msgstr "Costo"
+
+msgctxt "help:stock.shipment.in,cost_edit:"
+msgid "Check to edit the cost."
+msgstr ""
+
+msgctxt "selection:carrier,carrier_cost_allocation_method:"
+msgid "By Value"
+msgstr ""
diff --git a/modules/purchase_shipment_cost/locale/et.po b/modules/purchase_shipment_cost/locale/et.po
new file mode 100644
index 0000000000..191e8fce27
--- /dev/null
+++ b/modules/purchase_shipment_cost/locale/et.po
@@ -0,0 +1,46 @@
+#
+msgid ""
+msgstr "Content-Type: text/plain; charset=utf-8\n"
+
+msgctxt "field:carrier,carrier_cost_allocation_method:"
+msgid "Carrier Cost Allocation Method"
+msgstr "Vedaja kulu jaotamise meetod"
+
+msgctxt "field:stock.move,unit_shipment_cost:"
+msgid "Unit Shipment Cost"
+msgstr "Veokulu ühik"
+
+msgctxt "field:stock.shipment.in,carrier:"
+msgid "Carrier"
+msgstr "Vedaja"
+
+msgctxt "field:stock.shipment.in,cost:"
+msgid "Cost"
+msgstr "Kulu"
+
+msgctxt "field:stock.shipment.in,cost_currency:"
+msgid "Cost Currency"
+msgstr "Kulu valuuta"
+
+#, fuzzy
+msgctxt "field:stock.shipment.in,cost_currency_used:"
+msgid "Cost Currency"
+msgstr "Kulu valuuta"
+
+#, fuzzy
+msgctxt "field:stock.shipment.in,cost_edit:"
+msgid "Edit Cost"
+msgstr "Kulu"
+
+#, fuzzy
+msgctxt "field:stock.shipment.in,cost_used:"
+msgid "Cost"
+msgstr "Kulu"
+
+msgctxt "help:stock.shipment.in,cost_edit:"
+msgid "Check to edit the cost."
+msgstr ""
+
+msgctxt "selection:carrier,carrier_cost_allocation_method:"
+msgid "By Value"
+msgstr "Väärtuses"
diff --git a/modules/purchase_shipment_cost/locale/fa.po b/modules/purchase_shipment_cost/locale/fa.po
new file mode 100644
index 0000000000..03bf8ffe99
--- /dev/null
+++ b/modules/purchase_shipment_cost/locale/fa.po
@@ -0,0 +1,46 @@
+#
+msgid ""
+msgstr "Content-Type: text/plain; charset=utf-8\n"
+
+msgctxt "field:carrier,carrier_cost_allocation_method:"
+msgid "Carrier Cost Allocation Method"
+msgstr "روش تخصیص هزینه حمل"
+
+msgctxt "field:stock.move,unit_shipment_cost:"
+msgid "Unit Shipment Cost"
+msgstr "واحد هزینه حمل ونقل"
+
+msgctxt "field:stock.shipment.in,carrier:"
+msgid "Carrier"
+msgstr "حمل کننده"
+
+msgctxt "field:stock.shipment.in,cost:"
+msgid "Cost"
+msgstr "هزینه"
+
+msgctxt "field:stock.shipment.in,cost_currency:"
+msgid "Cost Currency"
+msgstr "واحد پول هزینه"
+
+#, fuzzy
+msgctxt "field:stock.shipment.in,cost_currency_used:"
+msgid "Cost Currency"
+msgstr "واحد پول هزینه"
+
+#, fuzzy
+msgctxt "field:stock.shipment.in,cost_edit:"
+msgid "Edit Cost"
+msgstr "هزینه"
+
+#, fuzzy
+msgctxt "field:stock.shipment.in,cost_used:"
+msgid "Cost"
+msgstr "هزینه"
+
+msgctxt "help:stock.shipment.in,cost_edit:"
+msgid "Check to edit the cost."
+msgstr ""
+
+msgctxt "selection:carrier,carrier_cost_allocation_method:"
+msgid "By Value"
+msgstr "براساس مقدار"
diff --git a/modules/purchase_shipment_cost/locale/fi.po b/modules/purchase_shipment_cost/locale/fi.po
new file mode 100644
index 0000000000..c692aa18d2
--- /dev/null
+++ b/modules/purchase_shipment_cost/locale/fi.po
@@ -0,0 +1,43 @@
+#
+msgid ""
+msgstr "Content-Type: text/plain; charset=utf-8\n"
+
+msgctxt "field:carrier,carrier_cost_allocation_method:"
+msgid "Carrier Cost Allocation Method"
+msgstr ""
+
+msgctxt "field:stock.move,unit_shipment_cost:"
+msgid "Unit Shipment Cost"
+msgstr ""
+
+msgctxt "field:stock.shipment.in,carrier:"
+msgid "Carrier"
+msgstr ""
+
+msgctxt "field:stock.shipment.in,cost:"
+msgid "Cost"
+msgstr ""
+
+msgctxt "field:stock.shipment.in,cost_currency:"
+msgid "Cost Currency"
+msgstr ""
+
+msgctxt "field:stock.shipment.in,cost_currency_used:"
+msgid "Cost Currency"
+msgstr ""
+
+msgctxt "field:stock.shipment.in,cost_edit:"
+msgid "Edit Cost"
+msgstr ""
+
+msgctxt "field:stock.shipment.in,cost_used:"
+msgid "Cost"
+msgstr ""
+
+msgctxt "help:stock.shipment.in,cost_edit:"
+msgid "Check to edit the cost."
+msgstr ""
+
+msgctxt "selection:carrier,carrier_cost_allocation_method:"
+msgid "By Value"
+msgstr ""
diff --git a/modules/purchase_shipment_cost/locale/fr.po b/modules/purchase_shipment_cost/locale/fr.po
new file mode 100644
index 0000000000..14ff29b1cc
--- /dev/null
+++ b/modules/purchase_shipment_cost/locale/fr.po
@@ -0,0 +1,43 @@
+#
+msgid ""
+msgstr "Content-Type: text/plain; charset=utf-8\n"
+
+msgctxt "field:carrier,carrier_cost_allocation_method:"
+msgid "Carrier Cost Allocation Method"
+msgstr "Méthode d'affectation des coûts de transport"
+
+msgctxt "field:stock.move,unit_shipment_cost:"
+msgid "Unit Shipment Cost"
+msgstr "Coût d'expédition unitaire"
+
+msgctxt "field:stock.shipment.in,carrier:"
+msgid "Carrier"
+msgstr "Transporteur"
+
+msgctxt "field:stock.shipment.in,cost:"
+msgid "Cost"
+msgstr "Coût"
+
+msgctxt "field:stock.shipment.in,cost_currency:"
+msgid "Cost Currency"
+msgstr "Devise du coût"
+
+msgctxt "field:stock.shipment.in,cost_currency_used:"
+msgid "Cost Currency"
+msgstr "Devise du coût"
+
+msgctxt "field:stock.shipment.in,cost_edit:"
+msgid "Edit Cost"
+msgstr "Modifier le coût"
+
+msgctxt "field:stock.shipment.in,cost_used:"
+msgid "Cost"
+msgstr "Coût"
+
+msgctxt "help:stock.shipment.in,cost_edit:"
+msgid "Check to edit the cost."
+msgstr "Cochez pour modifier le coût."
+
+msgctxt "selection:carrier,carrier_cost_allocation_method:"
+msgid "By Value"
+msgstr "Par valeur"
diff --git a/modules/purchase_shipment_cost/locale/hu.po b/modules/purchase_shipment_cost/locale/hu.po
new file mode 100644
index 0000000000..beff20fdc4
--- /dev/null
+++ b/modules/purchase_shipment_cost/locale/hu.po
@@ -0,0 +1,46 @@
+#
+msgid ""
+msgstr "Content-Type: text/plain; charset=utf-8\n"
+
+msgctxt "field:carrier,carrier_cost_allocation_method:"
+msgid "Carrier Cost Allocation Method"
+msgstr ""
+
+msgctxt "field:stock.move,unit_shipment_cost:"
+msgid "Unit Shipment Cost"
+msgstr ""
+
+msgctxt "field:stock.shipment.in,carrier:"
+msgid "Carrier"
+msgstr ""
+
+#, fuzzy
+msgctxt "field:stock.shipment.in,cost:"
+msgid "Cost"
+msgstr "Költség"
+
+msgctxt "field:stock.shipment.in,cost_currency:"
+msgid "Cost Currency"
+msgstr ""
+
+msgctxt "field:stock.shipment.in,cost_currency_used:"
+msgid "Cost Currency"
+msgstr ""
+
+#, fuzzy
+msgctxt "field:stock.shipment.in,cost_edit:"
+msgid "Edit Cost"
+msgstr "Költség"
+
+#, fuzzy
+msgctxt "field:stock.shipment.in,cost_used:"
+msgid "Cost"
+msgstr "Költség"
+
+msgctxt "help:stock.shipment.in,cost_edit:"
+msgid "Check to edit the cost."
+msgstr ""
+
+msgctxt "selection:carrier,carrier_cost_allocation_method:"
+msgid "By Value"
+msgstr ""
diff --git a/modules/purchase_shipment_cost/locale/id.po b/modules/purchase_shipment_cost/locale/id.po
new file mode 100644
index 0000000000..c692aa18d2
--- /dev/null
+++ b/modules/purchase_shipment_cost/locale/id.po
@@ -0,0 +1,43 @@
+#
+msgid ""
+msgstr "Content-Type: text/plain; charset=utf-8\n"
+
+msgctxt "field:carrier,carrier_cost_allocation_method:"
+msgid "Carrier Cost Allocation Method"
+msgstr ""
+
+msgctxt "field:stock.move,unit_shipment_cost:"
+msgid "Unit Shipment Cost"
+msgstr ""
+
+msgctxt "field:stock.shipment.in,carrier:"
+msgid "Carrier"
+msgstr ""
+
+msgctxt "field:stock.shipment.in,cost:"
+msgid "Cost"
+msgstr ""
+
+msgctxt "field:stock.shipment.in,cost_currency:"
+msgid "Cost Currency"
+msgstr ""
+
+msgctxt "field:stock.shipment.in,cost_currency_used:"
+msgid "Cost Currency"
+msgstr ""
+
+msgctxt "field:stock.shipment.in,cost_edit:"
+msgid "Edit Cost"
+msgstr ""
+
+msgctxt "field:stock.shipment.in,cost_used:"
+msgid "Cost"
+msgstr ""
+
+msgctxt "help:stock.shipment.in,cost_edit:"
+msgid "Check to edit the cost."
+msgstr ""
+
+msgctxt "selection:carrier,carrier_cost_allocation_method:"
+msgid "By Value"
+msgstr ""
diff --git a/modules/purchase_shipment_cost/locale/it.po b/modules/purchase_shipment_cost/locale/it.po
new file mode 100644
index 0000000000..85d74eb108
--- /dev/null
+++ b/modules/purchase_shipment_cost/locale/it.po
@@ -0,0 +1,46 @@
+#
+msgid ""
+msgstr "Content-Type: text/plain; charset=utf-8\n"
+
+msgctxt "field:carrier,carrier_cost_allocation_method:"
+msgid "Carrier Cost Allocation Method"
+msgstr "Metodo di allocazione del costo del vettore"
+
+msgctxt "field:stock.move,unit_shipment_cost:"
+msgid "Unit Shipment Cost"
+msgstr "Costo unitario di spedizione"
+
+msgctxt "field:stock.shipment.in,carrier:"
+msgid "Carrier"
+msgstr "Vettore"
+
+msgctxt "field:stock.shipment.in,cost:"
+msgid "Cost"
+msgstr "Costo"
+
+msgctxt "field:stock.shipment.in,cost_currency:"
+msgid "Cost Currency"
+msgstr "Valuta costo"
+
+#, fuzzy
+msgctxt "field:stock.shipment.in,cost_currency_used:"
+msgid "Cost Currency"
+msgstr "Valuta costo"
+
+#, fuzzy
+msgctxt "field:stock.shipment.in,cost_edit:"
+msgid "Edit Cost"
+msgstr "Costo"
+
+#, fuzzy
+msgctxt "field:stock.shipment.in,cost_used:"
+msgid "Cost"
+msgstr "Costo"
+
+msgctxt "help:stock.shipment.in,cost_edit:"
+msgid "Check to edit the cost."
+msgstr ""
+
+msgctxt "selection:carrier,carrier_cost_allocation_method:"
+msgid "By Value"
+msgstr "A valore"
diff --git a/modules/purchase_shipment_cost/locale/lo.po b/modules/purchase_shipment_cost/locale/lo.po
new file mode 100644
index 0000000000..538a87cda0
--- /dev/null
+++ b/modules/purchase_shipment_cost/locale/lo.po
@@ -0,0 +1,46 @@
+#
+msgid ""
+msgstr "Content-Type: text/plain; charset=utf-8\n"
+
+msgctxt "field:carrier,carrier_cost_allocation_method:"
+msgid "Carrier Cost Allocation Method"
+msgstr "ວິທີການຈັດສັນຕົ້ນທຶນຂອງຜູ້ບໍລິການ"
+
+msgctxt "field:stock.move,unit_shipment_cost:"
+msgid "Unit Shipment Cost"
+msgstr "ຫົວໜ່ວຍລາຄາຄ່າຈັດສົ່ງ"
+
+msgctxt "field:stock.shipment.in,carrier:"
+msgid "Carrier"
+msgstr "ຜູ້ບໍລິການ"
+
+msgctxt "field:stock.shipment.in,cost:"
+msgid "Cost"
+msgstr "ລາຄາ"
+
+msgctxt "field:stock.shipment.in,cost_currency:"
+msgid "Cost Currency"
+msgstr "ມູນຄ່າສະກຸນເງິນ"
+
+#, fuzzy
+msgctxt "field:stock.shipment.in,cost_currency_used:"
+msgid "Cost Currency"
+msgstr "ມູນຄ່າສະກຸນເງິນ"
+
+#, fuzzy
+msgctxt "field:stock.shipment.in,cost_edit:"
+msgid "Edit Cost"
+msgstr "ລາຄາ"
+
+#, fuzzy
+msgctxt "field:stock.shipment.in,cost_used:"
+msgid "Cost"
+msgstr "ລາຄາ"
+
+msgctxt "help:stock.shipment.in,cost_edit:"
+msgid "Check to edit the cost."
+msgstr ""
+
+msgctxt "selection:carrier,carrier_cost_allocation_method:"
+msgid "By Value"
+msgstr "ດ້ວຍມູນຄ່າ"
diff --git a/modules/purchase_shipment_cost/locale/lt.po b/modules/purchase_shipment_cost/locale/lt.po
new file mode 100644
index 0000000000..f07434d6af
--- /dev/null
+++ b/modules/purchase_shipment_cost/locale/lt.po
@@ -0,0 +1,44 @@
+#
+msgid ""
+msgstr "Content-Type: text/plain; charset=utf-8\n"
+
+msgctxt "field:carrier,carrier_cost_allocation_method:"
+msgid "Carrier Cost Allocation Method"
+msgstr ""
+
+msgctxt "field:stock.move,unit_shipment_cost:"
+msgid "Unit Shipment Cost"
+msgstr ""
+
+msgctxt "field:stock.shipment.in,carrier:"
+msgid "Carrier"
+msgstr ""
+
+msgctxt "field:stock.shipment.in,cost:"
+msgid "Cost"
+msgstr ""
+
+msgctxt "field:stock.shipment.in,cost_currency:"
+msgid "Cost Currency"
+msgstr "Savikainos valiuta"
+
+#, fuzzy
+msgctxt "field:stock.shipment.in,cost_currency_used:"
+msgid "Cost Currency"
+msgstr "Savikainos valiuta"
+
+msgctxt "field:stock.shipment.in,cost_edit:"
+msgid "Edit Cost"
+msgstr ""
+
+msgctxt "field:stock.shipment.in,cost_used:"
+msgid "Cost"
+msgstr ""
+
+msgctxt "help:stock.shipment.in,cost_edit:"
+msgid "Check to edit the cost."
+msgstr ""
+
+msgctxt "selection:carrier,carrier_cost_allocation_method:"
+msgid "By Value"
+msgstr ""
diff --git a/modules/purchase_shipment_cost/locale/nl.po b/modules/purchase_shipment_cost/locale/nl.po
new file mode 100644
index 0000000000..5bdbbafad3
--- /dev/null
+++ b/modules/purchase_shipment_cost/locale/nl.po
@@ -0,0 +1,46 @@
+#
+msgid ""
+msgstr "Content-Type: text/plain; charset=utf-8\n"
+
+msgctxt "field:carrier,carrier_cost_allocation_method:"
+msgid "Carrier Cost Allocation Method"
+msgstr "Toewijzingsmethode verzendkosten"
+
+msgctxt "field:stock.move,unit_shipment_cost:"
+msgid "Unit Shipment Cost"
+msgstr "eenheidskost verzending"
+
+msgctxt "field:stock.shipment.in,carrier:"
+msgid "Carrier"
+msgstr "Transporteur"
+
+msgctxt "field:stock.shipment.in,cost:"
+msgid "Cost"
+msgstr "Kosten"
+
+msgctxt "field:stock.shipment.in,cost_currency:"
+msgid "Cost Currency"
+msgstr "Kostenvaluta"
+
+#, fuzzy
+msgctxt "field:stock.shipment.in,cost_currency_used:"
+msgid "Cost Currency"
+msgstr "Kostenvaluta"
+
+#, fuzzy
+msgctxt "field:stock.shipment.in,cost_edit:"
+msgid "Edit Cost"
+msgstr "Kosten"
+
+#, fuzzy
+msgctxt "field:stock.shipment.in,cost_used:"
+msgid "Cost"
+msgstr "Kosten"
+
+msgctxt "help:stock.shipment.in,cost_edit:"
+msgid "Check to edit the cost."
+msgstr ""
+
+msgctxt "selection:carrier,carrier_cost_allocation_method:"
+msgid "By Value"
+msgstr "Op waarde"
diff --git a/modules/purchase_shipment_cost/locale/pl.po b/modules/purchase_shipment_cost/locale/pl.po
new file mode 100644
index 0000000000..fce2ee9d4f
--- /dev/null
+++ b/modules/purchase_shipment_cost/locale/pl.po
@@ -0,0 +1,46 @@
+#
+msgid ""
+msgstr "Content-Type: text/plain; charset=utf-8\n"
+
+msgctxt "field:carrier,carrier_cost_allocation_method:"
+msgid "Carrier Cost Allocation Method"
+msgstr ""
+
+msgctxt "field:stock.move,unit_shipment_cost:"
+msgid "Unit Shipment Cost"
+msgstr ""
+
+msgctxt "field:stock.shipment.in,carrier:"
+msgid "Carrier"
+msgstr ""
+
+msgctxt "field:stock.shipment.in,cost:"
+msgid "Cost"
+msgstr "Koszt"
+
+msgctxt "field:stock.shipment.in,cost_currency:"
+msgid "Cost Currency"
+msgstr "Koszt waluty"
+
+#, fuzzy
+msgctxt "field:stock.shipment.in,cost_currency_used:"
+msgid "Cost Currency"
+msgstr "Koszt waluty"
+
+#, fuzzy
+msgctxt "field:stock.shipment.in,cost_edit:"
+msgid "Edit Cost"
+msgstr "Koszt"
+
+#, fuzzy
+msgctxt "field:stock.shipment.in,cost_used:"
+msgid "Cost"
+msgstr "Koszt"
+
+msgctxt "help:stock.shipment.in,cost_edit:"
+msgid "Check to edit the cost."
+msgstr ""
+
+msgctxt "selection:carrier,carrier_cost_allocation_method:"
+msgid "By Value"
+msgstr "Wg wartości"
diff --git a/modules/purchase_shipment_cost/locale/pt.po b/modules/purchase_shipment_cost/locale/pt.po
new file mode 100644
index 0000000000..d063020742
--- /dev/null
+++ b/modules/purchase_shipment_cost/locale/pt.po
@@ -0,0 +1,46 @@
+#
+msgid ""
+msgstr "Content-Type: text/plain; charset=utf-8\n"
+
+msgctxt "field:carrier,carrier_cost_allocation_method:"
+msgid "Carrier Cost Allocation Method"
+msgstr "Método de atribuição de custo da transportadora"
+
+msgctxt "field:stock.move,unit_shipment_cost:"
+msgid "Unit Shipment Cost"
+msgstr "Custo unitário de remessa"
+
+msgctxt "field:stock.shipment.in,carrier:"
+msgid "Carrier"
+msgstr "Transportadora"
+
+msgctxt "field:stock.shipment.in,cost:"
+msgid "Cost"
+msgstr "Custo"
+
+msgctxt "field:stock.shipment.in,cost_currency:"
+msgid "Cost Currency"
+msgstr "Moeda de custo"
+
+#, fuzzy
+msgctxt "field:stock.shipment.in,cost_currency_used:"
+msgid "Cost Currency"
+msgstr "Moeda de custo"
+
+#, fuzzy
+msgctxt "field:stock.shipment.in,cost_edit:"
+msgid "Edit Cost"
+msgstr "Custo"
+
+#, fuzzy
+msgctxt "field:stock.shipment.in,cost_used:"
+msgid "Cost"
+msgstr "Custo"
+
+msgctxt "help:stock.shipment.in,cost_edit:"
+msgid "Check to edit the cost."
+msgstr ""
+
+msgctxt "selection:carrier,carrier_cost_allocation_method:"
+msgid "By Value"
+msgstr "Por valor"
diff --git a/modules/purchase_shipment_cost/locale/ro.po b/modules/purchase_shipment_cost/locale/ro.po
new file mode 100644
index 0000000000..c692aa18d2
--- /dev/null
+++ b/modules/purchase_shipment_cost/locale/ro.po
@@ -0,0 +1,43 @@
+#
+msgid ""
+msgstr "Content-Type: text/plain; charset=utf-8\n"
+
+msgctxt "field:carrier,carrier_cost_allocation_method:"
+msgid "Carrier Cost Allocation Method"
+msgstr ""
+
+msgctxt "field:stock.move,unit_shipment_cost:"
+msgid "Unit Shipment Cost"
+msgstr ""
+
+msgctxt "field:stock.shipment.in,carrier:"
+msgid "Carrier"
+msgstr ""
+
+msgctxt "field:stock.shipment.in,cost:"
+msgid "Cost"
+msgstr ""
+
+msgctxt "field:stock.shipment.in,cost_currency:"
+msgid "Cost Currency"
+msgstr ""
+
+msgctxt "field:stock.shipment.in,cost_currency_used:"
+msgid "Cost Currency"
+msgstr ""
+
+msgctxt "field:stock.shipment.in,cost_edit:"
+msgid "Edit Cost"
+msgstr ""
+
+msgctxt "field:stock.shipment.in,cost_used:"
+msgid "Cost"
+msgstr ""
+
+msgctxt "help:stock.shipment.in,cost_edit:"
+msgid "Check to edit the cost."
+msgstr ""
+
+msgctxt "selection:carrier,carrier_cost_allocation_method:"
+msgid "By Value"
+msgstr ""
diff --git a/modules/purchase_shipment_cost/locale/ru.po b/modules/purchase_shipment_cost/locale/ru.po
new file mode 100644
index 0000000000..b869e862dc
--- /dev/null
+++ b/modules/purchase_shipment_cost/locale/ru.po
@@ -0,0 +1,46 @@
+#
+msgid ""
+msgstr "Content-Type: text/plain; charset=utf-8\n"
+
+msgctxt "field:carrier,carrier_cost_allocation_method:"
+msgid "Carrier Cost Allocation Method"
+msgstr ""
+
+msgctxt "field:stock.move,unit_shipment_cost:"
+msgid "Unit Shipment Cost"
+msgstr ""
+
+msgctxt "field:stock.shipment.in,carrier:"
+msgid "Carrier"
+msgstr ""
+
+#, fuzzy
+msgctxt "field:stock.shipment.in,cost:"
+msgid "Cost"
+msgstr "Стоимость"
+
+msgctxt "field:stock.shipment.in,cost_currency:"
+msgid "Cost Currency"
+msgstr ""
+
+msgctxt "field:stock.shipment.in,cost_currency_used:"
+msgid "Cost Currency"
+msgstr ""
+
+#, fuzzy
+msgctxt "field:stock.shipment.in,cost_edit:"
+msgid "Edit Cost"
+msgstr "Стоимость"
+
+#, fuzzy
+msgctxt "field:stock.shipment.in,cost_used:"
+msgid "Cost"
+msgstr "Стоимость"
+
+msgctxt "help:stock.shipment.in,cost_edit:"
+msgid "Check to edit the cost."
+msgstr ""
+
+msgctxt "selection:carrier,carrier_cost_allocation_method:"
+msgid "By Value"
+msgstr ""
diff --git a/modules/purchase_shipment_cost/locale/sl.po b/modules/purchase_shipment_cost/locale/sl.po
new file mode 100644
index 0000000000..658e3fe83e
--- /dev/null
+++ b/modules/purchase_shipment_cost/locale/sl.po
@@ -0,0 +1,46 @@
+#
+msgid ""
+msgstr "Content-Type: text/plain; charset=utf-8\n"
+
+msgctxt "field:carrier,carrier_cost_allocation_method:"
+msgid "Carrier Cost Allocation Method"
+msgstr "Porazdelitev špedicijskih stroškov"
+
+msgctxt "field:stock.move,unit_shipment_cost:"
+msgid "Unit Shipment Cost"
+msgstr "Strošek dostave na enoto"
+
+msgctxt "field:stock.shipment.in,carrier:"
+msgid "Carrier"
+msgstr "Špediter"
+
+msgctxt "field:stock.shipment.in,cost:"
+msgid "Cost"
+msgstr "Strošek"
+
+msgctxt "field:stock.shipment.in,cost_currency:"
+msgid "Cost Currency"
+msgstr "Valuta stroška"
+
+#, fuzzy
+msgctxt "field:stock.shipment.in,cost_currency_used:"
+msgid "Cost Currency"
+msgstr "Valuta stroška"
+
+#, fuzzy
+msgctxt "field:stock.shipment.in,cost_edit:"
+msgid "Edit Cost"
+msgstr "Strošek"
+
+#, fuzzy
+msgctxt "field:stock.shipment.in,cost_used:"
+msgid "Cost"
+msgstr "Strošek"
+
+msgctxt "help:stock.shipment.in,cost_edit:"
+msgid "Check to edit the cost."
+msgstr ""
+
+msgctxt "selection:carrier,carrier_cost_allocation_method:"
+msgid "By Value"
+msgstr "Po vrednosti"
diff --git a/modules/purchase_shipment_cost/locale/tr.po b/modules/purchase_shipment_cost/locale/tr.po
new file mode 100644
index 0000000000..c692aa18d2
--- /dev/null
+++ b/modules/purchase_shipment_cost/locale/tr.po
@@ -0,0 +1,43 @@
+#
+msgid ""
+msgstr "Content-Type: text/plain; charset=utf-8\n"
+
+msgctxt "field:carrier,carrier_cost_allocation_method:"
+msgid "Carrier Cost Allocation Method"
+msgstr ""
+
+msgctxt "field:stock.move,unit_shipment_cost:"
+msgid "Unit Shipment Cost"
+msgstr ""
+
+msgctxt "field:stock.shipment.in,carrier:"
+msgid "Carrier"
+msgstr ""
+
+msgctxt "field:stock.shipment.in,cost:"
+msgid "Cost"
+msgstr ""
+
+msgctxt "field:stock.shipment.in,cost_currency:"
+msgid "Cost Currency"
+msgstr ""
+
+msgctxt "field:stock.shipment.in,cost_currency_used:"
+msgid "Cost Currency"
+msgstr ""
+
+msgctxt "field:stock.shipment.in,cost_edit:"
+msgid "Edit Cost"
+msgstr ""
+
+msgctxt "field:stock.shipment.in,cost_used:"
+msgid "Cost"
+msgstr ""
+
+msgctxt "help:stock.shipment.in,cost_edit:"
+msgid "Check to edit the cost."
+msgstr ""
+
+msgctxt "selection:carrier,carrier_cost_allocation_method:"
+msgid "By Value"
+msgstr ""
diff --git a/modules/purchase_shipment_cost/locale/zh_CN.po b/modules/purchase_shipment_cost/locale/zh_CN.po
new file mode 100644
index 0000000000..c692aa18d2
--- /dev/null
+++ b/modules/purchase_shipment_cost/locale/zh_CN.po
@@ -0,0 +1,43 @@
+#
+msgid ""
+msgstr "Content-Type: text/plain; charset=utf-8\n"
+
+msgctxt "field:carrier,carrier_cost_allocation_method:"
+msgid "Carrier Cost Allocation Method"
+msgstr ""
+
+msgctxt "field:stock.move,unit_shipment_cost:"
+msgid "Unit Shipment Cost"
+msgstr ""
+
+msgctxt "field:stock.shipment.in,carrier:"
+msgid "Carrier"
+msgstr ""
+
+msgctxt "field:stock.shipment.in,cost:"
+msgid "Cost"
+msgstr ""
+
+msgctxt "field:stock.shipment.in,cost_currency:"
+msgid "Cost Currency"
+msgstr ""
+
+msgctxt "field:stock.shipment.in,cost_currency_used:"
+msgid "Cost Currency"
+msgstr ""
+
+msgctxt "field:stock.shipment.in,cost_edit:"
+msgid "Edit Cost"
+msgstr ""
+
+msgctxt "field:stock.shipment.in,cost_used:"
+msgid "Cost"
+msgstr ""
+
+msgctxt "help:stock.shipment.in,cost_edit:"
+msgid "Check to edit the cost."
+msgstr ""
+
+msgctxt "selection:carrier,carrier_cost_allocation_method:"
+msgid "By Value"
+msgstr ""
diff --git a/modules/purchase_shipment_cost/setup.py b/modules/purchase_shipment_cost/setup.py
new file mode 100755
index 0000000000..da83f21a73
--- /dev/null
+++ b/modules/purchase_shipment_cost/setup.py
@@ -0,0 +1,160 @@
+#!/usr/bin/env python3
+# This file is part of Tryton. The COPYRIGHT file at the top level of
+# this repository contains the full copyright notices and license terms.
+
+import io
+import os
+import re
+from configparser import ConfigParser
+from setuptools import setup, find_packages
+
+
+def read(fname):
+ return io.open(
+ os.path.join(os.path.dirname(__file__), fname),
+ 'r', encoding='utf-8').read()
+
+
+def get_require_version(name):
+ if minor_version % 2:
+ require = '%s >= %s.%s.dev0, < %s.%s'
+ else:
+ require = '%s >= %s.%s, < %s.%s'
+ require %= (name, major_version, minor_version,
+ major_version, minor_version + 1)
+ return require
+
+
+config = ConfigParser()
+config.read_file(open(os.path.join(os.path.dirname(__file__), 'tryton.cfg')))
+info = dict(config.items('tryton'))
+for key in ('depends', 'extras_depend', 'xml'):
+ if key in info:
+ info[key] = info[key].strip().splitlines()
+version = info.get('version', '0.0.1')
+major_version, minor_version, _ = version.split('.', 2)
+major_version = int(major_version)
+minor_version = int(minor_version)
+name = 'trytond_purchase_shipment_cost'
+
+download_url = 'http://downloads.tryton.org/%s.%s/' % (
+ major_version, minor_version)
+if minor_version % 2:
+ version = '%s.%s.dev0' % (major_version, minor_version)
+ download_url = (
+ 'hg+http://hg.tryton.org/modules/%s#egg=%s-%s' % (
+ name[8:], name, version))
+local_version = []
+if os.environ.get('CI_JOB_ID'):
+ local_version.append(os.environ['CI_JOB_ID'])
+else:
+ for build in ['CI_BUILD_NUMBER', 'CI_JOB_NUMBER']:
+ if os.environ.get(build):
+ local_version.append(os.environ[build])
+ else:
+ local_version = []
+ break
+if local_version:
+ version += '+' + '.'.join(local_version)
+
+requires = []
+for dep in info.get('depends', []):
+ if not re.match(r'(ir|res)(\W|$)', dep):
+ requires.append(get_require_version('trytond_%s' % dep))
+requires.append(get_require_version('trytond'))
+
+extras_require = {}
+for dep in info.get('extras_depend', []):
+ if not re.match(r'(ir|res)(\W|$)', dep):
+ extras_require[dep] = get_require_version('trytond_%s' % dep)
+
+tests_require = [get_require_version('proteus'),
+ get_require_version('trytond_account_invoice_stock'),
+ get_require_version('trytond_account_stock_continental'),
+ get_require_version('trytond_account_stock_anglo_saxon'),
+ get_require_version('trytond_purchase')]
+dependency_links = []
+if minor_version % 2:
+ dependency_links.append(
+ 'https://trydevpi.tryton.org/?local_version='
+ + '.'.join(local_version))
+
+setup(name=name,
+ version=version,
+ description='Tryton module for purchase shipment cost',
+ long_description=read('README.rst'),
+ author='Tryton',
+ author_email='bugs@tryton.org',
+ url='http://www.tryton.org/',
+ download_url=download_url,
+ project_urls={
+ "Bug Tracker": 'https://bugs.tryton.org/',
+ "Documentation": 'https://docs.tryton.org/',
+ "Forum": 'https://www.tryton.org/forum',
+ "Source Code": 'https://hg.tryton.org/modules/purchase_shipment_cost',
+ },
+ keywords='tryton purchase shipment cost',
+ package_dir={'trytond.modules.purchase_shipment_cost': '.'},
+ packages=(
+ ['trytond.modules.purchase_shipment_cost']
+ + ['trytond.modules.purchase_shipment_cost.%s' % p
+ for p in find_packages()]
+ ),
+ package_data={
+ 'trytond.modules.purchase_shipment_cost': (info.get('xml', [])
+ + ['tryton.cfg', 'view/*.xml', 'locale/*.po', 'tests/*.rst']),
+ },
+ classifiers=[
+ 'Development Status :: 5 - Production/Stable',
+ 'Environment :: Plugins',
+ 'Framework :: Tryton',
+ 'Intended Audience :: Developers',
+ 'Intended Audience :: Financial and Insurance Industry',
+ 'Intended Audience :: Legal Industry',
+ 'Intended Audience :: Manufacturing',
+ 'License :: OSI Approved :: '
+ 'GNU General Public License v3 or later (GPLv3+)',
+ 'Natural Language :: Bulgarian',
+ 'Natural Language :: Catalan',
+ 'Natural Language :: Chinese (Simplified)',
+ 'Natural Language :: Czech',
+ 'Natural Language :: Dutch',
+ 'Natural Language :: English',
+ 'Natural Language :: Finnish',
+ 'Natural Language :: French',
+ 'Natural Language :: German',
+ 'Natural Language :: Hungarian',
+ 'Natural Language :: Indonesian',
+ 'Natural Language :: Italian',
+ 'Natural Language :: Persian',
+ 'Natural Language :: Polish',
+ 'Natural Language :: Portuguese (Brazilian)',
+ 'Natural Language :: Romanian',
+ 'Natural Language :: Russian',
+ 'Natural Language :: Slovenian',
+ 'Natural Language :: Spanish',
+ 'Natural Language :: Turkish',
+ 'Operating System :: OS Independent',
+ 'Programming Language :: Python :: 3',
+ 'Programming Language :: Python :: 3.6',
+ 'Programming Language :: Python :: 3.7',
+ 'Programming Language :: Python :: 3.8',
+ 'Programming Language :: Python :: 3.9',
+ 'Programming Language :: Python :: Implementation :: CPython',
+ 'Programming Language :: Python :: Implementation :: PyPy',
+ 'Topic :: Office/Business',
+ ],
+ license='GPL-3',
+ python_requires='>=3.6',
+ install_requires=requires,
+ extras_require=extras_require,
+ dependency_links=dependency_links,
+ zip_safe=False,
+ entry_points="""
+ [trytond.modules]
+ purchase_shipment_cost = trytond.modules.purchase_shipment_cost
+ """,
+ test_suite='tests',
+ test_loader='trytond.test_loader:Loader',
+ tests_require=tests_require,
+ )
diff --git a/modules/purchase_shipment_cost/stock.py b/modules/purchase_shipment_cost/stock.py
new file mode 100644
index 0000000000..c96aeca6ce
--- /dev/null
+++ b/modules/purchase_shipment_cost/stock.py
@@ -0,0 +1,254 @@
+# This file is part of Tryton. The COPYRIGHT file at the top level of
+# this repository contains the full copyright notices and license terms.
+from decimal import Decimal, ROUND_DOWN, ROUND_HALF_EVEN
+from operator import itemgetter
+
+from trytond.model import ModelView, Workflow, fields
+from trytond.pyson import Eval, Bool
+from trytond.pool import Pool, PoolMeta
+from trytond.transaction import Transaction
+
+from trytond.modules.product import price_digits, round_price
+
+
+class ShipmentIn(metaclass=PoolMeta):
+ __name__ = 'stock.shipment.in'
+ carrier = fields.Many2One('carrier', 'Carrier', states={
+ 'readonly': Eval('state') != 'draft',
+ },
+ depends=['state'])
+
+ cost_currency_used = fields.Function(fields.Many2One(
+ 'currency.currency', "Cost Currency",
+ states={
+ 'invisible': Eval('cost_edit', False),
+ },
+ depends=['cost_edit']),
+ 'on_change_with_cost_currency_used')
+ cost_currency = fields.Many2One(
+ 'currency.currency', "Cost Currency",
+ states={
+ 'required': Bool(Eval('cost')),
+ 'invisible': ~Eval('cost_edit', False),
+ 'readonly': ~Eval('state').in_(['draft']),
+ },
+ depends=['cost', 'cost_edit', 'state'])
+ cost_used = fields.Function(fields.Numeric(
+ "Cost", digits=price_digits,
+ states={
+ 'invisible': Eval('cost_edit', False),
+ },
+ depends=['cost_edit']),
+ 'on_change_with_cost_used')
+ cost = fields.Numeric(
+ "Cost", digits=price_digits,
+ states={
+ 'invisible': ~Eval('cost_edit', False),
+ 'readonly': ~Eval('state').in_(['draft']),
+ },
+ depends=['cost_edit', 'state'])
+
+ cost_edit = fields.Boolean(
+ "Edit Cost",
+ states={
+ 'readonly': ~Eval('state').in_(['draft']),
+ },
+ depends=['state'],
+ help="Check to edit the cost.")
+
+ def _get_carrier_context(self):
+ return {}
+
+ @fields.depends('carrier', methods=['_get_carrier_context'])
+ def _compute_costs(self):
+ costs = {
+ 'cost': None,
+ 'cost_currency': None,
+ }
+ if self.carrier:
+ with Transaction().set_context(self._get_carrier_context()):
+ cost, currency_id = self.carrier.get_purchase_price()
+ costs['cost'] = round_price(cost)
+ costs['cost_currency'] = currency_id
+ return costs
+
+ @fields.depends(
+ 'state', 'cost_currency', 'cost_edit', methods=['_compute_costs'])
+ def on_change_with_cost_currency_used(self, name=None):
+ if (not self.cost_edit
+ and self.state not in {'cancelled', 'received', 'done'}):
+ return self._compute_costs()['cost_currency']
+ elif self.cost_currency:
+ return self.cost_currency.id
+
+ @fields.depends('state', 'cost', 'cost_edit', methods=['_compute_costs'])
+ def on_change_with_cost_used(self, name=None):
+ if (not self.cost_edit
+ and self.state not in {'cancelled', 'received', 'done'}):
+ return self._compute_costs()['cost']
+ else:
+ return self.cost
+
+ @fields.depends(
+ 'cost_edit', 'cost_used', 'cost_currency_used')
+ def on_change_cost_edit(self):
+ if self.cost_edit:
+ self.cost = self.cost_used
+ self.cost_currency = self.cost_currency_used
+
+ def allocate_cost_by_value(self):
+ pool = Pool()
+ Currency = pool.get('currency.currency')
+ Move = pool.get('stock.move')
+
+ if not self.cost_used:
+ return
+
+ cost = Currency.compute(
+ self.cost_currency_used, self.cost_used, self.company.currency,
+ round=False)
+ moves = [m for m in self.incoming_moves
+ if m.state not in ('done', 'cancelled')]
+
+ sum_value = 0
+ unit_prices = {}
+ for move in moves:
+ unit_price = Currency.compute(move.currency, move.unit_price,
+ self.company.currency, round=False)
+ unit_prices[move.id] = unit_price
+ sum_value += unit_price * Decimal(str(move.quantity))
+
+ costs = []
+ digit = Move.unit_price.digits[1]
+ exp = Decimal(str(10.0 ** -digit))
+ difference = cost
+ for move in moves:
+ quantity = Decimal(str(move.quantity))
+ if not sum_value:
+ move_cost = cost / Decimal(len(moves))
+ else:
+ move_cost = cost * quantity * unit_prices[move.id] / sum_value
+ unit_shipment_cost = round_price(
+ move_cost / quantity, rounding=ROUND_DOWN)
+ costs.append({
+ 'unit_shipment_cost': unit_shipment_cost,
+ 'difference': move_cost - (unit_shipment_cost * quantity),
+ 'move': move,
+ })
+ difference -= unit_shipment_cost * quantity
+ costs.sort(key=itemgetter('difference'))
+ for cost in costs:
+ move = cost['move']
+ quantity = Decimal(str(move.quantity))
+ if exp * quantity < difference:
+ cost['unit_shipment_cost'] += exp
+ difference -= exp * quantity
+ if difference < exp:
+ break
+
+ for cost in costs:
+ move = cost['move']
+ unit_shipment_cost = Currency.compute(
+ self.company.currency, cost['unit_shipment_cost'],
+ move.currency, round=False)
+ unit_shipment_cost = round_price(
+ unit_shipment_cost, rounding=ROUND_HALF_EVEN)
+ move.unit_price += unit_shipment_cost
+ move.unit_shipment_cost = unit_shipment_cost
+ Move.save(moves)
+
+ @classmethod
+ @ModelView.button
+ @Workflow.transition('received')
+ def receive(cls, shipments):
+ Carrier = Pool().get('carrier')
+ for shipment in shipments:
+ shipment.cost = shipment.cost_used
+ shipment.cost_currency = shipment.cost_currency_used
+ if shipment.carrier:
+ allocation_method = \
+ shipment.carrier.carrier_cost_allocation_method
+ else:
+ allocation_method = \
+ Carrier.default_carrier_cost_allocation_method()
+ getattr(shipment, 'allocate_cost_by_%s' % allocation_method)()
+ super(ShipmentIn, cls).receive(shipments)
+
+ @classmethod
+ @ModelView.button
+ @Workflow.transition('cancelled')
+ def cancel(cls, shipments):
+ for shipment in shipments:
+ shipment.cost = None
+ shipment.cost_currency = None
+ cls.save(shipments)
+ super().cancel(shipments)
+
+
+class Move(metaclass=PoolMeta):
+ __name__ = 'stock.move'
+ unit_shipment_cost = fields.Numeric('Unit Shipment Cost',
+ digits=price_digits, readonly=True)
+
+ def _compute_unit_price(self, unit_price):
+ if self.unit_shipment_cost:
+ unit_price -= self.unit_shipment_cost
+ unit_price = super()._compute_unit_price(unit_price)
+ if self.unit_shipment_cost:
+ unit_price += self.unit_shipment_cost
+ return unit_price
+
+ def _compute_component_unit_price(self, unit_price):
+ if self.unit_shipment_cost:
+ unit_price -= self.unit_shipment_cost
+ unit_price = super()._compute_component_unit_price(unit_price)
+ if self.unit_shipment_cost:
+ unit_price += self.unit_shipment_cost
+ return unit_price
+
+ # Split the shipment cost if account_stock_continental is activated
+ def _get_account_stock_move_lines(self, type_):
+ pool = Pool()
+ AccountMoveLine = pool.get('account.move.line')
+ Currency = pool.get('currency.currency')
+ move_lines = super(Move, self)._get_account_stock_move_lines(type_)
+ if (type_.startswith('in_')
+ and self.unit_shipment_cost
+ and self.shipment
+ and self.shipment.carrier):
+ shipment_cost = Currency.compute(self.currency,
+ Decimal(str(self.quantity)) * self.unit_shipment_cost,
+ self.company.currency)
+ shipment_cost_account = \
+ self.shipment.carrier.carrier_product.account_expense_used
+ account = self.product.account_stock_in_used
+ for move_line in move_lines:
+ if move_line.account == account:
+ move_line.credit -= shipment_cost
+ shipment_cost_line = AccountMoveLine(
+ debit=Decimal('0'),
+ credit=shipment_cost,
+ account=shipment_cost_account,
+ )
+ move_lines.append(shipment_cost_line)
+ break
+ else:
+ raise AssertionError('missing account_stock_supplier')
+ return move_lines
+
+ # Remove shipment cost if account_stock_anglo_saxon is activated
+ @classmethod
+ def _get_anglo_saxon_move(cls, moves, quantity, type_):
+ pool = Pool()
+ Currency = pool.get('currency.currency')
+ Uom = pool.get('product.uom')
+ for move, qty, cost_price in super(Move, cls)._get_anglo_saxon_move(
+ moves, quantity, type_):
+ if (type_.startswith('in_')
+ and move.unit_shipment_cost):
+ shipment_cost = Uom.compute_price(move.uom,
+ move.unit_shipment_cost, move.product.default_uom)
+ shipment_cost = Currency.compute(move.currency,
+ shipment_cost, move.company.currency)
+ cost_price -= shipment_cost
+ yield move, qty, cost_price
diff --git a/modules/purchase_shipment_cost/stock.xml b/modules/purchase_shipment_cost/stock.xml
new file mode 100644
index 0000000000..522151e4eb
--- /dev/null
+++ b/modules/purchase_shipment_cost/stock.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+ stock.shipment.in
+
+
+ shipment_in_form
+
+
+
diff --git a/modules/purchase_shipment_cost/tests/__init__.py b/modules/purchase_shipment_cost/tests/__init__.py
new file mode 100644
index 0000000000..8b22afd6ba
--- /dev/null
+++ b/modules/purchase_shipment_cost/tests/__init__.py
@@ -0,0 +1,9 @@
+# This file is part of Tryton. The COPYRIGHT file at the top level of
+# this repository contains the full copyright notices and license terms.
+
+try:
+ from trytond.modules.purchase_shipment_cost.tests.test_purchase_shipment_cost import suite # noqa: E501
+except ImportError:
+ from .test_purchase_shipment_cost import suite
+
+__all__ = ['suite']
diff --git a/modules/purchase_shipment_cost/tests/scenario_purchase_shipment_cost.rst b/modules/purchase_shipment_cost/tests/scenario_purchase_shipment_cost.rst
new file mode 100644
index 0000000000..c64e350f5a
--- /dev/null
+++ b/modules/purchase_shipment_cost/tests/scenario_purchase_shipment_cost.rst
@@ -0,0 +1,141 @@
+===============================
+Purchase Shipment Cost Scenario
+===============================
+
+Imports::
+
+ >>> import datetime
+ >>> from dateutil.relativedelta import relativedelta
+ >>> from decimal import Decimal
+ >>> from proteus import Model, Wizard
+ >>> from trytond.tests.tools import activate_modules
+ >>> from trytond.modules.company.tests.tools import create_company, \
+ ... get_company
+ >>> today = datetime.date.today()
+
+Activate modules::
+
+ >>> config = activate_modules('purchase_shipment_cost')
+
+Create company::
+
+ >>> _ = create_company()
+ >>> company = get_company()
+
+Create supplier::
+
+ >>> Party = Model.get('party.party')
+ >>> supplier = Party(name='Supplier')
+ >>> supplier.save()
+
+Create products::
+
+ >>> ProductUom = Model.get('product.uom')
+ >>> ProductTemplate = Model.get('product.template')
+ >>> unit, = ProductUom.find([('name', '=', 'Unit')])
+
+ >>> template = ProductTemplate()
+ >>> template.name = 'Product'
+ >>> template.default_uom = unit
+ >>> template.type = 'goods'
+ >>> template.list_price = Decimal('20')
+ >>> product, = template.products
+ >>> product.cost_price = Decimal('8')
+ >>> template.save()
+ >>> product, = template.products
+
+ >>> carrier_template = ProductTemplate()
+ >>> carrier_template.name = 'Carrier Product'
+ >>> carrier_template.default_uom = unit
+ >>> carrier_template.type = 'service'
+ >>> carrier_template.list_price = Decimal('5')
+ >>> carrier_product, = carrier_template.products
+ >>> carrier_product.cost_price = Decimal('3')
+ >>> carrier_template.save()
+ >>> carrier_product, = carrier_template.products
+
+Create carrier::
+
+ >>> Carrier = Model.get('carrier')
+ >>> carrier = Carrier()
+ >>> party = Party(name='Carrier')
+ >>> party.save()
+ >>> carrier.party = party
+ >>> carrier.carrier_product = carrier_product
+ >>> carrier.save()
+
+Receive a single product line::
+
+ >>> ShipmentIn = Model.get('stock.shipment.in')
+ >>> Move = Model.get('stock.move')
+ >>> Location = Model.get('stock.location')
+ >>> supplier_location, = Location.find([
+ ... ('code', '=', 'SUP'),
+ ... ])
+ >>> shipment = ShipmentIn()
+ >>> shipment.supplier = supplier
+ >>> move = Move()
+ >>> shipment.incoming_moves.append(move)
+ >>> move.from_location = supplier_location
+ >>> move.to_location = shipment.warehouse.input_location
+ >>> move.product = product
+ >>> move.quantity = 50
+ >>> move.unit_price = Decimal('8')
+ >>> shipment.carrier = carrier
+ >>> shipment.cost_used
+ Decimal('3.0000')
+ >>> shipment.cost_currency_used == company.currency
+ True
+ >>> shipment.click('receive')
+ >>> shipment.state
+ 'received'
+ >>> move, = shipment.incoming_moves
+ >>> move.unit_price
+ Decimal('8.0600')
+
+Receive many product lines::
+
+ >>> shipment = ShipmentIn()
+ >>> shipment.supplier = supplier
+ >>> for quantity in (1, 3, 5):
+ ... move = Move()
+ ... shipment.incoming_moves.append(move)
+ ... move.from_location = supplier_location
+ ... move.to_location = shipment.warehouse.input_location
+ ... move.product = product
+ ... move.quantity = quantity
+ ... move.unit_price = Decimal('8')
+ >>> shipment.carrier = carrier
+ >>> shipment.cost_used
+ Decimal('3.0000')
+ >>> shipment.click('receive')
+ >>> shipment.state
+ 'received'
+ >>> [move.unit_price for move in shipment.incoming_moves] == \
+ ... [Decimal('8.3333'), Decimal('8.3333'), Decimal('8.3334')]
+ True
+
+Receive a two lines with no cost::
+
+ >>> shipment = ShipmentIn()
+ >>> shipment.supplier = supplier
+ >>> move = shipment.incoming_moves.new()
+ >>> move.from_location = supplier_location
+ >>> move.to_location = shipment.warehouse.input_location
+ >>> move.product = product
+ >>> move.quantity = 75
+ >>> move.unit_price = Decimal('0.0')
+ >>> move = shipment.incoming_moves.new()
+ >>> move.from_location = supplier_location
+ >>> move.to_location = shipment.warehouse.input_location
+ >>> move.product = product
+ >>> move.quantity = 25
+ >>> move.unit_price = Decimal('0.0')
+ >>> shipment.carrier = carrier
+ >>> shipment.cost_used
+ Decimal('3.0000')
+ >>> shipment.click('receive')
+ >>> shipment.state
+ 'received'
+ >>> tuple(m.unit_price for m in shipment.incoming_moves)
+ (Decimal('0.0600'), Decimal('0.0200'))
diff --git a/modules/purchase_shipment_cost/tests/scenario_purchase_shipment_cost_invoice_stock.rst b/modules/purchase_shipment_cost/tests/scenario_purchase_shipment_cost_invoice_stock.rst
new file mode 100644
index 0000000000..222dca49e3
--- /dev/null
+++ b/modules/purchase_shipment_cost/tests/scenario_purchase_shipment_cost_invoice_stock.rst
@@ -0,0 +1,142 @@
+==================================================
+Purchase Shipment Cost with Invoice Stock Scenario
+==================================================
+
+Imports::
+
+ >>> import datetime as dt
+ >>> from decimal import Decimal
+
+ >>> from proteus import Model, Wizard
+ >>> from trytond.tests.tools import activate_modules
+ >>> from trytond.modules.company.tests.tools import (
+ ... create_company, get_company)
+ >>> from trytond.modules.account.tests.tools import (
+ ... create_fiscalyear, create_chart, get_accounts)
+ >>> from trytond.modules.account_invoice.tests.tools import (
+ ... set_fiscalyear_invoice_sequences)
+
+ >>> today = dt.date.today()
+
+Activate modules::
+
+ >>> config = activate_modules([
+ ... 'purchase_shipment_cost',
+ ... 'account_invoice_stock',
+ ... 'purchase',
+ ... ])
+
+ >>> Carrier = Model.get('carrier')
+ >>> Move = Model.get('stock.move')
+ >>> Party = Model.get('party.party')
+ >>> ProductCategory = Model.get('product.category')
+ >>> ProductTemplate = Model.get('product.template')
+ >>> ProductUom = Model.get('product.uom')
+ >>> Purchase = Model.get('purchase.purchase')
+ >>> ShipmentIn = Model.get('stock.shipment.in')
+
+Create company::
+
+ >>> _ = create_company()
+ >>> company = get_company()
+
+Create chart of accounts::
+
+ >>> _ = create_chart(company)
+ >>> accounts = get_accounts(company)
+
+Create fiscal year::
+
+ >>> fiscalyear = set_fiscalyear_invoice_sequences(
+ ... create_fiscalyear(company))
+ >>> fiscalyear.click('create_period')
+
+Create account categories::
+
+ >>> account_category = ProductCategory(name="Account Category")
+ >>> account_category.accounting = True
+ >>> account_category.account_expense = accounts['expense']
+ >>> account_category.save()
+
+Create supplier::
+
+ >>> supplier = Party(name='Supplier')
+ >>> supplier.save()
+
+Create products::
+
+ >>> unit, = ProductUom.find([('name', '=', 'Unit')])
+
+ >>> template = ProductTemplate()
+ >>> template.name = 'Product'
+ >>> template.default_uom = unit
+ >>> template.type = 'goods'
+ >>> template.list_price = Decimal('20')
+ >>> template.purchasable = True
+ >>> template.account_category = account_category
+ >>> product, = template.products
+ >>> product.cost_price = Decimal('8')
+ >>> template.save()
+ >>> product, = template.products
+
+ >>> carrier_template = ProductTemplate()
+ >>> carrier_template.name = 'Carrier Product'
+ >>> carrier_template.default_uom = unit
+ >>> carrier_template.type = 'service'
+ >>> carrier_template.list_price = Decimal('5')
+ >>> carrier_product, = carrier_template.products
+ >>> carrier_product.cost_price = Decimal('3')
+ >>> carrier_template.save()
+ >>> carrier_product, = carrier_template.products
+
+Create carrier::
+
+ >>> carrier = Carrier()
+ >>> party = Party(name='Carrier')
+ >>> party.save()
+ >>> carrier.party = party
+ >>> carrier.carrier_product = carrier_product
+ >>> carrier.save()
+
+Purchase a product::
+
+ >>> purchase = Purchase()
+ >>> purchase.party = supplier
+ >>> line = purchase.lines.new()
+ >>> line.product = product
+ >>> line.quantity = 1
+ >>> line.unit_price = Decimal('10')
+ >>> purchase.click('quote')
+ >>> purchase.click('confirm')
+ >>> purchase.state
+ 'processing'
+
+Receive the product::
+
+ >>> shipment = ShipmentIn()
+ >>> shipment.supplier = supplier
+ >>> move, = purchase.moves
+ >>> shipment.incoming_moves.append(Move(id=move.id))
+ >>> shipment.carrier = carrier
+ >>> shipment.cost_used
+ Decimal('3.0000')
+ >>> shipment.click('receive')
+ >>> shipment.state
+ 'received'
+ >>> move, = shipment.incoming_moves
+ >>> move.unit_price
+ Decimal('13.0000')
+
+Post the invoice with a different price::
+
+ >>> invoice, = purchase.invoices
+ >>> line, = invoice.lines
+ >>> line.unit_price = Decimal('9')
+ >>> invoice.invoice_date = today
+ >>> invoice.click('post')
+
+Check unit price of move::
+
+ >>> move.reload()
+ >>> move.unit_price
+ Decimal('12.0000')
diff --git a/modules/purchase_shipment_cost/tests/scenario_purchase_shipment_cost_with_account_stock.rst b/modules/purchase_shipment_cost/tests/scenario_purchase_shipment_cost_with_account_stock.rst
new file mode 100644
index 0000000000..7d73cfa9fb
--- /dev/null
+++ b/modules/purchase_shipment_cost/tests/scenario_purchase_shipment_cost_with_account_stock.rst
@@ -0,0 +1,196 @@
+==================================================
+Purchase Shipment Cost with Account Stock Scenario
+==================================================
+
+Imports::
+
+ >>> import datetime
+ >>> from dateutil.relativedelta import relativedelta
+ >>> from decimal import Decimal
+ >>> from proteus import Model, Wizard
+ >>> from trytond.tests.tools import activate_modules
+ >>> from trytond.modules.company.tests.tools import create_company, \
+ ... get_company
+ >>> from trytond.modules.account.tests.tools import create_fiscalyear, \
+ ... create_chart, get_accounts
+ >>> from trytond.modules.account_invoice.tests.tools import \
+ ... set_fiscalyear_invoice_sequences
+ >>> from trytond.modules.account_stock_continental.tests.tools import \
+ ... add_stock_accounts
+ >>> today = datetime.date.today()
+
+Activate modules::
+
+ >>> config = activate_modules([
+ ... 'purchase_shipment_cost',
+ ... 'account_stock_continental',
+ ... ])
+
+Create company::
+
+ >>> _ = create_company()
+ >>> company = get_company()
+
+Create fiscal year::
+
+ >>> fiscalyear = create_fiscalyear(company)
+ >>> fiscalyear.account_stock_method = 'continental'
+ >>> fiscalyear.click('create_period')
+
+Create chart of accounts::
+
+ >>> _ = create_chart(company)
+ >>> accounts = add_stock_accounts(get_accounts(company), company)
+ >>> receivable = accounts['receivable']
+ >>> revenue = accounts['revenue']
+ >>> expense = accounts['expense']
+ >>> stock = accounts['stock']
+ >>> stock_in = accounts['stock_expense']
+ >>> stock_out, = stock_in.duplicate()
+
+ >>> AccountJournal = Model.get('account.journal')
+ >>> stock_journal, = AccountJournal.find([('code', '=', 'STO')])
+
+Create supplier::
+
+ >>> Party = Model.get('party.party')
+ >>> supplier = Party(name='Supplier')
+ >>> supplier.save()
+
+Create account category::
+
+ >>> ProductCategory = Model.get('product.category')
+ >>> account_category = ProductCategory(name="Account Category")
+ >>> account_category.accounting = True
+ >>> account_category.account_expense = expense
+ >>> account_category.account_revenue = revenue
+ >>> account_category.account_stock = stock
+ >>> account_category.account_stock_in = stock_in
+ >>> account_category.account_stock_out = stock_out
+ >>> account_category.save()
+
+Create products::
+
+ >>> ProductUom = Model.get('product.uom')
+ >>> ProductTemplate = Model.get('product.template')
+ >>> unit, = ProductUom.find([('name', '=', 'Unit')])
+
+ >>> template = ProductTemplate()
+ >>> template.name = 'Product'
+ >>> template.default_uom = unit
+ >>> template.type = 'goods'
+ >>> template.list_price = Decimal('20')
+ >>> template.account_category = account_category
+ >>> product, = template.products
+ >>> product.cost_price = Decimal('8')
+ >>> template.save()
+ >>> product, = template.products
+ >>> template_average, = template.duplicate({
+ ... 'cost_price_method': 'average',
+ ... })
+ >>> product_average, = template_average.products
+
+ >>> carrier_template = ProductTemplate()
+ >>> carrier_template.name = 'Carrier Product'
+ >>> carrier_template.default_uom = unit
+ >>> carrier_template.type = 'service'
+ >>> carrier_template.list_price = Decimal('5')
+ >>> carrier_template.account_category = account_category
+ >>> carrier_product, = carrier_template.products
+ >>> carrier_product.cost_price = Decimal('3')
+ >>> carrier_template.save()
+ >>> carrier_product, = carrier_template.products
+
+Create carrier::
+
+ >>> Carrier = Model.get('carrier')
+ >>> carrier = Carrier()
+ >>> party = Party(name='Carrier')
+ >>> party.save()
+ >>> carrier.party = party
+ >>> carrier.carrier_product = carrier_product
+ >>> carrier.save()
+
+Receive a single product line::
+
+ >>> ShipmentIn = Model.get('stock.shipment.in')
+ >>> Move = Model.get('stock.move')
+ >>> Location = Model.get('stock.location')
+ >>> supplier_location, = Location.find([
+ ... ('code', '=', 'SUP'),
+ ... ])
+ >>> shipment = ShipmentIn()
+ >>> shipment.supplier = supplier
+ >>> move = Move()
+ >>> shipment.incoming_moves.append(move)
+ >>> move.from_location = supplier_location
+ >>> move.to_location = shipment.warehouse.input_location
+ >>> move.product = product
+ >>> move.quantity = 30
+ >>> move.unit_price = Decimal('8')
+ >>> move = Move()
+ >>> shipment.incoming_moves.append(move)
+ >>> move.from_location = supplier_location
+ >>> move.to_location = shipment.warehouse.input_location
+ >>> move.product = product_average
+ >>> move.quantity = 20
+ >>> move.unit_price = Decimal('8')
+ >>> shipment.carrier = carrier
+ >>> shipment.cost_used
+ Decimal('3.0000')
+ >>> shipment.cost_currency_used == company.currency
+ True
+ >>> shipment.click('receive')
+ >>> shipment.state
+ 'received'
+ >>> move, move_average = shipment.incoming_moves
+ >>> move.unit_price
+ Decimal('8.0600')
+ >>> move_average.unit_price
+ Decimal('8.0600')
+ >>> stock_in.reload()
+ >>> (stock_in.debit, stock_in.credit) == \
+ ... (Decimal('0.00'), Decimal('398.20'))
+ True
+ >>> expense.reload()
+ >>> (expense.debit, expense.credit) == \
+ ... (Decimal('0.00'), Decimal('3.00'))
+ True
+ >>> stock.reload()
+ >>> (stock.debit, stock.credit) == \
+ ... (Decimal('401.20'), Decimal('0.00'))
+ True
+
+Receive many product lines::
+
+ >>> shipment = ShipmentIn()
+ >>> shipment.supplier = supplier
+ >>> for quantity in (1, 3, 5):
+ ... move = Move()
+ ... shipment.incoming_moves.append(move)
+ ... move.from_location = supplier_location
+ ... move.to_location = shipment.warehouse.input_location
+ ... move.product = product
+ ... move.quantity = quantity
+ ... move.unit_price = Decimal('8')
+ >>> shipment.carrier = carrier
+ >>> shipment.cost_used
+ Decimal('3.0000')
+ >>> shipment.click('receive')
+ >>> shipment.state
+ 'received'
+ >>> [move.unit_price for move in shipment.incoming_moves] == \
+ ... [Decimal('8.3333'), Decimal('8.3333'), Decimal('8.3334')]
+ True
+ >>> stock_in.reload()
+ >>> (stock_in.debit, stock_in.credit) == \
+ ... (Decimal('0.00'), Decimal('467.20'))
+ True
+ >>> expense.reload()
+ >>> (expense.debit, expense.credit) == \
+ ... (Decimal('0.00'), Decimal('6.00'))
+ True
+ >>> stock.reload()
+ >>> (stock.debit, stock.credit) == \
+ ... (Decimal('473.20'), Decimal('0.00'))
+ True
diff --git a/modules/purchase_shipment_cost/tests/scenario_purchase_shipment_cost_with_account_stock_anglo_saxon.rst b/modules/purchase_shipment_cost/tests/scenario_purchase_shipment_cost_with_account_stock_anglo_saxon.rst
new file mode 100644
index 0000000000..82c8b85c62
--- /dev/null
+++ b/modules/purchase_shipment_cost/tests/scenario_purchase_shipment_cost_with_account_stock_anglo_saxon.rst
@@ -0,0 +1,206 @@
+==============================================================
+Purchase Shipment Cost with Account Stock Anglo-Saxon Scenario
+==============================================================
+
+Imports::
+
+ >>> import datetime
+ >>> from dateutil.relativedelta import relativedelta
+ >>> from decimal import Decimal
+ >>> from proteus import Model, Wizard
+ >>> from trytond.tests.tools import activate_modules
+ >>> from trytond.modules.company.tests.tools import create_company, \
+ ... get_company
+ >>> from trytond.modules.account.tests.tools import create_fiscalyear, \
+ ... create_chart, get_accounts
+ >>> from trytond.modules.account_invoice.tests.tools import \
+ ... set_fiscalyear_invoice_sequences, create_payment_term
+ >>> from trytond.modules.account_stock_continental.tests.tools import \
+ ... add_stock_accounts
+ >>> from trytond.modules.account_stock_anglo_saxon.tests.tools import \
+ ... add_cogs_accounts
+ >>> today = datetime.date.today()
+
+Activate modules::
+
+ >>> config = activate_modules([
+ ... 'purchase_shipment_cost',
+ ... 'account_stock_anglo_saxon',
+ ... 'purchase',
+ ... ])
+
+Create company::
+
+ >>> _ = create_company()
+ >>> company = get_company()
+
+Create fiscal year::
+
+ >>> fiscalyear = set_fiscalyear_invoice_sequences(
+ ... create_fiscalyear(company))
+ >>> fiscalyear.account_stock_method = 'anglo_saxon'
+ >>> fiscalyear.click('create_period')
+
+Create chart of accounts::
+
+ >>> _ = create_chart(company)
+ >>> accounts = add_cogs_accounts(add_stock_accounts(
+ ... get_accounts(company), company), company)
+ >>> receivable = accounts['receivable']
+ >>> payable = accounts['payable']
+ >>> revenue = accounts['revenue']
+ >>> expense = accounts['expense']
+ >>> stock = accounts['stock']
+ >>> stock_in = accounts['stock_expense']
+ >>> stock_out, = stock_in.duplicate()
+ >>> cogs = accounts['cogs']
+
+ >>> AccountJournal = Model.get('account.journal')
+ >>> stock_journal, = AccountJournal.find([('code', '=', 'STO')])
+
+Create parties::
+
+ >>> Party = Model.get('party.party')
+ >>> supplier = Party(name='Supplier')
+ >>> supplier.save()
+
+Create account category::
+
+ >>> ProductCategory = Model.get('product.category')
+ >>> account_category = ProductCategory(name="Account Category")
+ >>> account_category.accounting = True
+ >>> account_category.account_expense = expense
+ >>> account_category.account_revenue = revenue
+ >>> account_category.account_stock = stock
+ >>> account_category.account_cogs = cogs
+ >>> account_category.account_stock_in = stock_in
+ >>> account_category.account_stock_out = stock_out
+ >>> account_category.save()
+
+Create product::
+
+ >>> ProductUom = Model.get('product.uom')
+ >>> unit, = ProductUom.find([('name', '=', 'Unit')])
+ >>> ProductTemplate = Model.get('product.template')
+
+ >>> template = ProductTemplate()
+ >>> template.name = 'product'
+ >>> template.default_uom = unit
+ >>> template.type = 'goods'
+ >>> template.purchasable = True
+ >>> template.list_price = Decimal('10')
+ >>> template.cost_price_method = 'average'
+ >>> template.account_category = account_category
+ >>> product, = template.products
+ >>> product.cost_price = Decimal('5')
+ >>> template.save()
+ >>> product, = template.products
+
+ >>> carrier_template = ProductTemplate()
+ >>> carrier_template.name = 'Carrier Product'
+ >>> carrier_template.default_uom = unit
+ >>> carrier_template.type = 'service'
+ >>> carrier_template.list_price = Decimal('5')
+ >>> carrier_template.account_category = account_category
+ >>> carrier_product, = carrier_template.products
+ >>> carrier_product.cost_price = Decimal('3')
+ >>> carrier_template.save()
+ >>> carrier_product, = carrier_template.products
+
+Create carrier::
+
+ >>> Carrier = Model.get('carrier')
+ >>> carrier = Carrier()
+ >>> party = Party(name='Carrier')
+ >>> party.save()
+ >>> carrier.party = party
+ >>> carrier.carrier_product = carrier_product
+ >>> carrier.save()
+
+Create payment term::
+
+ >>> payment_term = create_payment_term()
+ >>> payment_term.save()
+
+Purchase 5 products::
+
+ >>> Purchase = Model.get('purchase.purchase')
+ >>> PurchaseLine = Model.get('purchase.line')
+ >>> purchase = Purchase()
+ >>> purchase.party = supplier
+ >>> purchase.payment_term = payment_term
+ >>> purchase.invoice_method = 'shipment'
+ >>> purchase_line = PurchaseLine()
+ >>> purchase.lines.append(purchase_line)
+ >>> purchase_line.product = product
+ >>> purchase_line.quantity = 5.0
+ >>> purchase.click('quote')
+ >>> purchase.click('confirm')
+ >>> purchase.click('process')
+ >>> purchase.state
+ 'processing'
+
+Receive 4 products::
+
+ >>> ShipmentIn = Model.get('stock.shipment.in')
+ >>> Move = Model.get('stock.move')
+ >>> shipment = ShipmentIn(supplier=supplier)
+ >>> move = Move(purchase.moves[0].id)
+ >>> move.quantity = 4.0
+ >>> shipment.incoming_moves.append(move)
+ >>> shipment.carrier = carrier
+ >>> shipment.cost_used
+ Decimal('3.0000')
+ >>> shipment.cost_currency_used == company.currency
+ True
+ >>> shipment.click('receive')
+ >>> shipment.state
+ 'received'
+ >>> move, = shipment.incoming_moves
+ >>> move.unit_price
+ Decimal('5.7500')
+ >>> shipment.click('done')
+ >>> shipment.state
+ 'done'
+ >>> stock_in.reload()
+ >>> stock.reload()
+ >>> stock_in.debit
+ Decimal('0.00')
+ >>> stock_in.credit
+ Decimal('20.00')
+ >>> stock.reload()
+ >>> stock.debit
+ Decimal('23.00')
+ >>> stock.credit
+ Decimal('0.00')
+ >>> expense.reload()
+ >>> expense.debit
+ Decimal('0.00')
+ >>> expense.credit
+ Decimal('3.00')
+
+Open supplier invoice::
+
+ >>> Invoice = Model.get('account.invoice')
+ >>> purchase.reload()
+ >>> invoice, = purchase.invoices
+ >>> invoice.invoice_date = today
+ >>> invoice.save()
+ >>> invoice.click('post')
+ >>> invoice.state
+ 'posted'
+ >>> payable.reload()
+ >>> payable.debit
+ Decimal('0.00')
+ >>> payable.credit
+ Decimal('20.00')
+ >>> expense.reload()
+ >>> expense.debit
+ Decimal('20.00')
+ >>> expense.credit
+ Decimal('23.00')
+ >>> stock_in.reload()
+ >>> stock_in.debit
+ Decimal('20.00')
+ >>> stock_in.credit
+ Decimal('20.00')
diff --git a/modules/purchase_shipment_cost/tests/test_purchase_shipment_cost.py b/modules/purchase_shipment_cost/tests/test_purchase_shipment_cost.py
new file mode 100644
index 0000000000..0ade05bf3d
--- /dev/null
+++ b/modules/purchase_shipment_cost/tests/test_purchase_shipment_cost.py
@@ -0,0 +1,41 @@
+#!/usr/bin/env python
+# This file is part of Tryton. The COPYRIGHT file at the top level of
+# this repository contains the full copyright notices and license terms.
+import unittest
+import doctest
+import trytond.tests.test_tryton
+from trytond.tests.test_tryton import ModuleTestCase
+from trytond.tests.test_tryton import doctest_teardown
+from trytond.tests.test_tryton import doctest_checker
+
+
+class PurchaseShipmentCostTestCase(ModuleTestCase):
+ 'Test Purchase Shipment Cost module'
+ module = 'purchase_shipment_cost'
+
+
+def suite():
+ suite = trytond.tests.test_tryton.suite()
+ suite.addTests(unittest.TestLoader().loadTestsFromTestCase(
+ PurchaseShipmentCostTestCase))
+ suite.addTests(doctest.DocFileSuite('scenario_purchase_shipment_cost.rst',
+ tearDown=doctest_teardown, encoding='utf-8',
+ checker=doctest_checker,
+ optionflags=doctest.REPORT_ONLY_FIRST_FAILURE))
+ suite.addTests(doctest.DocFileSuite(
+ 'scenario_purchase_shipment_cost_invoice_stock.rst',
+ tearDown=doctest_teardown, encoding='utf-8',
+ checker=doctest_checker,
+ optionflags=doctest.REPORT_ONLY_FIRST_FAILURE))
+ suite.addTests(doctest.DocFileSuite(
+ 'scenario_purchase_shipment_cost_with_account_stock.rst',
+ tearDown=doctest_teardown, encoding='utf-8',
+ checker=doctest_checker,
+ optionflags=doctest.REPORT_ONLY_FIRST_FAILURE))
+ suite.addTests(doctest.DocFileSuite(
+ 'scenario_purchase_shipment_cost_'
+ 'with_account_stock_anglo_saxon.rst',
+ tearDown=doctest_teardown, encoding='utf-8',
+ checker=doctest_checker,
+ optionflags=doctest.REPORT_ONLY_FIRST_FAILURE))
+ return suite
diff --git a/modules/purchase_shipment_cost/tox.ini b/modules/purchase_shipment_cost/tox.ini
new file mode 100644
index 0000000000..197496c0cb
--- /dev/null
+++ b/modules/purchase_shipment_cost/tox.ini
@@ -0,0 +1,15 @@
+[tox]
+envlist = {py36,py37,py38,py39}-{sqlite,postgresql},pypy3-{sqlite,postgresql}
+
+[testenv]
+commands = {envpython} setup.py test
+deps =
+ {py36,py37,py38,py39}-postgresql: psycopg2 >= 2.5
+ pypy3-postgresql: psycopg2cffi >= 2.5
+ py36-sqlite: sqlitebck
+setenv =
+ sqlite: TRYTOND_DATABASE_URI={env:SQLITE_URI:sqlite://}
+ postgresql: TRYTOND_DATABASE_URI={env:POSTGRESQL_URI:postgresql://}
+ sqlite: DB_NAME={env:SQLITE_NAME::memory:}
+ postgresql: DB_NAME={env:POSTGRESQL_NAME:test}
+install_command = pip install --pre --find-links https://trydevpi.tryton.org/?local_version={env:CI_JOB_ID:{env:CI_BUILD_NUMBER}.{env:CI_JOB_NUMBER}} {opts} {packages}
diff --git a/modules/purchase_shipment_cost/tryton.cfg b/modules/purchase_shipment_cost/tryton.cfg
new file mode 100644
index 0000000000..f524f488aa
--- /dev/null
+++ b/modules/purchase_shipment_cost/tryton.cfg
@@ -0,0 +1,18 @@
+[tryton]
+version=6.0.1
+depends:
+ carrier
+ currency
+ ir
+ product
+ res
+ stock
+extras_depend:
+ account_invoice_stock
+ account_product
+ account_stock_continental
+ account_stock_anglo_saxon
+ product_kit
+xml:
+ stock.xml
+ carrier.xml
diff --git a/modules/purchase_shipment_cost/view/carrier_form.xml b/modules/purchase_shipment_cost/view/carrier_form.xml
new file mode 100644
index 0000000000..faa61964e4
--- /dev/null
+++ b/modules/purchase_shipment_cost/view/carrier_form.xml
@@ -0,0 +1,11 @@
+
+
+
+
+
+
+
+
+
+
diff --git a/modules/purchase_shipment_cost/view/shipment_in_form.xml b/modules/purchase_shipment_cost/view/shipment_in_form.xml
new file mode 100644
index 0000000000..c19d381705
--- /dev/null
+++ b/modules/purchase_shipment_cost/view/shipment_in_form.xml
@@ -0,0 +1,18 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/modules/sale/.drone.yml b/modules/sale/.drone.yml
new file mode 100644
index 0000000000..2049d30a49
--- /dev/null
+++ b/modules/sale/.drone.yml
@@ -0,0 +1,68 @@
+clone:
+ hg:
+ image: plugins/hg
+ environment:
+ - HG_SHARE_POOL=/root/.cache/hg
+ volumes:
+ - cache:/root/.cache
+
+pipeline:
+ tox:
+ image: ${IMAGE}
+ environment:
+ - CFLAGS=-O0
+ - DB_CACHE=/cache
+ - TOX_TESTENV_PASSENV=CFLAGS DB_CACHE CI_BUILD_NUMBER CI_JOB_NUMBER CI_JOB_ID
+ - POSTGRESQL_URI=postgresql://postgres@postgresql:5432/
+ commands:
+ - echo "[extensions]" >> /root/.hgrc
+ - echo "hgext.share =" >> /root/.hgrc
+ - echo "[share]" >> /root/.hgrc
+ - echo "pool = /root/.cache/hg" >> /root/.hgrc
+ - pip install tox
+ - tox -e "${TOXENV}-${DATABASE}"
+ volumes:
+ - cache:/root/.cache
+ check_dist:
+ image: ${IMAGE}
+ commands:
+ - pip install twine
+ - python setup.py sdist
+ - twine check dist/*
+
+services:
+ postgresql:
+ image: postgres
+ environment:
+ - POSTGRES_HOST_AUTH_METHOD=trust
+ command: "-c fsync=off -c synchronous_commit=off -c full_page_writes=off"
+ when:
+ matrix:
+ DATABASE: postgresql
+
+matrix:
+ include:
+ - IMAGE: python:3.6
+ TOXENV: py36
+ DATABASE: sqlite
+ - IMAGE: python:3.6
+ TOXENV: py36
+ DATABASE: postgresql
+ - IMAGE: python:3.7
+ TOXENV: py37
+ DATABASE: sqlite
+ - IMAGE: python:3.7
+ TOXENV: py37
+ DATABASE: postgresql
+ - IMAGE: python:3.8
+ TOXENV: py38
+ DATABASE: sqlite
+ - IMAGE: python:3.8
+ TOXENV: py38
+ DATABASE: postgresql
+ - IMAGE: python:3.9
+ TOXENV: py39
+ DATABASE: sqlite
+ - IMAGE: python:3.9
+ TOXENV: py39
+ DATABASE: postgresql
diff --git a/modules/sale/.flake8 b/modules/sale/.flake8
new file mode 100644
index 0000000000..fa6b4f66d1
--- /dev/null
+++ b/modules/sale/.flake8
@@ -0,0 +1,2 @@
+[flake8]
+ignore=E123,E124,E126,E128,E741,W503
diff --git a/modules/sale/CHANGELOG b/modules/sale/CHANGELOG
new file mode 100644
index 0000000000..990375096d
--- /dev/null
+++ b/modules/sale/CHANGELOG
@@ -0,0 +1,163 @@
+Version 6.0.9 - 2022-10-17
+* Bug fixes (see mercurial logs for details)
+
+Version 6.0.8 - 2022-08-03
+* Bug fixes (see mercurial logs for details)
+
+Version 6.0.7 - 2022-07-01
+* Bug fixes (see mercurial logs for details)
+
+Version 6.0.6 - 2022-06-03
+* Bug fixes (see mercurial logs for details)
+
+Version 6.0.5 - 2022-03-01
+* Bug fixes (see mercurial logs for details)
+
+Version 6.0.4 - 2022-02-16
+* Bug fixes (see mercurial logs for details)
+
+Version 6.0.3 - 2021-11-04
+* Bug fixes (see mercurial logs for details)
+
+Version 6.0.2 - 2021-09-16
+* Bug fixes (see mercurial logs for details)
+
+Version 6.0.1 - 2021-09-01
+* Bug fixes (see mercurial logs for details)
+
+Version 6.0.0 - 2021-05-03
+* Bug fixes (see mercurial logs for details)
+* Add default lead time for products
+* Add summary to sale line list
+* Add TaxableMixin to sale line
+
+Version 5.8.0 - 2020-11-02
+* Bug fixes (see mercurial logs for details)
+* Remove support for Python 3.5
+* Use original cost price for returned move
+* Add shipping date
+* Rename sale state from cancel to cancelled
+* Add window tab for exception states
+
+Version 5.6.0 - 2020-05-04
+* Bug fixes (see mercurial logs for details)
+* Add actual quantity on line
+* Add employee on sales for some states
+* Add contact and invoice party on sale
+* Add salable products menu entry
+
+Version 5.4.0 - 2019-11-04
+* Bug fixes (see mercurial logs for details)
+
+Version 5.2.0 - 2019-05-06
+* Bug fixes (see mercurial logs for details)
+* Use sale_uom as default for Product.get_sale_price
+
+Version 5.0.0 - 2018-10-01
+* Bug fixes (see mercurial logs for details)
+* Add configured delay for processing sale
+* Allow to reset to draft confirmed but not processed sale
+* Show number and reference in sale rec_name
+* Remove support for Python 2.7
+* Invoice sold product instead of shipped product
+* Prevent delete lines if sale is not draft or canceled
+* Use today as fallback for sale date report
+
+Version 4.8.0 - 2018-04-23
+* Bug fixes (see mercurial logs for details)
+* Add reporting
+* Check pending sale to erase party
+* Add wizard to modify sale header after filling lines
+* Make description on sale line optional
+* Invoice shipped product instead of sold product
+
+Version 4.6.0 - 2017-10-30
+* Bug fixes (see mercurial logs for details)
+* Plan backorder moves to today
+* Add cron task to process confirmed sale
+* Add report_address property on sale
+
+Version 4.4.0 - 2017-05-01
+* Bug fixes (see mercurial logs for details)
+* Add sale price on product view from line
+* Allow no lead time on product
+
+Version 4.2.0 - 2016-11-28
+* Bug fixes (see mercurial logs for details)
+* Manage readonly state on Sale Line
+* Allow sale without payment term
+
+Version 4.0.0 - 2016-05-02
+* Bug fixes (see mercurial logs for details)
+* Rename Sale reference into number and add reference
+* Add Python3 support
+* Replace Delivery Time by Lead Time on Product Template
+* Rename Delivery Date of Sale Line into Shipping Date
+
+Version 3.8.0 - 2015-11-02
+* Bug fixes (see mercurial logs for details)
+* Delivery Date of Line shows effective date if possible
+* Add shipment party
+
+Version 3.6.0 - 2015-04-20
+* Bug fixes (see mercurial logs for details)
+* Add support for PyPy
+* Add origin on sale
+* Support mixed invoice type by line in invoiced quantity calculation
+* Use TaxableMixin
+
+Version 3.4.0 - 2014-10-20
+* Bug fixes (see mercurial logs for details)
+
+Version 3.2.0 - 2014-04-21
+* Bug fixes (see mercurial logs for details)
+* Add link between stock moves and invoice lines
+* Add warning for customer moves without origin
+
+Version 3.0.0 - 2013-10-21
+* Bug fixes (see mercurial logs for details)
+* Replace reference copying by relate
+
+Version 2.8.0 - 2013-04-22
+* Bug fixes (see mercurial logs for details)
+* Use origin Reference on Invoice Line and Stock Move
+
+Version 2.6.0 - 2012-10-22
+* Bug fixes (see mercurial logs for details)
+
+Version 2.4.0 - 2012-04-24
+* Bug fixes (see mercurial logs for details)
+* Manage negative amounts in sale
+* Add cache on amount fields in readonly states
+* Confirmed state split into Confirmed and Processing
+* Add a Function field delivery_date to sale line
+* Sale date is required only at confirmation
+* warehouse is not always required
+
+Version 2.2.0 - 2011-10-25
+* Bug fixes (see mercurial logs for details)
+* Add delivery time on product
+* Use compute delivery date for stock moves
+* Group stock moves on shipment using a key
+
+Version 2.0.0 - 2011-04-27
+* Bug fixes (see mercurial logs for details)
+
+Version 1.8.0 - 2010-11-01
+* Bug fixes (see mercurial logs for details)
+
+Version 1.6.0 - 2010-05-13
+* Bug fixes (see mercurial logs for details)
+* Use a modelsingleton to define which sale sequence to use
+* Add default search value on sale
+
+Version 1.4.0 - 2009-10-19
+* Bug fixes (see mercurial logs for details)
+
+Version 1.2.0 - 2009-04-20
+* Bug fixes (see mercurial logs for details)
+* Add buttons to handle invoice and packing exceptions
+* Allow egg installation
+
+Version 1.0.0 - 2008-11-17
+* Initial release
diff --git a/modules/sale/COPYRIGHT b/modules/sale/COPYRIGHT
new file mode 100644
index 0000000000..f66a9e26c1
--- /dev/null
+++ b/modules/sale/COPYRIGHT
@@ -0,0 +1,17 @@
+Copyright (C) 2008-2022 Cédric Krier.
+Copyright (C) 2008-2013 Bertrand Chenal.
+Copyright (C) 2008-2022 B2CK SPRL.
+Copyright (C) 2004-2008 Tiny SPRL.
+
+This program is free software: you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation, either version 3 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program. If not, see .
diff --git a/modules/sale/LICENSE b/modules/sale/LICENSE
new file mode 100644
index 0000000000..94a9ed024d
--- /dev/null
+++ b/modules/sale/LICENSE
@@ -0,0 +1,674 @@
+ GNU GENERAL PUBLIC LICENSE
+ Version 3, 29 June 2007
+
+ Copyright (C) 2007 Free Software Foundation, Inc.
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+ Preamble
+
+ The GNU General Public License is a free, copyleft license for
+software and other kinds of works.
+
+ The licenses for most software and other practical works are designed
+to take away your freedom to share and change the works. By contrast,
+the GNU General Public License is intended to guarantee your freedom to
+share and change all versions of a program--to make sure it remains free
+software for all its users. We, the Free Software Foundation, use the
+GNU General Public License for most of our software; it applies also to
+any other work released this way by its authors. You can apply it to
+your programs, too.
+
+ When we speak of free software, we are referring to freedom, not
+price. Our General Public Licenses are designed to make sure that you
+have the freedom to distribute copies of free software (and charge for
+them if you wish), that you receive source code or can get it if you
+want it, that you can change the software or use pieces of it in new
+free programs, and that you know you can do these things.
+
+ To protect your rights, we need to prevent others from denying you
+these rights or asking you to surrender the rights. Therefore, you have
+certain responsibilities if you distribute copies of the software, or if
+you modify it: responsibilities to respect the freedom of others.
+
+ For example, if you distribute copies of such a program, whether
+gratis or for a fee, you must pass on to the recipients the same
+freedoms that you received. You must make sure that they, too, receive
+or can get the source code. And you must show them these terms so they
+know their rights.
+
+ Developers that use the GNU GPL protect your rights with two steps:
+(1) assert copyright on the software, and (2) offer you this License
+giving you legal permission to copy, distribute and/or modify it.
+
+ For the developers' and authors' protection, the GPL clearly explains
+that there is no warranty for this free software. For both users' and
+authors' sake, the GPL requires that modified versions be marked as
+changed, so that their problems will not be attributed erroneously to
+authors of previous versions.
+
+ Some devices are designed to deny users access to install or run
+modified versions of the software inside them, although the manufacturer
+can do so. This is fundamentally incompatible with the aim of
+protecting users' freedom to change the software. The systematic
+pattern of such abuse occurs in the area of products for individuals to
+use, which is precisely where it is most unacceptable. Therefore, we
+have designed this version of the GPL to prohibit the practice for those
+products. If such problems arise substantially in other domains, we
+stand ready to extend this provision to those domains in future versions
+of the GPL, as needed to protect the freedom of users.
+
+ Finally, every program is threatened constantly by software patents.
+States should not allow patents to restrict development and use of
+software on general-purpose computers, but in those that do, we wish to
+avoid the special danger that patents applied to a free program could
+make it effectively proprietary. To prevent this, the GPL assures that
+patents cannot be used to render the program non-free.
+
+ The precise terms and conditions for copying, distribution and
+modification follow.
+
+ TERMS AND CONDITIONS
+
+ 0. Definitions.
+
+ "This License" refers to version 3 of the GNU General Public License.
+
+ "Copyright" also means copyright-like laws that apply to other kinds of
+works, such as semiconductor masks.
+
+ "The Program" refers to any copyrightable work licensed under this
+License. Each licensee is addressed as "you". "Licensees" and
+"recipients" may be individuals or organizations.
+
+ To "modify" a work means to copy from or adapt all or part of the work
+in a fashion requiring copyright permission, other than the making of an
+exact copy. The resulting work is called a "modified version" of the
+earlier work or a work "based on" the earlier work.
+
+ A "covered work" means either the unmodified Program or a work based
+on the Program.
+
+ To "propagate" a work means to do anything with it that, without
+permission, would make you directly or secondarily liable for
+infringement under applicable copyright law, except executing it on a
+computer or modifying a private copy. Propagation includes copying,
+distribution (with or without modification), making available to the
+public, and in some countries other activities as well.
+
+ To "convey" a work means any kind of propagation that enables other
+parties to make or receive copies. Mere interaction with a user through
+a computer network, with no transfer of a copy, is not conveying.
+
+ An interactive user interface displays "Appropriate Legal Notices"
+to the extent that it includes a convenient and prominently visible
+feature that (1) displays an appropriate copyright notice, and (2)
+tells the user that there is no warranty for the work (except to the
+extent that warranties are provided), that licensees may convey the
+work under this License, and how to view a copy of this License. If
+the interface presents a list of user commands or options, such as a
+menu, a prominent item in the list meets this criterion.
+
+ 1. Source Code.
+
+ The "source code" for a work means the preferred form of the work
+for making modifications to it. "Object code" means any non-source
+form of a work.
+
+ A "Standard Interface" means an interface that either is an official
+standard defined by a recognized standards body, or, in the case of
+interfaces specified for a particular programming language, one that
+is widely used among developers working in that language.
+
+ The "System Libraries" of an executable work include anything, other
+than the work as a whole, that (a) is included in the normal form of
+packaging a Major Component, but which is not part of that Major
+Component, and (b) serves only to enable use of the work with that
+Major Component, or to implement a Standard Interface for which an
+implementation is available to the public in source code form. A
+"Major Component", in this context, means a major essential component
+(kernel, window system, and so on) of the specific operating system
+(if any) on which the executable work runs, or a compiler used to
+produce the work, or an object code interpreter used to run it.
+
+ The "Corresponding Source" for a work in object code form means all
+the source code needed to generate, install, and (for an executable
+work) run the object code and to modify the work, including scripts to
+control those activities. However, it does not include the work's
+System Libraries, or general-purpose tools or generally available free
+programs which are used unmodified in performing those activities but
+which are not part of the work. For example, Corresponding Source
+includes interface definition files associated with source files for
+the work, and the source code for shared libraries and dynamically
+linked subprograms that the work is specifically designed to require,
+such as by intimate data communication or control flow between those
+subprograms and other parts of the work.
+
+ The Corresponding Source need not include anything that users
+can regenerate automatically from other parts of the Corresponding
+Source.
+
+ The Corresponding Source for a work in source code form is that
+same work.
+
+ 2. Basic Permissions.
+
+ All rights granted under this License are granted for the term of
+copyright on the Program, and are irrevocable provided the stated
+conditions are met. This License explicitly affirms your unlimited
+permission to run the unmodified Program. The output from running a
+covered work is covered by this License only if the output, given its
+content, constitutes a covered work. This License acknowledges your
+rights of fair use or other equivalent, as provided by copyright law.
+
+ You may make, run and propagate covered works that you do not
+convey, without conditions so long as your license otherwise remains
+in force. You may convey covered works to others for the sole purpose
+of having them make modifications exclusively for you, or provide you
+with facilities for running those works, provided that you comply with
+the terms of this License in conveying all material for which you do
+not control copyright. Those thus making or running the covered works
+for you must do so exclusively on your behalf, under your direction
+and control, on terms that prohibit them from making any copies of
+your copyrighted material outside their relationship with you.
+
+ Conveying under any other circumstances is permitted solely under
+the conditions stated below. Sublicensing is not allowed; section 10
+makes it unnecessary.
+
+ 3. Protecting Users' Legal Rights From Anti-Circumvention Law.
+
+ No covered work shall be deemed part of an effective technological
+measure under any applicable law fulfilling obligations under article
+11 of the WIPO copyright treaty adopted on 20 December 1996, or
+similar laws prohibiting or restricting circumvention of such
+measures.
+
+ When you convey a covered work, you waive any legal power to forbid
+circumvention of technological measures to the extent such circumvention
+is effected by exercising rights under this License with respect to
+the covered work, and you disclaim any intention to limit operation or
+modification of the work as a means of enforcing, against the work's
+users, your or third parties' legal rights to forbid circumvention of
+technological measures.
+
+ 4. Conveying Verbatim Copies.
+
+ You may convey verbatim copies of the Program's source code as you
+receive it, in any medium, provided that you conspicuously and
+appropriately publish on each copy an appropriate copyright notice;
+keep intact all notices stating that this License and any
+non-permissive terms added in accord with section 7 apply to the code;
+keep intact all notices of the absence of any warranty; and give all
+recipients a copy of this License along with the Program.
+
+ You may charge any price or no price for each copy that you convey,
+and you may offer support or warranty protection for a fee.
+
+ 5. Conveying Modified Source Versions.
+
+ You may convey a work based on the Program, or the modifications to
+produce it from the Program, in the form of source code under the
+terms of section 4, provided that you also meet all of these conditions:
+
+ a) The work must carry prominent notices stating that you modified
+ it, and giving a relevant date.
+
+ b) The work must carry prominent notices stating that it is
+ released under this License and any conditions added under section
+ 7. This requirement modifies the requirement in section 4 to
+ "keep intact all notices".
+
+ c) You must license the entire work, as a whole, under this
+ License to anyone who comes into possession of a copy. This
+ License will therefore apply, along with any applicable section 7
+ additional terms, to the whole of the work, and all its parts,
+ regardless of how they are packaged. This License gives no
+ permission to license the work in any other way, but it does not
+ invalidate such permission if you have separately received it.
+
+ d) If the work has interactive user interfaces, each must display
+ Appropriate Legal Notices; however, if the Program has interactive
+ interfaces that do not display Appropriate Legal Notices, your
+ work need not make them do so.
+
+ A compilation of a covered work with other separate and independent
+works, which are not by their nature extensions of the covered work,
+and which are not combined with it such as to form a larger program,
+in or on a volume of a storage or distribution medium, is called an
+"aggregate" if the compilation and its resulting copyright are not
+used to limit the access or legal rights of the compilation's users
+beyond what the individual works permit. Inclusion of a covered work
+in an aggregate does not cause this License to apply to the other
+parts of the aggregate.
+
+ 6. Conveying Non-Source Forms.
+
+ You may convey a covered work in object code form under the terms
+of sections 4 and 5, provided that you also convey the
+machine-readable Corresponding Source under the terms of this License,
+in one of these ways:
+
+ a) Convey the object code in, or embodied in, a physical product
+ (including a physical distribution medium), accompanied by the
+ Corresponding Source fixed on a durable physical medium
+ customarily used for software interchange.
+
+ b) Convey the object code in, or embodied in, a physical product
+ (including a physical distribution medium), accompanied by a
+ written offer, valid for at least three years and valid for as
+ long as you offer spare parts or customer support for that product
+ model, to give anyone who possesses the object code either (1) a
+ copy of the Corresponding Source for all the software in the
+ product that is covered by this License, on a durable physical
+ medium customarily used for software interchange, for a price no
+ more than your reasonable cost of physically performing this
+ conveying of source, or (2) access to copy the
+ Corresponding Source from a network server at no charge.
+
+ c) Convey individual copies of the object code with a copy of the
+ written offer to provide the Corresponding Source. This
+ alternative is allowed only occasionally and noncommercially, and
+ only if you received the object code with such an offer, in accord
+ with subsection 6b.
+
+ d) Convey the object code by offering access from a designated
+ place (gratis or for a charge), and offer equivalent access to the
+ Corresponding Source in the same way through the same place at no
+ further charge. You need not require recipients to copy the
+ Corresponding Source along with the object code. If the place to
+ copy the object code is a network server, the Corresponding Source
+ may be on a different server (operated by you or a third party)
+ that supports equivalent copying facilities, provided you maintain
+ clear directions next to the object code saying where to find the
+ Corresponding Source. Regardless of what server hosts the
+ Corresponding Source, you remain obligated to ensure that it is
+ available for as long as needed to satisfy these requirements.
+
+ e) Convey the object code using peer-to-peer transmission, provided
+ you inform other peers where the object code and Corresponding
+ Source of the work are being offered to the general public at no
+ charge under subsection 6d.
+
+ A separable portion of the object code, whose source code is excluded
+from the Corresponding Source as a System Library, need not be
+included in conveying the object code work.
+
+ A "User Product" is either (1) a "consumer product", which means any
+tangible personal property which is normally used for personal, family,
+or household purposes, or (2) anything designed or sold for incorporation
+into a dwelling. In determining whether a product is a consumer product,
+doubtful cases shall be resolved in favor of coverage. For a particular
+product received by a particular user, "normally used" refers to a
+typical or common use of that class of product, regardless of the status
+of the particular user or of the way in which the particular user
+actually uses, or expects or is expected to use, the product. A product
+is a consumer product regardless of whether the product has substantial
+commercial, industrial or non-consumer uses, unless such uses represent
+the only significant mode of use of the product.
+
+ "Installation Information" for a User Product means any methods,
+procedures, authorization keys, or other information required to install
+and execute modified versions of a covered work in that User Product from
+a modified version of its Corresponding Source. The information must
+suffice to ensure that the continued functioning of the modified object
+code is in no case prevented or interfered with solely because
+modification has been made.
+
+ If you convey an object code work under this section in, or with, or
+specifically for use in, a User Product, and the conveying occurs as
+part of a transaction in which the right of possession and use of the
+User Product is transferred to the recipient in perpetuity or for a
+fixed term (regardless of how the transaction is characterized), the
+Corresponding Source conveyed under this section must be accompanied
+by the Installation Information. But this requirement does not apply
+if neither you nor any third party retains the ability to install
+modified object code on the User Product (for example, the work has
+been installed in ROM).
+
+ The requirement to provide Installation Information does not include a
+requirement to continue to provide support service, warranty, or updates
+for a work that has been modified or installed by the recipient, or for
+the User Product in which it has been modified or installed. Access to a
+network may be denied when the modification itself materially and
+adversely affects the operation of the network or violates the rules and
+protocols for communication across the network.
+
+ Corresponding Source conveyed, and Installation Information provided,
+in accord with this section must be in a format that is publicly
+documented (and with an implementation available to the public in
+source code form), and must require no special password or key for
+unpacking, reading or copying.
+
+ 7. Additional Terms.
+
+ "Additional permissions" are terms that supplement the terms of this
+License by making exceptions from one or more of its conditions.
+Additional permissions that are applicable to the entire Program shall
+be treated as though they were included in this License, to the extent
+that they are valid under applicable law. If additional permissions
+apply only to part of the Program, that part may be used separately
+under those permissions, but the entire Program remains governed by
+this License without regard to the additional permissions.
+
+ When you convey a copy of a covered work, you may at your option
+remove any additional permissions from that copy, or from any part of
+it. (Additional permissions may be written to require their own
+removal in certain cases when you modify the work.) You may place
+additional permissions on material, added by you to a covered work,
+for which you have or can give appropriate copyright permission.
+
+ Notwithstanding any other provision of this License, for material you
+add to a covered work, you may (if authorized by the copyright holders of
+that material) supplement the terms of this License with terms:
+
+ a) Disclaiming warranty or limiting liability differently from the
+ terms of sections 15 and 16 of this License; or
+
+ b) Requiring preservation of specified reasonable legal notices or
+ author attributions in that material or in the Appropriate Legal
+ Notices displayed by works containing it; or
+
+ c) Prohibiting misrepresentation of the origin of that material, or
+ requiring that modified versions of such material be marked in
+ reasonable ways as different from the original version; or
+
+ d) Limiting the use for publicity purposes of names of licensors or
+ authors of the material; or
+
+ e) Declining to grant rights under trademark law for use of some
+ trade names, trademarks, or service marks; or
+
+ f) Requiring indemnification of licensors and authors of that
+ material by anyone who conveys the material (or modified versions of
+ it) with contractual assumptions of liability to the recipient, for
+ any liability that these contractual assumptions directly impose on
+ those licensors and authors.
+
+ All other non-permissive additional terms are considered "further
+restrictions" within the meaning of section 10. If the Program as you
+received it, or any part of it, contains a notice stating that it is
+governed by this License along with a term that is a further
+restriction, you may remove that term. If a license document contains
+a further restriction but permits relicensing or conveying under this
+License, you may add to a covered work material governed by the terms
+of that license document, provided that the further restriction does
+not survive such relicensing or conveying.
+
+ If you add terms to a covered work in accord with this section, you
+must place, in the relevant source files, a statement of the
+additional terms that apply to those files, or a notice indicating
+where to find the applicable terms.
+
+ Additional terms, permissive or non-permissive, may be stated in the
+form of a separately written license, or stated as exceptions;
+the above requirements apply either way.
+
+ 8. Termination.
+
+ You may not propagate or modify a covered work except as expressly
+provided under this License. Any attempt otherwise to propagate or
+modify it is void, and will automatically terminate your rights under
+this License (including any patent licenses granted under the third
+paragraph of section 11).
+
+ However, if you cease all violation of this License, then your
+license from a particular copyright holder is reinstated (a)
+provisionally, unless and until the copyright holder explicitly and
+finally terminates your license, and (b) permanently, if the copyright
+holder fails to notify you of the violation by some reasonable means
+prior to 60 days after the cessation.
+
+ Moreover, your license from a particular copyright holder is
+reinstated permanently if the copyright holder notifies you of the
+violation by some reasonable means, this is the first time you have
+received notice of violation of this License (for any work) from that
+copyright holder, and you cure the violation prior to 30 days after
+your receipt of the notice.
+
+ Termination of your rights under this section does not terminate the
+licenses of parties who have received copies or rights from you under
+this License. If your rights have been terminated and not permanently
+reinstated, you do not qualify to receive new licenses for the same
+material under section 10.
+
+ 9. Acceptance Not Required for Having Copies.
+
+ You are not required to accept this License in order to receive or
+run a copy of the Program. Ancillary propagation of a covered work
+occurring solely as a consequence of using peer-to-peer transmission
+to receive a copy likewise does not require acceptance. However,
+nothing other than this License grants you permission to propagate or
+modify any covered work. These actions infringe copyright if you do
+not accept this License. Therefore, by modifying or propagating a
+covered work, you indicate your acceptance of this License to do so.
+
+ 10. Automatic Licensing of Downstream Recipients.
+
+ Each time you convey a covered work, the recipient automatically
+receives a license from the original licensors, to run, modify and
+propagate that work, subject to this License. You are not responsible
+for enforcing compliance by third parties with this License.
+
+ An "entity transaction" is a transaction transferring control of an
+organization, or substantially all assets of one, or subdividing an
+organization, or merging organizations. If propagation of a covered
+work results from an entity transaction, each party to that
+transaction who receives a copy of the work also receives whatever
+licenses to the work the party's predecessor in interest had or could
+give under the previous paragraph, plus a right to possession of the
+Corresponding Source of the work from the predecessor in interest, if
+the predecessor has it or can get it with reasonable efforts.
+
+ You may not impose any further restrictions on the exercise of the
+rights granted or affirmed under this License. For example, you may
+not impose a license fee, royalty, or other charge for exercise of
+rights granted under this License, and you may not initiate litigation
+(including a cross-claim or counterclaim in a lawsuit) alleging that
+any patent claim is infringed by making, using, selling, offering for
+sale, or importing the Program or any portion of it.
+
+ 11. Patents.
+
+ A "contributor" is a copyright holder who authorizes use under this
+License of the Program or a work on which the Program is based. The
+work thus licensed is called the contributor's "contributor version".
+
+ A contributor's "essential patent claims" are all patent claims
+owned or controlled by the contributor, whether already acquired or
+hereafter acquired, that would be infringed by some manner, permitted
+by this License, of making, using, or selling its contributor version,
+but do not include claims that would be infringed only as a
+consequence of further modification of the contributor version. For
+purposes of this definition, "control" includes the right to grant
+patent sublicenses in a manner consistent with the requirements of
+this License.
+
+ Each contributor grants you a non-exclusive, worldwide, royalty-free
+patent license under the contributor's essential patent claims, to
+make, use, sell, offer for sale, import and otherwise run, modify and
+propagate the contents of its contributor version.
+
+ In the following three paragraphs, a "patent license" is any express
+agreement or commitment, however denominated, not to enforce a patent
+(such as an express permission to practice a patent or covenant not to
+sue for patent infringement). To "grant" such a patent license to a
+party means to make such an agreement or commitment not to enforce a
+patent against the party.
+
+ If you convey a covered work, knowingly relying on a patent license,
+and the Corresponding Source of the work is not available for anyone
+to copy, free of charge and under the terms of this License, through a
+publicly available network server or other readily accessible means,
+then you must either (1) cause the Corresponding Source to be so
+available, or (2) arrange to deprive yourself of the benefit of the
+patent license for this particular work, or (3) arrange, in a manner
+consistent with the requirements of this License, to extend the patent
+license to downstream recipients. "Knowingly relying" means you have
+actual knowledge that, but for the patent license, your conveying the
+covered work in a country, or your recipient's use of the covered work
+in a country, would infringe one or more identifiable patents in that
+country that you have reason to believe are valid.
+
+ If, pursuant to or in connection with a single transaction or
+arrangement, you convey, or propagate by procuring conveyance of, a
+covered work, and grant a patent license to some of the parties
+receiving the covered work authorizing them to use, propagate, modify
+or convey a specific copy of the covered work, then the patent license
+you grant is automatically extended to all recipients of the covered
+work and works based on it.
+
+ A patent license is "discriminatory" if it does not include within
+the scope of its coverage, prohibits the exercise of, or is
+conditioned on the non-exercise of one or more of the rights that are
+specifically granted under this License. You may not convey a covered
+work if you are a party to an arrangement with a third party that is
+in the business of distributing software, under which you make payment
+to the third party based on the extent of your activity of conveying
+the work, and under which the third party grants, to any of the
+parties who would receive the covered work from you, a discriminatory
+patent license (a) in connection with copies of the covered work
+conveyed by you (or copies made from those copies), or (b) primarily
+for and in connection with specific products or compilations that
+contain the covered work, unless you entered into that arrangement,
+or that patent license was granted, prior to 28 March 2007.
+
+ Nothing in this License shall be construed as excluding or limiting
+any implied license or other defenses to infringement that may
+otherwise be available to you under applicable patent law.
+
+ 12. No Surrender of Others' Freedom.
+
+ If conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License. If you cannot convey a
+covered work so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you may
+not convey it at all. For example, if you agree to terms that obligate you
+to collect a royalty for further conveying from those to whom you convey
+the Program, the only way you could satisfy both those terms and this
+License would be to refrain entirely from conveying the Program.
+
+ 13. Use with the GNU Affero General Public License.
+
+ Notwithstanding any other provision of this License, you have
+permission to link or combine any covered work with a work licensed
+under version 3 of the GNU Affero General Public License into a single
+combined work, and to convey the resulting work. The terms of this
+License will continue to apply to the part which is the covered work,
+but the special requirements of the GNU Affero General Public License,
+section 13, concerning interaction through a network will apply to the
+combination as such.
+
+ 14. Revised Versions of this License.
+
+ The Free Software Foundation may publish revised and/or new versions of
+the GNU General Public License from time to time. Such new versions will
+be similar in spirit to the present version, but may differ in detail to
+address new problems or concerns.
+
+ Each version is given a distinguishing version number. If the
+Program specifies that a certain numbered version of the GNU General
+Public License "or any later version" applies to it, you have the
+option of following the terms and conditions either of that numbered
+version or of any later version published by the Free Software
+Foundation. If the Program does not specify a version number of the
+GNU General Public License, you may choose any version ever published
+by the Free Software Foundation.
+
+ If the Program specifies that a proxy can decide which future
+versions of the GNU General Public License can be used, that proxy's
+public statement of acceptance of a version permanently authorizes you
+to choose that version for the Program.
+
+ Later license versions may give you additional or different
+permissions. However, no additional obligations are imposed on any
+author or copyright holder as a result of your choosing to follow a
+later version.
+
+ 15. Disclaimer of Warranty.
+
+ THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY
+APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT
+HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY
+OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO,
+THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM
+IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF
+ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
+
+ 16. Limitation of Liability.
+
+ IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS
+THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY
+GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE
+USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF
+DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD
+PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS),
+EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF
+SUCH DAMAGES.
+
+ 17. Interpretation of Sections 15 and 16.
+
+ If the disclaimer of warranty and limitation of liability provided
+above cannot be given local legal effect according to their terms,
+reviewing courts shall apply local law that most closely approximates
+an absolute waiver of all civil liability in connection with the
+Program, unless a warranty or assumption of liability accompanies a
+copy of the Program in return for a fee.
+
+ END OF TERMS AND CONDITIONS
+
+ How to Apply These Terms to Your New Programs
+
+ If you develop a new program, and you want it to be of the greatest
+possible use to the public, the best way to achieve this is to make it
+free software which everyone can redistribute and change under these terms.
+
+ To do so, attach the following notices to the program. It is safest
+to attach them to the start of each source file to most effectively
+state the exclusion of warranty; and each file should have at least
+the "copyright" line and a pointer to where the full notice is found.
+
+
+ Copyright (C)
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see .
+
+Also add information on how to contact you by electronic and paper mail.
+
+ If the program does terminal interaction, make it output a short
+notice like this when it starts in an interactive mode:
+
+ Copyright (C)
+ This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
+ This is free software, and you are welcome to redistribute it
+ under certain conditions; type `show c' for details.
+
+The hypothetical commands `show w' and `show c' should show the appropriate
+parts of the General Public License. Of course, your program's commands
+might be different; for a GUI interface, you would use an "about box".
+
+ You should also get your employer (if you work as a programmer) or school,
+if any, to sign a "copyright disclaimer" for the program, if necessary.
+For more information on this, and how to apply and follow the GNU GPL, see
+.
+
+ The GNU General Public License does not permit incorporating your program
+into proprietary programs. If your program is a subroutine library, you
+may consider it more useful to permit linking proprietary applications with
+the library. If this is what you want to do, use the GNU Lesser General
+Public License instead of this License. But first, please read
+.
diff --git a/modules/sale/MANIFEST.in b/modules/sale/MANIFEST.in
new file mode 100644
index 0000000000..94499680c6
--- /dev/null
+++ b/modules/sale/MANIFEST.in
@@ -0,0 +1,6 @@
+include CHANGELOG
+include COPYRIGHT
+include LICENSE
+include README.rst
+include doc/*
+include icons/LICENSE
diff --git a/modules/sale/README.rst b/modules/sale/README.rst
new file mode 120000
index 0000000000..176d9c2695
--- /dev/null
+++ b/modules/sale/README.rst
@@ -0,0 +1 @@
+doc/index.rst
\ No newline at end of file
diff --git a/modules/sale/__init__.py b/modules/sale/__init__.py
new file mode 100644
index 0000000000..30ff37e2fd
--- /dev/null
+++ b/modules/sale/__init__.py
@@ -0,0 +1,65 @@
+# This file is part of Tryton. The COPYRIGHT file at the top level of
+# this repository contains the full copyright notices and license terms.
+
+from trytond.pool import Pool
+from . import sale
+from . import product
+from . import stock
+from . import configuration
+from . import invoice
+from . import party
+from . import sale_reporting
+
+
+def register():
+ Pool.register(
+ stock.Move,
+ sale.Sale,
+ sale.SaleIgnoredInvoice,
+ sale.SaleRecreatedInvoice,
+ sale.SaleLine,
+ sale.SaleLineTax,
+ sale.SaleLineIgnoredMove,
+ sale.SaleLineRecreatedMove,
+ product.Configuration,
+ product.DefaultLeadTime,
+ product.Template,
+ product.Product,
+ product.SaleContext,
+ stock.ShipmentOut,
+ stock.ShipmentOutReturn,
+ sale.HandleShipmentExceptionAsk,
+ sale.HandleInvoiceExceptionAsk,
+ sale.ReturnSaleStart,
+ configuration.Configuration,
+ configuration.ConfigurationSequence,
+ configuration.ConfigurationSaleMethod,
+ sale_reporting.Context,
+ sale_reporting.Customer,
+ sale_reporting.CustomerTimeseries,
+ sale_reporting.Product,
+ sale_reporting.ProductTimeseries,
+ sale_reporting.Category,
+ sale_reporting.CategoryTimeseries,
+ sale_reporting.CategoryTree,
+ sale_reporting.Country,
+ sale_reporting.CountryTimeseries,
+ sale_reporting.Subdivision,
+ sale_reporting.SubdivisionTimeseries,
+ sale_reporting.Region,
+ invoice.Invoice,
+ invoice.Line,
+ module='sale', type_='model')
+ Pool.register(
+ sale.OpenCustomer,
+ sale.HandleShipmentException,
+ sale.HandleInvoiceException,
+ sale.ReturnSale,
+ sale.ModifyHeader,
+ party.Replace,
+ party.Erase,
+ sale_reporting.OpenRegion,
+ module='sale', type_='wizard')
+ Pool.register(
+ sale.SaleReport,
+ module='sale', type_='report')
diff --git a/modules/sale/configuration.py b/modules/sale/configuration.py
new file mode 100644
index 0000000000..6a1ec87a77
--- /dev/null
+++ b/modules/sale/configuration.py
@@ -0,0 +1,140 @@
+# This file is part of Tryton. The COPYRIGHT file at the top level of
+# this repository contains the full copyright notices and license terms.
+from trytond import backend
+from trytond.model import (ModelView, ModelSQL, ModelSingleton, ValueMixin,
+ fields)
+from trytond.pool import Pool
+from trytond.pyson import Eval, Id
+from trytond.tools.multivalue import migrate_property
+from trytond.modules.company.model import (
+ CompanyMultiValueMixin, CompanyValueMixin)
+
+sale_invoice_method = fields.Selection(
+ 'get_sale_invoice_methods', "Sale Invoice Method")
+sale_shipment_method = fields.Selection(
+ 'get_sale_shipment_methods', "Sale Shipment Method")
+
+
+def get_sale_methods(field_name):
+ @classmethod
+ def func(cls):
+ pool = Pool()
+ Sale = pool.get('sale.sale')
+ return Sale.fields_get([field_name])[field_name]['selection']
+ return func
+
+
+def default_func(field_name):
+ @classmethod
+ def default(cls, **pattern):
+ return getattr(
+ cls.multivalue_model(field_name),
+ 'default_%s' % field_name, lambda: None)()
+ return default
+
+
+class Configuration(
+ ModelSingleton, ModelSQL, ModelView, CompanyMultiValueMixin):
+ 'Sale Configuration'
+ __name__ = 'sale.configuration'
+ sale_sequence = fields.MultiValue(fields.Many2One(
+ 'ir.sequence', "Sale Sequence", required=True,
+ domain=[
+ ('company', 'in',
+ [Eval('context', {}).get('company', -1), None]),
+ ('sequence_type', '=', Id('sale', 'sequence_type_sale')),
+ ]))
+ sale_invoice_method = fields.MultiValue(sale_invoice_method)
+ get_sale_invoice_methods = get_sale_methods('invoice_method')
+ sale_shipment_method = fields.MultiValue(sale_shipment_method)
+ get_sale_shipment_methods = get_sale_methods('shipment_method')
+ sale_process_after = fields.TimeDelta("Process Sale after",
+ help="The grace period during which confirmed sale "
+ "can still be reset to draft.\n"
+ "Applied if a worker queue is activated.")
+
+ @classmethod
+ def multivalue_model(cls, field):
+ pool = Pool()
+ if field in {'sale_invoice_method', 'sale_shipment_method'}:
+ return pool.get('sale.configuration.sale_method')
+ if field == 'sale_sequence':
+ return pool.get('sale.configuration.sequence')
+ return super(Configuration, cls).multivalue_model(field)
+
+ default_sale_sequence = default_func('sale_sequence')
+ default_sale_invoice_method = default_func('sale_invoice_method')
+ default_sale_shipment_method = default_func('sale_shipment_method')
+
+
+class ConfigurationSequence(ModelSQL, CompanyValueMixin):
+ "Sale Configuration Sequence"
+ __name__ = 'sale.configuration.sequence'
+ sale_sequence = fields.Many2One(
+ 'ir.sequence', "Sale Sequence", required=True,
+ domain=[
+ ('company', 'in', [Eval('company', -1), None]),
+ ('sequence_type', '=', Id('sale', 'sequence_type_sale')),
+ ],
+ depends=['company'])
+
+ @classmethod
+ def __register__(cls, module_name):
+ exist = backend.TableHandler.table_exist(cls._table)
+
+ super(ConfigurationSequence, cls).__register__(module_name)
+
+ if not exist:
+ cls._migrate_property([], [], [])
+
+ @classmethod
+ def _migrate_property(cls, field_names, value_names, fields):
+ field_names.append('sale_sequence')
+ value_names.append('sale_sequence')
+ fields.append('company')
+ migrate_property(
+ 'sale.configuration', field_names, cls, value_names,
+ fields=fields)
+
+ @classmethod
+ def default_sale_sequence(cls):
+ pool = Pool()
+ ModelData = pool.get('ir.model.data')
+ try:
+ return ModelData.get_id('sale', 'sequence_sale')
+ except KeyError:
+ return None
+
+
+class ConfigurationSaleMethod(ModelSQL, ValueMixin):
+ "Sale Configuration Sale Method"
+ __name__ = 'sale.configuration.sale_method'
+ sale_invoice_method = sale_invoice_method
+ get_sale_invoice_methods = get_sale_methods('invoice_method')
+ sale_shipment_method = sale_shipment_method
+ get_sale_shipment_methods = get_sale_methods('shipment_method')
+
+ @classmethod
+ def __register__(cls, module_name):
+ exist = backend.TableHandler.table_exist(cls._table)
+
+ super(ConfigurationSaleMethod, cls).__register__(module_name)
+
+ if not exist:
+ cls._migrate_property([], [], [])
+
+ @classmethod
+ def _migrate_property(cls, field_names, value_names, fields):
+ field_names.extend(['sale_invoice_method', 'sale_shipment_method'])
+ value_names.extend(['sale_invoice_method', 'sale_shipment_method'])
+ migrate_property(
+ 'sale.configuration', field_names, cls, value_names,
+ fields=fields)
+
+ @classmethod
+ def default_sale_invoice_method(cls):
+ return 'order'
+
+ @classmethod
+ def default_sale_shipment_method(cls):
+ return 'order'
diff --git a/modules/sale/configuration.xml b/modules/sale/configuration.xml
new file mode 100644
index 0000000000..152e7ede8b
--- /dev/null
+++ b/modules/sale/configuration.xml
@@ -0,0 +1,56 @@
+
+
+
+
+
+
+
+
+
+
+
+ sale.configuration
+ form
+ configuration_form
+
+
+ Configuration
+ sale.configuration
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/modules/sale/doc/conf.py b/modules/sale/doc/conf.py
new file mode 100644
index 0000000000..8513b72dd2
--- /dev/null
+++ b/modules/sale/doc/conf.py
@@ -0,0 +1,61 @@
+# This file is part of Tryton. The COPYRIGHT file at the top level of
+# this repository contains the full copyright notices and license terms.
+
+modules_url = 'https://docs.tryton.org/projects/modules-{module}/en/{series}/'
+trytond_url = 'https://docs.tryton.org/projects/server/en/{series}/'
+
+
+def get_info():
+ import configparser
+ import os
+ import subprocess
+ import sys
+
+ module_dir = os.path.dirname(os.path.dirname(__file__))
+
+ config = configparser.ConfigParser()
+ config.read_file(open(os.path.join(module_dir, 'tryton.cfg')))
+ info = dict(config.items('tryton'))
+
+ result = subprocess.run(
+ [sys.executable, 'setup.py', '--name'],
+ stdout=subprocess.PIPE, check=True, cwd=module_dir)
+ info['name'] = result.stdout.decode('utf-8').strip()
+
+ result = subprocess.run(
+ [sys.executable, 'setup.py', '--version'],
+ stdout=subprocess.PIPE, check=True, cwd=module_dir)
+ version = result.stdout.decode('utf-8').strip()
+ if 'dev' in version:
+ info['series'] = 'latest'
+ else:
+ info['series'] = '.'.join(version.split('.', 2)[:2])
+
+ for key in {'depends', 'extras_depend'}:
+ info[key] = info.get(key, '').strip().splitlines()
+ info['modules'] = set(info['depends'] + info['extras_depend'])
+ info['modules'] -= {'ir', 'res'}
+
+ return info
+
+
+info = get_info()
+
+master_doc = 'index'
+project = info['name']
+release = version = info['series']
+default_role = 'ref'
+highlight_language = 'none'
+extensions = [
+ 'sphinx.ext.intersphinx',
+ ]
+intersphinx_mapping = {
+ 'trytond': (trytond_url.format(series=version), None),
+ }
+intersphinx_mapping.update({
+ m: (modules_url.format(
+ module=m.replace('_', '-'), series=version), None)
+ for m in info['modules']
+ })
+
+del get_info, info, modules_url, trytond_url
diff --git a/modules/sale/doc/design.rst b/modules/sale/doc/design.rst
new file mode 100644
index 0000000000..998ba5d909
--- /dev/null
+++ b/modules/sale/doc/design.rst
@@ -0,0 +1,272 @@
+******
+Design
+******
+
+The *Sale Module* introduces the concepts that are required to manage sales.
+It also extends existing concepts so sales become an fully integrated part of
+the system.
+
+.. _model-sale.sale:
+
+Sale
+====
+
+The *Sale* concept is used to manage the selling process.
+Each sale, at any time, can be in one of several different states.
+A sale progress though these states until it is either done or gets cancelled.
+When some of these state changes happen the
+`Employee ` that triggered the state change
+is also recorded.
+
+Each sale contains details of the `Party ` that the
+sale is made to, including details such as the party's preferred
+`Contact Method `, and what
+`Addresses ` the shipments and invoices must be
+sent to.
+
+A sale is identified by a unique number that is generated automatically from
+the configured `Sequence `.
+It also has other general information like a sale date, description, and
+reference used by the customer.
+
+The sale is made up from one, or more, sales lines.
+These lines can be arranged into a particular order, if required.
+Normally most sales lines provide information about which
+`Products ` or items are included in the sale.
+Extra lines can be added for things like titles, comments or subtotals.
+
+The total, untaxed, and tax amounts for a sale are derived from the amounts,
+prices and `Taxes ` of the sale's lines.
+
+For sales of physical items, such as goods or assets, the
+`Warehouse ` the items are dispatched
+from is required.
+The sale's shipment method determines whether
+`Customer Shipments ` are automatically created
+for the sale, and when during the process this happens.
+If customer shipments do get created then the
+`Stock Moves ` on these shipments are linked to the
+sale lines and must be recreated or ignored if they get cancelled.
+
+`Invoices ` can be generated
+automatically at the correct time based on the invoice method.
+These invoices are created from data taken from the sale, and when invoicing
+based on shipment they also use the quantities from the shipments.
+The invoices are tracked by the sale, and if they are cancelled they must
+either be recreated or ignored.
+
+.. seealso::
+
+ Sales are found by opening the main menu item:
+
+ |Sales --> Sales|__
+
+ .. |Sales --> Sales| replace:: :menuselection:`Sales --> Sales`
+ __ https://demo.tryton.org/model/sale.sale
+
+Reports
+-------
+
+.. _report-sale.sale:
+
+Sale Report
+^^^^^^^^^^^
+
+The *Sale Report* is a document that can be printed out that contains all the
+relevant information about each sale, including the lines which have been
+sold.
+
+Wizards
+-------
+
+.. _wizard-sale.handle.shipment.exception:
+
+Handle Shipment Exception
+^^^^^^^^^^^^^^^^^^^^^^^^^
+
+The *Handle Shipment Exception* wizard helps the user ensure each sale
+has the correct `Stock Moves ` associated with it.
+For stock moves that have been cancelled, it lets the user decide which
+should be re-created, and which should be ignored.
+
+.. _wizard-sale.handle.invoice.exception:
+
+Handle Invoice Exception
+^^^^^^^^^^^^^^^^^^^^^^^^^
+
+The *Handle Invoice Exception* wizard helps the user make sure each sale
+only has the appropriate `Invoices `
+associated with it.
+If any of the sale's invoices get cancelled this wizard provides the user
+with the option to re-create or ignore the cancelled invoice.
+
+.. _wizard-sale.modify_header:
+
+Modify Header
+^^^^^^^^^^^^^
+
+Some fields on a draft sale become read-only when lines are added to it.
+The *Modify Header* wizard allows the values in these fields to be safely
+updated.
+
+.. _wizard-sale.return_sale:
+
+Return Sale
+^^^^^^^^^^^
+
+The *Return Sale* wizard is used when a customer returns all or part of a sale.
+It creates new draft sales that match any selected sales, but with all the
+quantities negated.
+
+.. _model-product.sale.context:
+
+Sale Context
+============
+
+The *Sale Context* allows the user to set a context in which a
+`Product's ` properties are then calculated.
+
+This is used when showing a list of salable products.
+It allows the user to select a customer and some other properties,
+and then get a list of products that are available along with their prices
+in the selected `Currency `.
+
+.. seealso::
+
+ The Sale Context is used to provide context in the main menu item:
+
+ |Sales --> Salable Products|__
+
+ .. |Sales --> Salable Products| replace:: :menuselection:`Sales --> Salable Products`
+ __ https://demo.tryton.org/model/product.product;context_model=product.sale.context
+
+.. _concept-sale.reporting:
+
+Sale Reporting
+==============
+
+Each of the different *Sale Reporting* concepts are based on either an
+``Abstract`` sales report, or an ``AbstractTimeseries``.
+There is also a base ``Context`` that is inherited and used to specify things
+such as the date range that is used by the report.
+
+The ``Abstract`` provides the basic properties that makes up a sales report
+including the number of sales and revenue.
+The ``AbstractTimeseries`` is used to extend this with a date.
+This is used in sales reports that cover multiple periods of time.
+These are combined together with additional specific properties to create the
+different sales reports.
+
+.. seealso::
+
+ Sales reports can be accessed from the main menu item:
+
+ :menuselection:`Sales --> Reporting --> Sales`
+
+.. _model-sale.reporting.customer:
+.. _model-sale.reporting.customer.time_series:
+
+By Customer
+-----------
+
+The sales reporting that is done *By Customer* splits the sales up based on
+what each `Customer ` bought.
+This is done in two separate parts.
+One that shows the sales, in total, for the selected period from the
+``Context``.
+Another that breaks them down by date into smaller chunks.
+
+.. _model-sale.reporting.product:
+.. _model-sale.reporting.product.time_series:
+
+By Product
+----------
+
+Sales reporting that is done *By Product* splits up the sales based on the
+`Product ` that was sold.
+This is structured as two parts.
+One that shows the total sales for the selected period of time, and another
+that shows how the sales were distributed over time.
+
+.. _model-sale.reporting.category.tree:
+.. _model-sale.reporting.category:
+.. _model-sale.reporting.category.time_series:
+
+By Category
+-----------
+
+The *By Category* sales reporting shows the sales based on the
+`Category ` that a product is in.
+This works in the same way as the `By Product `
+sales reporting, but there is also an additional report that shows the
+categories in their natural tree structure.
+
+.. _model-sale.reporting.region:
+
+By Region
+---------
+
+The sales reporting that is done *By Region* shows sales based on where the
+customer is located.
+This is done by combining together in a tree structure the sales
+`By Country ` below which are the sales
+`By Subdivision `.
+
+.. _model-sale.reporting.country:
+.. _model-sale.reporting.country.time_series:
+
+By Country
+^^^^^^^^^^
+
+The *By Country* concept groups sales based on the
+`Country ` in which the customer is located.
+This is done in two parts, one for total sales and one showing how the sales
+were distributed over time.
+
+.. _model-sale.reporting.country.subdivision:
+.. _model-sale.reporting.country.subdivision.time_series:
+
+By Subdivision
+^^^^^^^^^^^^^^
+
+The *By Subdivision* concept groups sales based on which
+`Subdivision ` of a country a customer is
+located.
+This is done in two parts, one for total sales and one showing how the sales
+were distributed over time.
+
+Wizards
+^^^^^^^
+
+.. _wizard-sale.reporting.region.open:
+
+Open Region
+"""""""""""
+
+The *Open Region* wizard ensures that the correct type of time series gets
+opened.
+This may be a time series for either a country, or subdivision, depending on
+what line from the `By Region ` was opened.
+
+.. _model-sale.configuration:
+
+Configuration
+=============
+
+The *Sale Configuration* concept is used for the settings that affect the
+general behaviour and default values for sales related activities.
+
+.. note::
+
+ Some of the sales configuration options have no effect unless the
+ :doc:`Task Queue` has been setup and some
+ workers are running.
+
+.. seealso::
+
+ Sales configuration settings are found by opening the main menu item:
+
+ |Sales --> Configuration --> Sales Configuration|__
+
+ .. |Sales --> Configuration --> Sales Configuration| replace:: :menuselection:`Sales --> Configuration --> Sales Configuration`
+ __ https://demo.tryton.org/model/sale.configuration/1
diff --git a/modules/sale/doc/index.rst b/modules/sale/doc/index.rst
new file mode 100644
index 0000000000..b1bf7c5fe5
--- /dev/null
+++ b/modules/sale/doc/index.rst
@@ -0,0 +1,15 @@
+###########
+Sale Module
+###########
+
+The *Sale Module* helps organise and manage sales made by the company.
+It adds the concept of a sale to Tryton and allows it to be tracked through
+its states from draft to done.
+It also oversees the creation of customer shipments and invoices for the sales,
+and allows reports to be generated that contain aggregated sales figures.
+
+.. toctree::
+ :maxdepth: 2
+
+ usage/index
+ design
diff --git a/modules/sale/doc/usage/index.rst b/modules/sale/doc/usage/index.rst
new file mode 100644
index 0000000000..7d98d727a3
--- /dev/null
+++ b/modules/sale/doc/usage/index.rst
@@ -0,0 +1,14 @@
+*****
+Usage
+*****
+
+Configuration, management, and reporting tasks relating to sales can be found
+under the [:menuselection:`Sales`] main menu item.
+
+.. toctree::
+ :maxdepth: 1
+
+ presales
+ process
+ returns
+ reporting
diff --git a/modules/sale/doc/usage/presales.rst b/modules/sale/doc/usage/presales.rst
new file mode 100644
index 0000000000..a759d0e3a2
--- /dev/null
+++ b/modules/sale/doc/usage/presales.rst
@@ -0,0 +1,52 @@
+.. _Listing customers:
+
+Listing customers
+=================
+
+In Tryton, by definition, the `Parties ` that
+have bought `Products ` from your
+`Company ` are its customers.
+The *Sale Module* lets you get a list of these from the
+[:menuselection:`Party --> Parties --> Parties associated to Sales`]
+main menu item.
+
+.. tip::
+
+ For some companies it is important to know which parties are, or may
+ eventually be, customers before they have bought anything.
+ One way you can do this is to create a ``Customer``
+ `Category `, and add all the appropriate
+ parties to it.
+
+.. _Making products salable:
+
+Making products salable
+=======================
+
+Before you can add a `Product ` to a
+`Sale ` it must be marked as salable.
+When you do this you will also be able to set some additional properties such
+as the `Unit of Measure ` the product is normally
+sold in and how long it normally takes before the product can be delivered.
+
+.. _Finding sale prices and availability:
+
+Finding sale prices and availability
+====================================
+
+Before making a `Sale ` it is sometimes useful to know how
+much of a `Product ` is available, and what the sale
+price will be.
+
+You can get a list of this information for the salable products by using the
+[:menuselection:`Sales --> Salable Products`] main menu item.
+The `Sale Context ` allows you to adjust the
+various parameters that can effect stock availability and price, such as which
+`Warehouse ` will be supplying the
+product, who the customer is and how much they want to buy.
+
+.. tip::
+
+ As with all Tryton data you can export this list to a
+ :abbr:`CSV (Comma Separated Value)` file by using the form's
+ :guilabel:`Export` menu item.
diff --git a/modules/sale/doc/usage/process.rst b/modules/sale/doc/usage/process.rst
new file mode 100644
index 0000000000..e9502f2105
--- /dev/null
+++ b/modules/sale/doc/usage/process.rst
@@ -0,0 +1,113 @@
+.. _Creating a sales order:
+
+Creating a sales order
+======================
+
+Creating a new sales order is simply a matter of creating a new
+`Sale ` and adding the lines that are required.
+Most of the fields are optional or have sensible default values.
+
+.. tip::
+
+ The sale's reference field is intended to be used to keep track of the
+ customers reference for the sale.
+ This can be filled in at any time even when the sale is done.
+
+.. _Changing a sales order:
+
+Changing a sales order
+======================
+
+The `Sale ` needs to be in a draft state in order to change
+the values in most of the fields.
+
+There are also few fields, such as the `Party ` and
+`Currency `, which become read-only when any
+lines are added to the order.
+In order to change these without needing to remove the sales lines you can use
+the :guilabel:`Modify Header` button to start the
+`Modify Header ` wizard.
+
+.. _Shipping a sale:
+
+Shipping a sale
+===============
+
+Any goods that were sold as part of the sale are
+`sent to the customer ` using a
+`Customer Shipment `.
+
+Depending on the shipment method chosen for the sale, the customer shipment
+may be created for you automatically.
+
+.. tip::
+
+ The customer shipments that have been generated from the sale can be found
+ using the sale's :guilabel:`Shipments` link.
+
+ The :guilabel:`Shipments` and stock :guilabel:`Moves` related to a sale
+ can also be found using the items in the sale's
+ :guilabel:`Open related records` menu.
+
+.. _Part shipments:
+
+Part shipments
+^^^^^^^^^^^^^^
+
+In some cases you may want to send a sale to a customer in stages.
+If you want to do this then you just need to make sure that the shipment's
+inventory moves are correct.
+Once the shipment is packed, or the sale is processed again, the sale will
+automatically create a new shipment that contains any remaining quantities.
+This new customer shipment, often referred to as a back-order, can then be
+shipped at a later date, split up further, or cancelled.
+
+.. _Invoicing a sale:
+
+Invoicing a sale
+================
+
+The `Sale's ` invoice method determines whether the sale will
+automatically generate `Invoices `.
+
+.. tip::
+
+ The invoices that have been generated from the sale can be found using the
+ sale's :guilabel:`Invoices` link or the :guilabel:`Invoices` item found in
+ the sale's :guilabel:`Open related records` menu.
+
+.. _Handling shipment and invoice exceptions:
+
+Handling shipment and invoice exceptions
+========================================
+
+Sometimes you may have cancelled items from a `Sale's `
+`Shipment `, or cancelled a sale's
+`Invoice `, and need to recreate
+them.
+Other times you may have cancelled things because you no longer want to ship,
+or invoice, them.
+As Tryton does not know if a cancelled item needs to be recreated, or not,
+it shows this as an exception in the sale's shipment or invoice state.
+
+For sales that have a shipment or invoice exception you can use the
+`Handle Shipment Exception ` or
+`Handle Invoice Exception ` wizards
+to recreate the items that need recreating, and ignore the rest.
+
+.. tip::
+
+ When using the wizard the moves and invoices to recreate will, by default,
+ already be selected.
+ This means you will need to deselect any that you do not want to recreate.
+
+.. _Finishing a sale:
+
+Finishing a sale
+================
+
+In Tryton once a `Sale ` is being processed there is no
+button that moves the sale into a done state.
+This will happen automatically once the sale's
+`Shipments ` and
+`Invoices ` are completed.
diff --git a/modules/sale/doc/usage/reporting.rst b/modules/sale/doc/usage/reporting.rst
new file mode 100644
index 0000000000..7b5d1dfff9
--- /dev/null
+++ b/modules/sale/doc/usage/reporting.rst
@@ -0,0 +1,20 @@
+.. _Getting sales data:
+
+Getting sales data
+==================
+
+You can analyse aggregated sales data using the items found under the
+[:menuselection:`Sales --> Reporting`] main menu item.
+These `Sales Reports ` allow you to view sales
+grouped by a range of different factors.
+
+.. note::
+
+ The value of the sales in these reports are always shown in the
+ `Company's `
+ `Currency `.
+
+ To ensure the values that are shown are correct you must ensure that you
+ have correctly `set the currency exchange rates
+ ` for any currencies that you
+ use, including for the company's currency.
diff --git a/modules/sale/doc/usage/returns.rst b/modules/sale/doc/usage/returns.rst
new file mode 100644
index 0000000000..7ebb8631dd
--- /dev/null
+++ b/modules/sale/doc/usage/returns.rst
@@ -0,0 +1,42 @@
+.. _Cancelling sales:
+
+Cancelling sales
+================
+
+You can easily cancel `Sales ` that are not yet confirmed
+using the :guilabel:`Cancel` button.
+
+Confirmed sales cannot be cancelled, but you can put them back to a state
+where they can be cancelled.
+However, as soon as a confirmed sale starts to be processed it can no longer
+be cancelled.
+This may happen immediately when it is confirmed, or after a delay if one has
+been correctly `Configured `.
+
+Once a sale has started to be processed, to effectively cancel the sale,
+you must cancel its `Customer Shipments ` and
+`Invoices `.
+Once you have done this you must
+`handle the exceptions ` this
+generates, ensuring that none of the moves or invoices are selected for
+recreation.
+
+.. _Handling customer returns:
+
+Handling customer returns
+=========================
+
+Sometimes a customer may decide to return a `Sale `, or part
+of a sale, to you.
+In Tryton this is represented by a sale that has negative quantities.
+
+One way of creating a customer return is to use the
+`Return Sale ` wizard.
+This creates a new draft sales return for the whole of the selected sale.
+
+If the customer has only returned part of the sale, then the sales return can
+be altered as required.
+When it gets processed it will automatically create
+`Credit Notes ` and
+`Customer Return Shipments ` where
+required.
diff --git a/modules/sale/exceptions.py b/modules/sale/exceptions.py
new file mode 100644
index 0000000000..ba30d19264
--- /dev/null
+++ b/modules/sale/exceptions.py
@@ -0,0 +1,21 @@
+# This file is part of Tryton. The COPYRIGHT file at the top level of
+# this repository contains the full copyright notices and license terms.
+
+from trytond.exceptions import UserError
+from trytond.model.exceptions import ValidationError
+
+
+class SaleValidationError(ValidationError):
+ pass
+
+
+class SaleQuotationError(ValidationError):
+ pass
+
+
+class SaleConfirmError(UserError):
+ pass
+
+
+class PartyLocationError(UserError):
+ pass
diff --git a/modules/sale/icons/LICENSE b/modules/sale/icons/LICENSE
new file mode 100644
index 0000000000..7a4a3ea242
--- /dev/null
+++ b/modules/sale/icons/LICENSE
@@ -0,0 +1,202 @@
+
+ Apache License
+ Version 2.0, January 2004
+ http://www.apache.org/licenses/
+
+ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+ 1. Definitions.
+
+ "License" shall mean the terms and conditions for use, reproduction,
+ and distribution as defined by Sections 1 through 9 of this document.
+
+ "Licensor" shall mean the copyright owner or entity authorized by
+ the copyright owner that is granting the License.
+
+ "Legal Entity" shall mean the union of the acting entity and all
+ other entities that control, are controlled by, or are under common
+ control with that entity. For the purposes of this definition,
+ "control" means (i) the power, direct or indirect, to cause the
+ direction or management of such entity, whether by contract or
+ otherwise, or (ii) ownership of fifty percent (50%) or more of the
+ outstanding shares, or (iii) beneficial ownership of such entity.
+
+ "You" (or "Your") shall mean an individual or Legal Entity
+ exercising permissions granted by this License.
+
+ "Source" form shall mean the preferred form for making modifications,
+ including but not limited to software source code, documentation
+ source, and configuration files.
+
+ "Object" form shall mean any form resulting from mechanical
+ transformation or translation of a Source form, including but
+ not limited to compiled object code, generated documentation,
+ and conversions to other media types.
+
+ "Work" shall mean the work of authorship, whether in Source or
+ Object form, made available under the License, as indicated by a
+ copyright notice that is included in or attached to the work
+ (an example is provided in the Appendix below).
+
+ "Derivative Works" shall mean any work, whether in Source or Object
+ form, that is based on (or derived from) the Work and for which the
+ editorial revisions, annotations, elaborations, or other modifications
+ represent, as a whole, an original work of authorship. For the purposes
+ of this License, Derivative Works shall not include works that remain
+ separable from, or merely link (or bind by name) to the interfaces of,
+ the Work and Derivative Works thereof.
+
+ "Contribution" shall mean any work of authorship, including
+ the original version of the Work and any modifications or additions
+ to that Work or Derivative Works thereof, that is intentionally
+ submitted to Licensor for inclusion in the Work by the copyright owner
+ or by an individual or Legal Entity authorized to submit on behalf of
+ the copyright owner. For the purposes of this definition, "submitted"
+ means any form of electronic, verbal, or written communication sent
+ to the Licensor or its representatives, including but not limited to
+ communication on electronic mailing lists, source code control systems,
+ and issue tracking systems that are managed by, or on behalf of, the
+ Licensor for the purpose of discussing and improving the Work, but
+ excluding communication that is conspicuously marked or otherwise
+ designated in writing by the copyright owner as "Not a Contribution."
+
+ "Contributor" shall mean Licensor and any individual or Legal Entity
+ on behalf of whom a Contribution has been received by Licensor and
+ subsequently incorporated within the Work.
+
+ 2. Grant of Copyright License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ copyright license to reproduce, prepare Derivative Works of,
+ publicly display, publicly perform, sublicense, and distribute the
+ Work and such Derivative Works in Source or Object form.
+
+ 3. Grant of Patent License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ (except as stated in this section) patent license to make, have made,
+ use, offer to sell, sell, import, and otherwise transfer the Work,
+ where such license applies only to those patent claims licensable
+ by such Contributor that are necessarily infringed by their
+ Contribution(s) alone or by combination of their Contribution(s)
+ with the Work to which such Contribution(s) was submitted. If You
+ institute patent litigation against any entity (including a
+ cross-claim or counterclaim in a lawsuit) alleging that the Work
+ or a Contribution incorporated within the Work constitutes direct
+ or contributory patent infringement, then any patent licenses
+ granted to You under this License for that Work shall terminate
+ as of the date such litigation is filed.
+
+ 4. Redistribution. You may reproduce and distribute copies of the
+ Work or Derivative Works thereof in any medium, with or without
+ modifications, and in Source or Object form, provided that You
+ meet the following conditions:
+
+ (a) You must give any other recipients of the Work or
+ Derivative Works a copy of this License; and
+
+ (b) You must cause any modified files to carry prominent notices
+ stating that You changed the files; and
+
+ (c) You must retain, in the Source form of any Derivative Works
+ that You distribute, all copyright, patent, trademark, and
+ attribution notices from the Source form of the Work,
+ excluding those notices that do not pertain to any part of
+ the Derivative Works; and
+
+ (d) If the Work includes a "NOTICE" text file as part of its
+ distribution, then any Derivative Works that You distribute must
+ include a readable copy of the attribution notices contained
+ within such NOTICE file, excluding those notices that do not
+ pertain to any part of the Derivative Works, in at least one
+ of the following places: within a NOTICE text file distributed
+ as part of the Derivative Works; within the Source form or
+ documentation, if provided along with the Derivative Works; or,
+ within a display generated by the Derivative Works, if and
+ wherever such third-party notices normally appear. The contents
+ of the NOTICE file are for informational purposes only and
+ do not modify the License. You may add Your own attribution
+ notices within Derivative Works that You distribute, alongside
+ or as an addendum to the NOTICE text from the Work, provided
+ that such additional attribution notices cannot be construed
+ as modifying the License.
+
+ You may add Your own copyright statement to Your modifications and
+ may provide additional or different license terms and conditions
+ for use, reproduction, or distribution of Your modifications, or
+ for any such Derivative Works as a whole, provided Your use,
+ reproduction, and distribution of the Work otherwise complies with
+ the conditions stated in this License.
+
+ 5. Submission of Contributions. Unless You explicitly state otherwise,
+ any Contribution intentionally submitted for inclusion in the Work
+ by You to the Licensor shall be under the terms and conditions of
+ this License, without any additional terms or conditions.
+ Notwithstanding the above, nothing herein shall supersede or modify
+ the terms of any separate license agreement you may have executed
+ with Licensor regarding such Contributions.
+
+ 6. Trademarks. This License does not grant permission to use the trade
+ names, trademarks, service marks, or product names of the Licensor,
+ except as required for reasonable and customary use in describing the
+ origin of the Work and reproducing the content of the NOTICE file.
+
+ 7. Disclaimer of Warranty. Unless required by applicable law or
+ agreed to in writing, Licensor provides the Work (and each
+ Contributor provides its Contributions) on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ implied, including, without limitation, any warranties or conditions
+ of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+ PARTICULAR PURPOSE. You are solely responsible for determining the
+ appropriateness of using or redistributing the Work and assume any
+ risks associated with Your exercise of permissions under this License.
+
+ 8. Limitation of Liability. In no event and under no legal theory,
+ whether in tort (including negligence), contract, or otherwise,
+ unless required by applicable law (such as deliberate and grossly
+ negligent acts) or agreed to in writing, shall any Contributor be
+ liable to You for damages, including any direct, indirect, special,
+ incidental, or consequential damages of any character arising as a
+ result of this License or out of the use or inability to use the
+ Work (including but not limited to damages for loss of goodwill,
+ work stoppage, computer failure or malfunction, or any and all
+ other commercial damages or losses), even if such Contributor
+ has been advised of the possibility of such damages.
+
+ 9. Accepting Warranty or Additional Liability. While redistributing
+ the Work or Derivative Works thereof, You may choose to offer,
+ and charge a fee for, acceptance of support, warranty, indemnity,
+ or other liability obligations and/or rights consistent with this
+ License. However, in accepting such obligations, You may act only
+ on Your own behalf and on Your sole responsibility, not on behalf
+ of any other Contributor, and only if You agree to indemnify,
+ defend, and hold each Contributor harmless for any liability
+ incurred by, or claims asserted against, such Contributor by reason
+ of your accepting any such warranty or additional liability.
+
+ END OF TERMS AND CONDITIONS
+
+ APPENDIX: How to apply the Apache License to your work.
+
+ To apply the Apache License to your work, attach the following
+ boilerplate notice, with the fields enclosed by brackets "[]"
+ replaced with your own identifying information. (Don't include
+ the brackets!) The text should be enclosed in the appropriate
+ comment syntax for the file format. We also recommend that a
+ file or class name and description of purpose be included on the
+ same "printed page" as the copyright notice for easier
+ identification within third-party archives.
+
+ Copyright [yyyy] [name of copyright owner]
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
\ No newline at end of file
diff --git a/modules/sale/icons/tryton-sale.svg b/modules/sale/icons/tryton-sale.svg
new file mode 100644
index 0000000000..cecd62e71b
--- /dev/null
+++ b/modules/sale/icons/tryton-sale.svg
@@ -0,0 +1,4 @@
+
diff --git a/modules/sale/invoice.py b/modules/sale/invoice.py
new file mode 100644
index 0000000000..5bf42f18a0
--- /dev/null
+++ b/modules/sale/invoice.py
@@ -0,0 +1,144 @@
+# This file is part of Tryton. The COPYRIGHT file at the top level of
+# this repository contains the full copyright notices and license terms.
+from functools import wraps
+
+from trytond.i18n import gettext
+from trytond.model import Workflow, fields
+from trytond.model.exceptions import AccessError
+from trytond.pool import Pool, PoolMeta
+from trytond.transaction import Transaction
+
+
+def process_sale(func):
+ @wraps(func)
+ def wrapper(cls, invoices):
+ pool = Pool()
+ Sale = pool.get('sale.sale')
+ with Transaction().set_context(_check_access=False):
+ sales = set(s for i in cls.browse(invoices) for s in i.sales)
+ func(cls, invoices)
+ if sales:
+ Sale.__queue__.process(sales)
+ return wrapper
+
+
+class Invoice(metaclass=PoolMeta):
+ __name__ = 'account.invoice'
+ sale_exception_state = fields.Function(fields.Selection([
+ ('', ''),
+ ('ignored', 'Ignored'),
+ ('recreated', 'Recreated'),
+ ], 'Exception State'), 'get_sale_exception_state')
+ sales = fields.Function(fields.Many2Many(
+ 'sale.sale', None, None, "Sales"),
+ 'get_sales', searcher='search_sales')
+
+ def get_sale_exception_state(self, name):
+ sales = self.sales
+
+ recreated = tuple(i for p in sales for i in p.invoices_recreated)
+ ignored = tuple(i for p in sales for i in p.invoices_ignored)
+
+ if self in recreated:
+ return 'recreated'
+ elif self in ignored:
+ return 'ignored'
+ return ''
+
+ def get_sales(self, name):
+ pool = Pool()
+ SaleLine = pool.get('sale.line')
+ sales = set()
+ for line in self.lines:
+ if isinstance(line.origin, SaleLine):
+ sales.add(line.origin.sale.id)
+ return list(sales)
+
+ @classmethod
+ def search_sales(cls, name, clause):
+ return [('lines.origin.sale' + clause[0].lstrip(name),)
+ + tuple(clause[1:3]) + ('sale.line',) + tuple(clause[3:])]
+
+ @classmethod
+ def copy(cls, invoices, default=None):
+ if default is None:
+ default = {}
+ else:
+ default = default.copy()
+ default.setdefault('sales', None)
+ return super(Invoice, cls).copy(invoices, default=default)
+
+ @classmethod
+ @process_sale
+ def delete(cls, invoices):
+ super(Invoice, cls).delete(invoices)
+
+ @classmethod
+ @process_sale
+ def _post(cls, invoices):
+ super()._post(invoices)
+
+ @classmethod
+ @process_sale
+ def paid(cls, invoices):
+ super(Invoice, cls).paid(invoices)
+
+ @classmethod
+ @process_sale
+ def cancel(cls, invoices):
+ super(Invoice, cls).cancel(invoices)
+
+ @classmethod
+ @Workflow.transition('draft')
+ def draft(cls, invoices):
+ for invoice in invoices:
+ if invoice.sales and invoice.state == 'cancelled':
+ raise AccessError(
+ gettext('sale.msg_sale_invoice_reset_draft',
+ invoice=invoice.rec_name))
+
+ return super(Invoice, cls).draft(invoices)
+
+
+class Line(metaclass=PoolMeta):
+ __name__ = 'account.invoice.line'
+
+ @fields.depends('origin')
+ def on_change_with_product_uom_category(self, name=None):
+ pool = Pool()
+ SaleLine = pool.get('sale.line')
+ category = super().on_change_with_product_uom_category(name=name)
+ # Enforce the same unit category as they are used to compute the
+ # remaining quantity to invoice and the quantity to ship.
+ # Use getattr as reference field can have negative id
+ if (isinstance(self.origin, SaleLine)
+ and getattr(self.origin, 'unit', None)):
+ category = self.origin.unit.category.id
+ return category
+
+ @property
+ def origin_name(self):
+ pool = Pool()
+ SaleLine = pool.get('sale.line')
+ name = super().origin_name
+ if isinstance(self.origin, SaleLine):
+ name = self.origin.sale.rec_name
+ return name
+
+ @classmethod
+ def _get_origin(cls):
+ models = super()._get_origin()
+ models.append('sale.line')
+ return models
+
+ @classmethod
+ def delete(cls, lines):
+ pool = Pool()
+ Sale = pool.get('sale.sale')
+ with Transaction().set_context(_check_access=False):
+ invoices = (l.invoice for l in cls.browse(lines)
+ if l.type == 'line' and l.invoice)
+ sales = set(s for i in invoices for s in i.sales)
+ super().delete(lines)
+ if sales:
+ Sale.__queue__.process(sales)
diff --git a/modules/sale/locale/bg.po b/modules/sale/locale/bg.po
new file mode 100644
index 0000000000..62c0fd3c9f
--- /dev/null
+++ b/modules/sale/locale/bg.po
@@ -0,0 +1,1422 @@
+#
+msgid ""
+msgstr "Content-Type: text/plain; charset=utf-8\n"
+
+msgctxt "field:account.invoice,sale_exception_state:"
+msgid "Exception State"
+msgstr "Състояние на грешка"
+
+msgctxt "field:account.invoice,sales:"
+msgid "Sales"
+msgstr "Продажби"
+
+msgctxt "field:product.configuration,default_lead_time:"
+msgid "Default Lead Time"
+msgstr ""
+
+#, fuzzy
+msgctxt "field:product.configuration.default_lead_time,company:"
+msgid "Company"
+msgstr "Фирма"
+
+msgctxt "field:product.configuration.default_lead_time,default_lead_time:"
+msgid "Default Lead Time"
+msgstr ""
+
+msgctxt "field:product.product,lead_time:"
+msgid "Lead Time"
+msgstr ""
+
+#, fuzzy
+msgctxt "field:product.product,salable:"
+msgid "Salable"
+msgstr "Продажен"
+
+msgctxt "field:product.product,sale_price_uom:"
+msgid "Sale Price"
+msgstr ""
+
+#, fuzzy
+msgctxt "field:product.product,sale_uom:"
+msgid "Sale UOM"
+msgstr "Мер. ед. на продажба"
+
+#, fuzzy
+msgctxt "field:product.sale.context,company:"
+msgid "Company"
+msgstr "Фирма"
+
+#, fuzzy
+msgctxt "field:product.sale.context,currency:"
+msgid "Currency"
+msgstr "Валута"
+
+#, fuzzy
+msgctxt "field:product.sale.context,customer:"
+msgid "Customer"
+msgstr "Клиенти"
+
+#, fuzzy
+msgctxt "field:product.sale.context,locations:"
+msgid "Warehouses"
+msgstr "Склад"
+
+#, fuzzy
+msgctxt "field:product.sale.context,quantity:"
+msgid "Quantity"
+msgstr "Количество"
+
+#, fuzzy
+msgctxt "field:product.sale.context,sale_date:"
+msgid "Sale Date"
+msgstr "Дата на продажба"
+
+msgctxt "field:product.sale.context,stock_date_end:"
+msgid "Stock End Date"
+msgstr ""
+
+msgctxt "field:product.template,lead_time:"
+msgid "Lead Time"
+msgstr ""
+
+msgctxt "field:product.template,salable:"
+msgid "Salable"
+msgstr "Продажен"
+
+msgctxt "field:product.template,sale_uom:"
+msgid "Sale UOM"
+msgstr "Мер. ед. на продажба"
+
+msgctxt "field:sale.configuration,sale_invoice_method:"
+msgid "Sale Invoice Method"
+msgstr "Начин на фактурине на продажба"
+
+msgctxt "field:sale.configuration,sale_process_after:"
+msgid "Process Sale after"
+msgstr ""
+
+msgctxt "field:sale.configuration,sale_sequence:"
+msgid "Sale Sequence"
+msgstr ""
+
+msgctxt "field:sale.configuration,sale_shipment_method:"
+msgid "Sale Shipment Method"
+msgstr "Начин на фактуриране на продажба"
+
+#, fuzzy
+msgctxt "field:sale.configuration.sale_method,sale_invoice_method:"
+msgid "Sale Invoice Method"
+msgstr "Начин на фактурине на продажба"
+
+#, fuzzy
+msgctxt "field:sale.configuration.sale_method,sale_shipment_method:"
+msgid "Sale Shipment Method"
+msgstr "Начин на фактуриране на продажба"
+
+#, fuzzy
+msgctxt "field:sale.configuration.sequence,company:"
+msgid "Company"
+msgstr "Фирма"
+
+msgctxt "field:sale.configuration.sequence,sale_sequence:"
+msgid "Sale Sequence"
+msgstr ""
+
+msgctxt "field:sale.handle.invoice.exception.ask,domain_invoices:"
+msgid "Domain Invoices"
+msgstr "Фактури на домейн"
+
+msgctxt "field:sale.handle.invoice.exception.ask,recreate_invoices:"
+msgid "Recreate Invoices"
+msgstr "Наново създаване на фактури"
+
+msgctxt "field:sale.handle.shipment.exception.ask,domain_moves:"
+msgid "Domain Moves"
+msgstr "Движение на домейн"
+
+msgctxt "field:sale.handle.shipment.exception.ask,recreate_moves:"
+msgid "Recreate Moves"
+msgstr "Наново създаване на движения"
+
+#, fuzzy
+msgctxt "field:sale.line,actual_quantity:"
+msgid "Actual Quantity"
+msgstr "Количество"
+
+msgctxt "field:sale.line,amount:"
+msgid "Amount"
+msgstr "Сума"
+
+#, fuzzy
+msgctxt "field:sale.line,company:"
+msgid "Company"
+msgstr "Фирма"
+
+#, fuzzy
+msgctxt "field:sale.line,currency:"
+msgid "Currency"
+msgstr "Валута"
+
+msgctxt "field:sale.line,description:"
+msgid "Description"
+msgstr "Описание"
+
+msgctxt "field:sale.line,from_location:"
+msgid "From Location"
+msgstr "От местонахождение"
+
+msgctxt "field:sale.line,invoice_lines:"
+msgid "Invoice Lines"
+msgstr "Редове от фактура"
+
+msgctxt "field:sale.line,move_done:"
+msgid "Moves Done"
+msgstr "Направени движения"
+
+msgctxt "field:sale.line,move_exception:"
+msgid "Moves Exception"
+msgstr "Грешка при движение"
+
+msgctxt "field:sale.line,moves:"
+msgid "Moves"
+msgstr "Движения"
+
+msgctxt "field:sale.line,moves_ignored:"
+msgid "Ignored Moves"
+msgstr "Игнорирани движения"
+
+msgctxt "field:sale.line,moves_recreated:"
+msgid "Recreated Moves"
+msgstr "Наново създаване на движения"
+
+msgctxt "field:sale.line,note:"
+msgid "Note"
+msgstr "Бележка"
+
+msgctxt "field:sale.line,product:"
+msgid "Product"
+msgstr "Продукт"
+
+msgctxt "field:sale.line,product_uom_category:"
+msgid "Product Uom Category"
+msgstr "Категория мер. ед. на продукт"
+
+msgctxt "field:sale.line,quantity:"
+msgid "Quantity"
+msgstr "Количество"
+
+msgctxt "field:sale.line,sale:"
+msgid "Sale"
+msgstr "Продажба"
+
+#, fuzzy
+msgctxt "field:sale.line,sale_state:"
+msgid "Sale State"
+msgstr "Дата на продажба"
+
+msgctxt "field:sale.line,shipping_date:"
+msgid "Shipping Date"
+msgstr ""
+
+msgctxt "field:sale.line,summary:"
+msgid "Summary"
+msgstr ""
+
+msgctxt "field:sale.line,taxes:"
+msgid "Taxes"
+msgstr "Данъци"
+
+msgctxt "field:sale.line,to_location:"
+msgid "To Location"
+msgstr "Към местонахождение"
+
+msgctxt "field:sale.line,type:"
+msgid "Type"
+msgstr "Вид"
+
+msgctxt "field:sale.line,unit:"
+msgid "Unit"
+msgstr "Единица"
+
+msgctxt "field:sale.line,unit_digits:"
+msgid "Unit Digits"
+msgstr "Десетични единици"
+
+msgctxt "field:sale.line,unit_price:"
+msgid "Unit Price"
+msgstr "Единична цена"
+
+msgctxt "field:sale.line,warehouse:"
+msgid "Warehouse"
+msgstr "Склад"
+
+msgctxt "field:sale.line-account.tax,line:"
+msgid "Sale Line"
+msgstr "Ред от продажба"
+
+msgctxt "field:sale.line-account.tax,tax:"
+msgid "Tax"
+msgstr "Данък"
+
+msgctxt "field:sale.line-ignored-stock.move,move:"
+msgid "Move"
+msgstr "Движение"
+
+msgctxt "field:sale.line-ignored-stock.move,sale_line:"
+msgid "Sale Line"
+msgstr "Ред от продажба"
+
+msgctxt "field:sale.line-recreated-stock.move,move:"
+msgid "Move"
+msgstr "Движение"
+
+msgctxt "field:sale.line-recreated-stock.move,sale_line:"
+msgid "Sale Line"
+msgstr "Ред от продажба"
+
+msgctxt "field:sale.reporting.category,category:"
+msgid "Category"
+msgstr ""
+
+msgctxt "field:sale.reporting.category,time_series:"
+msgid "Time Series"
+msgstr ""
+
+msgctxt "field:sale.reporting.category.time_series,category:"
+msgid "Category"
+msgstr ""
+
+#, fuzzy
+msgctxt "field:sale.reporting.category.time_series,date:"
+msgid "Date"
+msgstr "Дата:"
+
+msgctxt "field:sale.reporting.category.tree,children:"
+msgid "Children"
+msgstr ""
+
+#, fuzzy
+msgctxt "field:sale.reporting.category.tree,currency_digits:"
+msgid "Currency Digits"
+msgstr "Цифри за валута"
+
+#, fuzzy
+msgctxt "field:sale.reporting.category.tree,name:"
+msgid "Name"
+msgstr "Име"
+
+msgctxt "field:sale.reporting.category.tree,parent:"
+msgid "Parent"
+msgstr ""
+
+msgctxt "field:sale.reporting.category.tree,revenue:"
+msgid "Revenue"
+msgstr ""
+
+#, fuzzy
+msgctxt "field:sale.reporting.context,company:"
+msgid "Company"
+msgstr "Фирма"
+
+msgctxt "field:sale.reporting.context,from_date:"
+msgid "From Date"
+msgstr ""
+
+msgctxt "field:sale.reporting.context,period:"
+msgid "Period"
+msgstr ""
+
+msgctxt "field:sale.reporting.context,to_date:"
+msgid "To Date"
+msgstr ""
+
+#, fuzzy
+msgctxt "field:sale.reporting.context,warehouse:"
+msgid "Warehouse"
+msgstr "Склад"
+
+msgctxt "field:sale.reporting.country,country:"
+msgid "Country"
+msgstr ""
+
+msgctxt "field:sale.reporting.country,time_series:"
+msgid "Time Series"
+msgstr ""
+
+msgctxt "field:sale.reporting.country.subdivision,country:"
+msgid "Country"
+msgstr ""
+
+msgctxt "field:sale.reporting.country.subdivision,subdivision:"
+msgid "Subdivision"
+msgstr ""
+
+msgctxt "field:sale.reporting.country.subdivision,time_series:"
+msgid "Time Series"
+msgstr ""
+
+msgctxt "field:sale.reporting.country.subdivision.time_series,country:"
+msgid "Country"
+msgstr ""
+
+#, fuzzy
+msgctxt "field:sale.reporting.country.subdivision.time_series,date:"
+msgid "Date"
+msgstr "Дата:"
+
+msgctxt "field:sale.reporting.country.subdivision.time_series,subdivision:"
+msgid "Subdivision"
+msgstr ""
+
+msgctxt "field:sale.reporting.country.time_series,country:"
+msgid "Country"
+msgstr ""
+
+#, fuzzy
+msgctxt "field:sale.reporting.country.time_series,date:"
+msgid "Date"
+msgstr "Дата:"
+
+#, fuzzy
+msgctxt "field:sale.reporting.customer,customer:"
+msgid "Customer"
+msgstr "Клиенти"
+
+msgctxt "field:sale.reporting.customer,time_series:"
+msgid "Time Series"
+msgstr ""
+
+#, fuzzy
+msgctxt "field:sale.reporting.customer.time_series,customer:"
+msgid "Customer"
+msgstr "Клиенти"
+
+#, fuzzy
+msgctxt "field:sale.reporting.customer.time_series,date:"
+msgid "Date"
+msgstr "Дата:"
+
+#, fuzzy
+msgctxt "field:sale.reporting.product,product:"
+msgid "Product"
+msgstr "Продукт"
+
+msgctxt "field:sale.reporting.product,time_series:"
+msgid "Time Series"
+msgstr ""
+
+#, fuzzy
+msgctxt "field:sale.reporting.product.time_series,date:"
+msgid "Date"
+msgstr "Дата:"
+
+#, fuzzy
+msgctxt "field:sale.reporting.product.time_series,product:"
+msgid "Product"
+msgstr "Продукт"
+
+msgctxt "field:sale.reporting.region,children:"
+msgid "Children"
+msgstr ""
+
+msgctxt "field:sale.reporting.region,parent:"
+msgid "Parent"
+msgstr ""
+
+msgctxt "field:sale.reporting.region,region:"
+msgid "Region"
+msgstr ""
+
+msgctxt "field:sale.sale,comment:"
+msgid "Comment"
+msgstr "Коментар"
+
+msgctxt "field:sale.sale,company:"
+msgid "Company"
+msgstr "Фирма"
+
+#, fuzzy
+msgctxt "field:sale.sale,confirmed_by:"
+msgid "Confirmed By"
+msgstr "Потвърден"
+
+msgctxt "field:sale.sale,contact:"
+msgid "Contact"
+msgstr ""
+
+msgctxt "field:sale.sale,currency:"
+msgid "Currency"
+msgstr "Валута"
+
+msgctxt "field:sale.sale,currency_digits:"
+msgid "Currency Digits"
+msgstr "Цифри за валута"
+
+msgctxt "field:sale.sale,description:"
+msgid "Description"
+msgstr "Описание"
+
+msgctxt "field:sale.sale,invoice_address:"
+msgid "Invoice Address"
+msgstr "Адрес за фактура"
+
+msgctxt "field:sale.sale,invoice_method:"
+msgid "Invoice Method"
+msgstr "Начин на фактуриране"
+
+#, fuzzy
+msgctxt "field:sale.sale,invoice_party:"
+msgid "Invoice Party"
+msgstr "Състояние на фактура"
+
+msgctxt "field:sale.sale,invoice_state:"
+msgid "Invoice State"
+msgstr "Състояние на фактура"
+
+msgctxt "field:sale.sale,invoices:"
+msgid "Invoices"
+msgstr "Фактури"
+
+msgctxt "field:sale.sale,invoices_ignored:"
+msgid "Ignored Invoices"
+msgstr "Игнорирани фактури"
+
+msgctxt "field:sale.sale,invoices_recreated:"
+msgid "Recreated Invoices"
+msgstr "Наново създадени на фактури"
+
+msgctxt "field:sale.sale,lines:"
+msgid "Lines"
+msgstr "Редове"
+
+msgctxt "field:sale.sale,moves:"
+msgid "Moves"
+msgstr "Движения"
+
+#, fuzzy
+msgctxt "field:sale.sale,number:"
+msgid "Number"
+msgstr "Номер"
+
+#, fuzzy
+msgctxt "field:sale.sale,origin:"
+msgid "Origin"
+msgstr "Източник"
+
+msgctxt "field:sale.sale,party:"
+msgid "Party"
+msgstr "Партньор"
+
+msgctxt "field:sale.sale,party_lang:"
+msgid "Party Language"
+msgstr "Език на партньор"
+
+msgctxt "field:sale.sale,payment_term:"
+msgid "Payment Term"
+msgstr "Условие за плащане"
+
+#, fuzzy
+msgctxt "field:sale.sale,quoted_by:"
+msgid "Quoted By"
+msgstr "Quote"
+
+msgctxt "field:sale.sale,reference:"
+msgid "Reference"
+msgstr "Отпратка"
+
+msgctxt "field:sale.sale,sale_date:"
+msgid "Sale Date"
+msgstr "Дата на продажба"
+
+msgctxt "field:sale.sale,shipment_address:"
+msgid "Shipment Address"
+msgstr "Адрес за доставка"
+
+msgctxt "field:sale.sale,shipment_method:"
+msgid "Shipment Method"
+msgstr "Начин на изпращане"
+
+msgctxt "field:sale.sale,shipment_party:"
+msgid "Shipment Party"
+msgstr ""
+
+msgctxt "field:sale.sale,shipment_returns:"
+msgid "Shipment Returns"
+msgstr "Върнати доставки"
+
+msgctxt "field:sale.sale,shipment_state:"
+msgid "Shipment State"
+msgstr "Състояние на пратка"
+
+msgctxt "field:sale.sale,shipments:"
+msgid "Shipments"
+msgstr "Изпращания"
+
+#, fuzzy
+msgctxt "field:sale.sale,shipping_date:"
+msgid "Shipping Date"
+msgstr "Състояние на пратка"
+
+msgctxt "field:sale.sale,state:"
+msgid "State"
+msgstr "Състояние"
+
+msgctxt "field:sale.sale,tax_amount:"
+msgid "Tax"
+msgstr "Данък"
+
+msgctxt "field:sale.sale,tax_amount_cache:"
+msgid "Tax Cache"
+msgstr "Данък в брой"
+
+msgctxt "field:sale.sale,total_amount:"
+msgid "Total"
+msgstr "Общо"
+
+#, fuzzy
+msgctxt "field:sale.sale,total_amount_cache:"
+msgid "Total Cache"
+msgstr "Данък в брой"
+
+msgctxt "field:sale.sale,untaxed_amount:"
+msgid "Untaxed"
+msgstr "Необложен с данък"
+
+msgctxt "field:sale.sale,untaxed_amount_cache:"
+msgid "Untaxed Cache"
+msgstr "Наличност преди данъци"
+
+msgctxt "field:sale.sale,warehouse:"
+msgid "Warehouse"
+msgstr "Склад"
+
+msgctxt "field:sale.sale-ignored-account.invoice,invoice:"
+msgid "Invoice"
+msgstr "Фактура"
+
+msgctxt "field:sale.sale-ignored-account.invoice,sale:"
+msgid "Sale"
+msgstr "Продажба"
+
+msgctxt "field:sale.sale-recreated-account.invoice,invoice:"
+msgid "Invoice"
+msgstr "Фактура"
+
+msgctxt "field:sale.sale-recreated-account.invoice,sale:"
+msgid "Sale"
+msgstr "Продажба"
+
+msgctxt "field:stock.move,sale:"
+msgid "Sale"
+msgstr "Продажба"
+
+msgctxt "field:stock.move,sale_exception_state:"
+msgid "Exception State"
+msgstr "Състояние на грешка"
+
+msgctxt "help:product.configuration,default_lead_time:"
+msgid ""
+"The time from confirming the sales order to sending the products.\n"
+"Used for products without a lead time."
+msgstr ""
+
+msgctxt "help:product.product,lead_time:"
+msgid ""
+"The time from confirming the sales order to sending the products.\n"
+"If empty the default lead time from the configuration is used."
+msgstr ""
+
+msgctxt "help:product.template,lead_time:"
+msgid ""
+"The time from confirming the sales order to sending the products.\n"
+"If empty the default lead time from the configuration is used."
+msgstr ""
+
+msgctxt "help:sale.configuration,sale_process_after:"
+msgid ""
+"The grace period during which confirmed sale can still be reset to draft.\n"
+"Applied if a worker queue is activated."
+msgstr ""
+
+msgctxt "help:sale.handle.invoice.exception.ask,recreate_invoices:"
+msgid ""
+"The selected invoices will be recreated. The other ones will be ignored."
+msgstr ""
+"Избраните фактури ще бъдат наново създадени. Останалите ще бъдат игнорирани."
+
+msgctxt "help:sale.sale,shipping_date:"
+msgid "When the shipping of goods should start."
+msgstr ""
+
+#, fuzzy
+msgctxt "model:ir.action,name:act_invoice_form"
+msgid "Invoices"
+msgstr "Invoices"
+
+#, fuzzy
+msgctxt "model:ir.action,name:act_open_customer"
+msgid "Parties associated to Sales"
+msgstr "Parties associated to Sales"
+
+#, fuzzy
+msgctxt "model:ir.action,name:act_product"
+msgid "Products"
+msgstr "Продукт"
+
+msgctxt "model:ir.action,name:act_reporting_category"
+msgid "Sales per Category"
+msgstr "Sales per Category"
+
+msgctxt "model:ir.action,name:act_reporting_category_time_series"
+msgid "Sales per Category"
+msgstr "Sales per Category"
+
+msgctxt "model:ir.action,name:act_reporting_category_tree"
+msgid "Sales per Category"
+msgstr "Sales per Category"
+
+msgctxt "model:ir.action,name:act_reporting_country_subdivision_time_series"
+msgid "Sales per Subdivision"
+msgstr "Sales per Subdivision"
+
+msgctxt "model:ir.action,name:act_reporting_country_time_series"
+msgid "Sales per Country"
+msgstr "Sales per Country"
+
+msgctxt "model:ir.action,name:act_reporting_customer"
+msgid "Sales per Customer"
+msgstr "Sales per Customer"
+
+msgctxt "model:ir.action,name:act_reporting_customer_time_series"
+msgid "Sales per Customer"
+msgstr "Sales per Customer"
+
+msgctxt "model:ir.action,name:act_reporting_product"
+msgid "Sales per Product"
+msgstr "Sales per Product"
+
+msgctxt "model:ir.action,name:act_reporting_product_time_series"
+msgid "Sales per Product"
+msgstr "Sales per Product"
+
+msgctxt "model:ir.action,name:act_reporting_region"
+msgid "Sales per Region"
+msgstr "Sales per Region"
+
+#, fuzzy
+msgctxt "model:ir.action,name:act_return_form"
+msgid "Returns"
+msgstr "Returns"
+
+#, fuzzy
+msgctxt "model:ir.action,name:act_sale_configuration_form"
+msgid "Configuration"
+msgstr "Configuration"
+
+#, fuzzy
+msgctxt "model:ir.action,name:act_sale_form"
+msgid "Sales"
+msgstr "Sales"
+
+#, fuzzy
+msgctxt "model:ir.action,name:act_sale_form2"
+msgid "Sales"
+msgstr "Sales"
+
+#, fuzzy
+msgctxt "model:ir.action,name:act_sale_invoice_relate"
+msgid "Sales"
+msgstr "Управление на продажби"
+
+#, fuzzy
+msgctxt "model:ir.action,name:act_sale_move_relate"
+msgid "Moves"
+msgstr "Движения"
+
+msgctxt "model:ir.action,name:act_sale_shipment_returns_relate"
+msgid "Sales"
+msgstr "Sales"
+
+#, fuzzy
+msgctxt "model:ir.action,name:act_sale_shipments_relate"
+msgid "Sales"
+msgstr "Управление на продажби"
+
+#, fuzzy
+msgctxt "model:ir.action,name:act_shipment_form"
+msgid "Shipments"
+msgstr "Shipments"
+
+#, fuzzy
+msgctxt "model:ir.action,name:report_sale"
+msgid "Sale"
+msgstr "Sale"
+
+#, fuzzy
+msgctxt "model:ir.action,name:wizard_invoice_handle_exception"
+msgid "Handle Invoice Exception"
+msgstr "Handle Invoice Exception"
+
+msgctxt "model:ir.action,name:wizard_modify_header"
+msgid "Modify Header"
+msgstr "Modify Header"
+
+msgctxt "model:ir.action,name:wizard_reporting_region_open"
+msgid "Open Region"
+msgstr "Open Region"
+
+#, fuzzy
+msgctxt "model:ir.action,name:wizard_return_sale"
+msgid "Return Sale"
+msgstr "Създаване на меню Продажби"
+
+#, fuzzy
+msgctxt "model:ir.action,name:wizard_shipment_handle_exception"
+msgid "Handle Shipment Exception"
+msgstr "Handle Shipment Exception"
+
+msgctxt "model:ir.action.act_window.domain,name:act_sale_form_domain_all"
+msgid "All"
+msgstr "All"
+
+#, fuzzy
+msgctxt ""
+"model:ir.action.act_window.domain,name:act_sale_form_domain_confirmed"
+msgid "Confirmed"
+msgstr "Потвърден"
+
+#, fuzzy
+msgctxt "model:ir.action.act_window.domain,name:act_sale_form_domain_draft"
+msgid "Draft"
+msgstr "Проект"
+
+#, fuzzy
+msgctxt ""
+"model:ir.action.act_window.domain,name:act_sale_form_domain_exception"
+msgid "Exception"
+msgstr "Грешка"
+
+#, fuzzy
+msgctxt ""
+"model:ir.action.act_window.domain,name:act_sale_form_domain_processing"
+msgid "Processing"
+msgstr "Обработване"
+
+#, fuzzy
+msgctxt ""
+"model:ir.action.act_window.domain,name:act_sale_form_domain_quotation"
+msgid "Quotation"
+msgstr "Запитване"
+
+msgctxt "model:ir.message,text:msg_erase_party_pending_sale"
+msgid ""
+"You cannot erase party \"%(party)s\" while they have pending sales with "
+"company \"%(company)s\"."
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_sale_customer_location_required"
+msgid ""
+"To process sale \"%(sale)s\" you must set a customer location on party "
+"\"%(party)s\"."
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_sale_delete_cancel"
+msgid "To delete sale \"%(sale)s\" you must cancel it."
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_sale_invalid_method"
+msgid ""
+"You cannot use together invoice \"%(invoice_method)s\" and shipment "
+"\"%(shipment_method)s\" on sale \"%(sale)s\"."
+msgstr ""
+
+msgctxt ""
+"model:ir.message,text:msg_sale_invoice_address_required_for_quotation"
+msgid "To get a quote for sale \"%(sale)s\" you must enter an invoice address."
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_sale_invoice_reset_draft"
+msgid ""
+"You cannot reset invoice \"%(invoice)s\" to draft because it was generated "
+"by a sale."
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_sale_line_delete_cancel_draft"
+msgid ""
+"To delete line \"%(line)s\" you must cancel or reset to draft sale "
+"\"%(sale)s\"."
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_sale_missing_account_revenue"
+msgid "To invoice sale \"%(sale)s\" you must configure a default account revenue."
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_sale_modify_header_draft"
+msgid "To modify the header of sale \"%(sale)s\", it must be in \"draft\" state."
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_sale_move_reset_draft"
+msgid ""
+"You cannot reset move \"%(move)s\" to draft because it was generated by a "
+"sale."
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_sale_product_missing_account_revenue"
+msgid ""
+"To invoice sale \"%(sale)s\" you must define an account revenue for product "
+"\"%(product)s\"."
+msgstr ""
+
+#, fuzzy
+msgctxt "model:ir.message,text:msg_sale_reporting_company"
+msgid "Company"
+msgstr "Фирма"
+
+#, fuzzy
+msgctxt "model:ir.message,text:msg_sale_reporting_currency"
+msgid "Currency"
+msgstr "Валута"
+
+#, fuzzy
+msgctxt "model:ir.message,text:msg_sale_reporting_currency_digits"
+msgid "Currency Digits"
+msgstr "Цифри за валута"
+
+#, fuzzy
+msgctxt "model:ir.message,text:msg_sale_reporting_number"
+msgid "#"
+msgstr "#"
+
+msgctxt "model:ir.message,text:msg_sale_reporting_number_help"
+msgid "Number of sales"
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_sale_reporting_revenue"
+msgid "Revenue"
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_sale_reporting_revenue_trend"
+msgid "Revenue Trend"
+msgstr ""
+
+msgctxt ""
+"model:ir.message,text:msg_sale_shipment_address_required_for_quotation"
+msgid "To get a quote for sale \"%(sale)s\" you must enter a shipment address."
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_sale_warehouse_required_for_quotation"
+msgid "To get a quote for sale \"%(sale)s\" you must enter a warehouse."
+msgstr ""
+
+msgctxt "model:ir.model.button,string:sale_cancel_button"
+msgid "Cancel"
+msgstr "Cancel"
+
+msgctxt "model:ir.model.button,string:sale_confirm_button"
+msgid "Confirm"
+msgstr "Confirm"
+
+msgctxt "model:ir.model.button,string:sale_draft_button"
+msgid "Draft"
+msgstr "Draft"
+
+msgctxt "model:ir.model.button,string:sale_handle_invoice_exception_button"
+msgid "Handle Invoice Exception"
+msgstr "Handle Invoice Exception"
+
+msgctxt "model:ir.model.button,string:sale_handle_shipment_exception_button"
+msgid "Handle Shipment Exception"
+msgstr "Handle Shipment Exception"
+
+msgctxt "model:ir.model.button,string:sale_modify_header_button"
+msgid "Modify Header"
+msgstr "Modify Header"
+
+msgctxt "model:ir.model.button,string:sale_process_button"
+msgid "Process"
+msgstr "Process"
+
+msgctxt "model:ir.model.button,string:sale_quote_button"
+msgid "Quote"
+msgstr "Quote"
+
+msgctxt "model:ir.rule.group,name:rule_group_reporting_category_companies"
+msgid "User in companies"
+msgstr ""
+
+msgctxt ""
+"model:ir.rule.group,name:rule_group_reporting_category_time_series_companies"
+msgid "User in companies"
+msgstr ""
+
+msgctxt ""
+"model:ir.rule.group,name:rule_group_reporting_country_subdivision_time_series_companies"
+msgid "User in companies"
+msgstr ""
+
+msgctxt ""
+"model:ir.rule.group,name:rule_group_reporting_country_time_series_companies"
+msgid "User in companies"
+msgstr ""
+
+msgctxt "model:ir.rule.group,name:rule_group_reporting_customer_companies"
+msgid "User in companies"
+msgstr ""
+
+msgctxt ""
+"model:ir.rule.group,name:rule_group_reporting_customer_time_series_companies"
+msgid "User in companies"
+msgstr ""
+
+msgctxt "model:ir.rule.group,name:rule_group_reporting_product_companies"
+msgid "User in companies"
+msgstr ""
+
+msgctxt ""
+"model:ir.rule.group,name:rule_group_reporting_product_time_series_companies"
+msgid "User in companies"
+msgstr ""
+
+msgctxt "model:ir.rule.group,name:rule_group_reporting_region_companies"
+msgid "User in companies"
+msgstr ""
+
+msgctxt "model:ir.rule.group,name:rule_group_sale_companies"
+msgid "User in companies"
+msgstr ""
+
+#, fuzzy
+msgctxt "model:ir.sequence,name:sequence_sale"
+msgid "Sale"
+msgstr "Sale"
+
+#, fuzzy
+msgctxt "model:ir.sequence.type,name:sequence_type_sale"
+msgid "Sale"
+msgstr "Sale"
+
+#, fuzzy
+msgctxt "model:ir.ui.menu,name:menu_configuration"
+msgid "Configuration"
+msgstr "Configuration"
+
+#, fuzzy
+msgctxt "model:ir.ui.menu,name:menu_customer"
+msgid "Associated to Sales"
+msgstr "Parties associated to Sales"
+
+#, fuzzy
+msgctxt "model:ir.ui.menu,name:menu_product"
+msgid "Products"
+msgstr "Продукт"
+
+msgctxt "model:ir.ui.menu,name:menu_reporting"
+msgid "Reporting"
+msgstr "Reporting"
+
+msgctxt "model:ir.ui.menu,name:menu_reporting_sale"
+msgid "Sales"
+msgstr "Sales"
+
+#, fuzzy
+msgctxt "model:ir.ui.menu,name:menu_sale"
+msgid "Sales"
+msgstr "Sales"
+
+#, fuzzy
+msgctxt "model:ir.ui.menu,name:menu_sale_configuration"
+msgid "Configuration"
+msgstr "Configuration"
+
+#, fuzzy
+msgctxt "model:ir.ui.menu,name:menu_sale_form"
+msgid "Sales"
+msgstr "Sales"
+
+msgctxt "model:product.configuration.default_lead_time,name:"
+msgid "Product Default Lead Time"
+msgstr ""
+
+msgctxt "model:product.sale.context,name:"
+msgid "Product Sale Context"
+msgstr ""
+
+#, fuzzy
+msgctxt "model:res.group,name:group_sale"
+msgid "Sales"
+msgstr "Sales"
+
+#, fuzzy
+msgctxt "model:res.group,name:group_sale_admin"
+msgid "Sales Administrator"
+msgstr "Sales Administrator"
+
+msgctxt "model:sale.configuration,name:"
+msgid "Sale Configuration"
+msgstr "Конфигурация на продажба"
+
+msgctxt "model:sale.configuration.sale_method,name:"
+msgid "Sale Configuration Sale Method"
+msgstr ""
+
+msgctxt "model:sale.configuration.sequence,name:"
+msgid "Sale Configuration Sequence"
+msgstr ""
+
+msgctxt "model:sale.handle.invoice.exception.ask,name:"
+msgid "Handle Invoice Exception"
+msgstr "Обработване за грешка в фактура"
+
+msgctxt "model:sale.handle.shipment.exception.ask,name:"
+msgid "Handle Shipment Exception"
+msgstr "Обработване на грешка при пратка"
+
+msgctxt "model:sale.line,name:"
+msgid "Sale Line"
+msgstr "Ред от продажба"
+
+msgctxt "model:sale.line-account.tax,name:"
+msgid "Sale Line - Tax"
+msgstr "Ред от продажба - Данък"
+
+msgctxt "model:sale.line-ignored-stock.move,name:"
+msgid "Sale Line - Ignored Move"
+msgstr "Ред от продажба - Игнорирано движение"
+
+msgctxt "model:sale.line-recreated-stock.move,name:"
+msgid "Sale Line - Recreated Move"
+msgstr "Ред от продажба - Нановосъздадено движение"
+
+msgctxt "model:sale.reporting.category,name:"
+msgid "Sale Reporting per Category"
+msgstr ""
+
+msgctxt "model:sale.reporting.category.time_series,name:"
+msgid "Sale Reporting per Category"
+msgstr ""
+
+msgctxt "model:sale.reporting.category.tree,name:"
+msgid "Sale Reporting per Category"
+msgstr ""
+
+msgctxt "model:sale.reporting.context,name:"
+msgid "Sale Reporting Context"
+msgstr ""
+
+msgctxt "model:sale.reporting.country,name:"
+msgid "Sale Reporting per Country"
+msgstr ""
+
+msgctxt "model:sale.reporting.country.subdivision,name:"
+msgid "Sale Reporting per Subdivision"
+msgstr ""
+
+msgctxt "model:sale.reporting.country.subdivision.time_series,name:"
+msgid "Sale Reporting per Subdivision"
+msgstr ""
+
+msgctxt "model:sale.reporting.country.time_series,name:"
+msgid "Sale Reporting per Country"
+msgstr ""
+
+msgctxt "model:sale.reporting.customer,name:"
+msgid "Sale Reporting per Customer"
+msgstr ""
+
+msgctxt "model:sale.reporting.customer.time_series,name:"
+msgid "Sale Reporting per Customer"
+msgstr ""
+
+msgctxt "model:sale.reporting.product,name:"
+msgid "Sale Reporting per Product"
+msgstr ""
+
+msgctxt "model:sale.reporting.product.time_series,name:"
+msgid "Sale Reporting per Product"
+msgstr ""
+
+msgctxt "model:sale.reporting.region,name:"
+msgid "Sale Reporting per Region"
+msgstr ""
+
+#, fuzzy
+msgctxt "model:sale.return_sale.start,name:"
+msgid "Return Sale"
+msgstr "Създаване на меню Продажби"
+
+msgctxt "model:sale.sale,name:"
+msgid "Sale"
+msgstr "Продажба"
+
+msgctxt "model:sale.sale-ignored-account.invoice,name:"
+msgid "Sale - Ignored Invoice"
+msgstr "Продажба - Игнорирани фактури"
+
+msgctxt "model:sale.sale-recreated-account.invoice,name:"
+msgid "Sale - Recreated Invoice"
+msgstr "Продажба - Наново създадена фактура"
+
+#, fuzzy
+msgctxt "report:sale.sale:"
+msgid ":"
+msgstr ":"
+
+msgctxt "report:sale.sale:"
+msgid "Amount"
+msgstr "Сума"
+
+msgctxt "report:sale.sale:"
+msgid "Date:"
+msgstr "Дата:"
+
+msgctxt "report:sale.sale:"
+msgid "Description"
+msgstr "Описание"
+
+msgctxt "report:sale.sale:"
+msgid "Description:"
+msgstr "Описание:"
+
+msgctxt "report:sale.sale:"
+msgid "Draft Sale Order"
+msgstr "Проект на поръчка за продажба"
+
+msgctxt "report:sale.sale:"
+msgid "Quantity"
+msgstr "Количество"
+
+msgctxt "report:sale.sale:"
+msgid "Quotation N°:"
+msgstr "Запитване N°:"
+
+#, fuzzy
+msgctxt "report:sale.sale:"
+msgid "Reference:"
+msgstr "Отпратка"
+
+msgctxt "report:sale.sale:"
+msgid "Sale Order N°:"
+msgstr "Поръчка за продажба N°:"
+
+msgctxt "report:sale.sale:"
+msgid "Taxes"
+msgstr "Данъци"
+
+msgctxt "report:sale.sale:"
+msgid "Taxes:"
+msgstr "Данъци:"
+
+msgctxt "report:sale.sale:"
+msgid "Total (excl. taxes):"
+msgstr "Общо (без данъци):"
+
+msgctxt "report:sale.sale:"
+msgid "Total:"
+msgstr "Общо:"
+
+msgctxt "report:sale.sale:"
+msgid "Unit Price"
+msgstr "Единична цена"
+
+msgctxt "selection:account.invoice,sale_exception_state:"
+msgid "Ignored"
+msgstr "Игнорирано"
+
+msgctxt "selection:account.invoice,sale_exception_state:"
+msgid "Recreated"
+msgstr "Създаден наново"
+
+msgctxt "selection:sale.line,type:"
+msgid "Comment"
+msgstr "Коментар"
+
+msgctxt "selection:sale.line,type:"
+msgid "Line"
+msgstr "Ред"
+
+msgctxt "selection:sale.line,type:"
+msgid "Subtotal"
+msgstr "Междинна сума"
+
+msgctxt "selection:sale.line,type:"
+msgid "Title"
+msgstr "Заглавие"
+
+msgctxt "selection:sale.reporting.context,period:"
+msgid "Day"
+msgstr ""
+
+msgctxt "selection:sale.reporting.context,period:"
+msgid "Month"
+msgstr ""
+
+msgctxt "selection:sale.reporting.context,period:"
+msgid "Year"
+msgstr ""
+
+msgctxt "selection:sale.sale,invoice_method:"
+msgid "Manual"
+msgstr "Ръчно"
+
+msgctxt "selection:sale.sale,invoice_method:"
+msgid "On Order Processed"
+msgstr "При обработена поръчка"
+
+msgctxt "selection:sale.sale,invoice_method:"
+msgid "On Shipment Sent"
+msgstr "При изпращане на пратка"
+
+msgctxt "selection:sale.sale,invoice_state:"
+msgid "Exception"
+msgstr "Грешка"
+
+msgctxt "selection:sale.sale,invoice_state:"
+msgid "None"
+msgstr "Няма"
+
+msgctxt "selection:sale.sale,invoice_state:"
+msgid "Paid"
+msgstr "Платен"
+
+msgctxt "selection:sale.sale,invoice_state:"
+msgid "Waiting"
+msgstr "Изчакващ"
+
+msgctxt "selection:sale.sale,shipment_method:"
+msgid "Manual"
+msgstr "Ръчно"
+
+msgctxt "selection:sale.sale,shipment_method:"
+msgid "On Invoice Paid"
+msgstr "При плащане на фактура"
+
+msgctxt "selection:sale.sale,shipment_method:"
+msgid "On Order Processed"
+msgstr "При обработена поръчка"
+
+msgctxt "selection:sale.sale,shipment_state:"
+msgid "Exception"
+msgstr "Грешка"
+
+msgctxt "selection:sale.sale,shipment_state:"
+msgid "None"
+msgstr "Няма"
+
+msgctxt "selection:sale.sale,shipment_state:"
+msgid "Sent"
+msgstr "Изпратен"
+
+msgctxt "selection:sale.sale,shipment_state:"
+msgid "Waiting"
+msgstr "Изчакващ"
+
+#, fuzzy
+msgctxt "selection:sale.sale,state:"
+msgid "Cancelled"
+msgstr "Отказан"
+
+msgctxt "selection:sale.sale,state:"
+msgid "Confirmed"
+msgstr "Потвърден"
+
+msgctxt "selection:sale.sale,state:"
+msgid "Done"
+msgstr "Приключен"
+
+msgctxt "selection:sale.sale,state:"
+msgid "Draft"
+msgstr "Проект"
+
+msgctxt "selection:sale.sale,state:"
+msgid "Processing"
+msgstr "Обработване"
+
+msgctxt "selection:sale.sale,state:"
+msgid "Quotation"
+msgstr "Запитване"
+
+msgctxt "selection:stock.move,sale_exception_state:"
+msgid "Ignored"
+msgstr "Игнорирано"
+
+msgctxt "selection:stock.move,sale_exception_state:"
+msgid "Recreated"
+msgstr "Създаден наново"
+
+#, fuzzy
+msgctxt "view:party.party:"
+msgid "Sale"
+msgstr "Продажба"
+
+msgctxt "view:product.template:"
+msgid "Customers"
+msgstr "Клиенти"
+
+#, fuzzy
+msgctxt "view:sale.handle.invoice.exception.ask:"
+msgid "Choose invoices to recreate:"
+msgstr "Избор на фактури за ново създаване"
+
+#, fuzzy
+msgctxt "view:sale.handle.shipment.exception.ask:"
+msgid "Choose move to recreate:"
+msgstr "Избор на движение за ново създаване"
+
+msgctxt "view:sale.line:"
+msgid "General"
+msgstr "Основен"
+
+msgctxt "view:sale.line:"
+msgid "Notes"
+msgstr "Бележки"
+
+msgctxt "view:sale.line:"
+msgid "Taxes"
+msgstr "Данъци"
+
+msgctxt "view:sale.return_sale.start:"
+msgid "Are you sure to return these/this sale(s)?"
+msgstr ""
+
+msgctxt "view:sale.sale:"
+msgid "Other Info"
+msgstr "Друга информация"
+
+msgctxt "view:sale.sale:"
+msgid "Sale"
+msgstr "Продажба"
+
+msgctxt "wizard_button:sale.handle.invoice.exception,ask,end:"
+msgid "Cancel"
+msgstr "Отказ"
+
+msgctxt "wizard_button:sale.handle.invoice.exception,ask,handle:"
+msgid "OK"
+msgstr "Добре"
+
+msgctxt "wizard_button:sale.handle.shipment.exception,ask,end:"
+msgid "Cancel"
+msgstr "Отказ"
+
+msgctxt "wizard_button:sale.handle.shipment.exception,ask,handle:"
+msgid "OK"
+msgstr "Добре"
+
+#, fuzzy
+msgctxt "wizard_button:sale.modify_header,start,end:"
+msgid "Cancel"
+msgstr "Отказ"
+
+msgctxt "wizard_button:sale.modify_header,start,modify:"
+msgid "Modify"
+msgstr ""
+
+#, fuzzy
+msgctxt "wizard_button:sale.return_sale,start,end:"
+msgid "Cancel"
+msgstr "Отказване"
+
+#, fuzzy
+msgctxt "wizard_button:sale.return_sale,start,return_:"
+msgid "Return"
+msgstr "Връщане"
diff --git a/modules/sale/locale/ca.po b/modules/sale/locale/ca.po
new file mode 100644
index 0000000000..ce0d269dd3
--- /dev/null
+++ b/modules/sale/locale/ca.po
@@ -0,0 +1,1375 @@
+#
+msgid ""
+msgstr "Content-Type: text/plain; charset=utf-8\n"
+
+msgctxt "field:account.invoice,sale_exception_state:"
+msgid "Exception State"
+msgstr "Estat d'excepció"
+
+msgctxt "field:account.invoice,sales:"
+msgid "Sales"
+msgstr "Vendes"
+
+msgctxt "field:product.configuration,default_lead_time:"
+msgid "Default Lead Time"
+msgstr "Temps d'espera per defecte"
+
+msgctxt "field:product.configuration.default_lead_time,company:"
+msgid "Company"
+msgstr "Empresa"
+
+msgctxt "field:product.configuration.default_lead_time,default_lead_time:"
+msgid "Default Lead Time"
+msgstr "Temps d'espera per defecte"
+
+msgctxt "field:product.product,lead_time:"
+msgid "Lead Time"
+msgstr "Temps d'espera"
+
+msgctxt "field:product.product,salable:"
+msgid "Salable"
+msgstr "Vendible"
+
+msgctxt "field:product.product,sale_price_uom:"
+msgid "Sale Price"
+msgstr "Preu de venda"
+
+msgctxt "field:product.product,sale_uom:"
+msgid "Sale UOM"
+msgstr "UdM de venda"
+
+msgctxt "field:product.sale.context,company:"
+msgid "Company"
+msgstr "Empresa"
+
+msgctxt "field:product.sale.context,currency:"
+msgid "Currency"
+msgstr "Moneda"
+
+msgctxt "field:product.sale.context,customer:"
+msgid "Customer"
+msgstr "Client"
+
+msgctxt "field:product.sale.context,locations:"
+msgid "Warehouses"
+msgstr "Magatzems"
+
+msgctxt "field:product.sale.context,quantity:"
+msgid "Quantity"
+msgstr "Quantitat"
+
+msgctxt "field:product.sale.context,sale_date:"
+msgid "Sale Date"
+msgstr "Data venda"
+
+msgctxt "field:product.sale.context,stock_date_end:"
+msgid "Stock End Date"
+msgstr "Data final existències"
+
+msgctxt "field:product.template,lead_time:"
+msgid "Lead Time"
+msgstr "Temps d'espera"
+
+msgctxt "field:product.template,salable:"
+msgid "Salable"
+msgstr "Vendible"
+
+msgctxt "field:product.template,sale_uom:"
+msgid "Sale UOM"
+msgstr "UdM de venda"
+
+msgctxt "field:sale.configuration,sale_invoice_method:"
+msgid "Sale Invoice Method"
+msgstr "Mètode de facturació"
+
+msgctxt "field:sale.configuration,sale_process_after:"
+msgid "Process Sale after"
+msgstr "Processa les vendes desprès de"
+
+msgctxt "field:sale.configuration,sale_sequence:"
+msgid "Sale Sequence"
+msgstr "Seqüència de venda"
+
+msgctxt "field:sale.configuration,sale_shipment_method:"
+msgid "Sale Shipment Method"
+msgstr "Mètode d'enviament"
+
+msgctxt "field:sale.configuration.sale_method,sale_invoice_method:"
+msgid "Sale Invoice Method"
+msgstr "Mètode de facturació"
+
+msgctxt "field:sale.configuration.sale_method,sale_shipment_method:"
+msgid "Sale Shipment Method"
+msgstr "Mètode d'enviament"
+
+msgctxt "field:sale.configuration.sequence,company:"
+msgid "Company"
+msgstr "Empresa"
+
+msgctxt "field:sale.configuration.sequence,sale_sequence:"
+msgid "Sale Sequence"
+msgstr "Seqüència de venda"
+
+msgctxt "field:sale.handle.invoice.exception.ask,domain_invoices:"
+msgid "Domain Invoices"
+msgstr "Domini factures"
+
+msgctxt "field:sale.handle.invoice.exception.ask,recreate_invoices:"
+msgid "Recreate Invoices"
+msgstr "Recrea factures"
+
+msgctxt "field:sale.handle.shipment.exception.ask,domain_moves:"
+msgid "Domain Moves"
+msgstr "Domini dels moviments"
+
+msgctxt "field:sale.handle.shipment.exception.ask,recreate_moves:"
+msgid "Recreate Moves"
+msgstr "Recrea moviments"
+
+msgctxt "field:sale.line,actual_quantity:"
+msgid "Actual Quantity"
+msgstr "Quantitat actual"
+
+msgctxt "field:sale.line,amount:"
+msgid "Amount"
+msgstr "Import"
+
+msgctxt "field:sale.line,company:"
+msgid "Company"
+msgstr "Empresa"
+
+msgctxt "field:sale.line,currency:"
+msgid "Currency"
+msgstr "Moneda"
+
+msgctxt "field:sale.line,description:"
+msgid "Description"
+msgstr "Descripció"
+
+msgctxt "field:sale.line,from_location:"
+msgid "From Location"
+msgstr "Des de la ubicació"
+
+msgctxt "field:sale.line,invoice_lines:"
+msgid "Invoice Lines"
+msgstr "Línies de factura"
+
+msgctxt "field:sale.line,move_done:"
+msgid "Moves Done"
+msgstr "Moviments finalitzats"
+
+msgctxt "field:sale.line,move_exception:"
+msgid "Moves Exception"
+msgstr "Moviments en excepció"
+
+msgctxt "field:sale.line,moves:"
+msgid "Moves"
+msgstr "Moviments"
+
+msgctxt "field:sale.line,moves_ignored:"
+msgid "Ignored Moves"
+msgstr "Moviments ignorats"
+
+msgctxt "field:sale.line,moves_recreated:"
+msgid "Recreated Moves"
+msgstr "Moviments recreats"
+
+msgctxt "field:sale.line,note:"
+msgid "Note"
+msgstr "Nota"
+
+msgctxt "field:sale.line,product:"
+msgid "Product"
+msgstr "Producte"
+
+msgctxt "field:sale.line,product_uom_category:"
+msgid "Product Uom Category"
+msgstr "Categoria UdM del producte"
+
+msgctxt "field:sale.line,quantity:"
+msgid "Quantity"
+msgstr "Quantitat"
+
+msgctxt "field:sale.line,sale:"
+msgid "Sale"
+msgstr "Venda"
+
+msgctxt "field:sale.line,sale_state:"
+msgid "Sale State"
+msgstr "Estat de venda"
+
+msgctxt "field:sale.line,shipping_date:"
+msgid "Shipping Date"
+msgstr "Data d'enviament"
+
+msgctxt "field:sale.line,summary:"
+msgid "Summary"
+msgstr "Resum"
+
+msgctxt "field:sale.line,taxes:"
+msgid "Taxes"
+msgstr "Impostos"
+
+msgctxt "field:sale.line,to_location:"
+msgid "To Location"
+msgstr "A la ubicació"
+
+msgctxt "field:sale.line,type:"
+msgid "Type"
+msgstr "Tipus"
+
+msgctxt "field:sale.line,unit:"
+msgid "Unit"
+msgstr "Unitat"
+
+msgctxt "field:sale.line,unit_digits:"
+msgid "Unit Digits"
+msgstr "Dígits de la unitat"
+
+msgctxt "field:sale.line,unit_price:"
+msgid "Unit Price"
+msgstr "Preu unitari"
+
+msgctxt "field:sale.line,warehouse:"
+msgid "Warehouse"
+msgstr "Magatzem"
+
+msgctxt "field:sale.line-account.tax,line:"
+msgid "Sale Line"
+msgstr "Línia de venta"
+
+msgctxt "field:sale.line-account.tax,tax:"
+msgid "Tax"
+msgstr "Impost"
+
+msgctxt "field:sale.line-ignored-stock.move,move:"
+msgid "Move"
+msgstr "Moviment"
+
+msgctxt "field:sale.line-ignored-stock.move,sale_line:"
+msgid "Sale Line"
+msgstr "Línia de venda"
+
+msgctxt "field:sale.line-recreated-stock.move,move:"
+msgid "Move"
+msgstr "Moviment"
+
+msgctxt "field:sale.line-recreated-stock.move,sale_line:"
+msgid "Sale Line"
+msgstr "Línia de venta"
+
+msgctxt "field:sale.reporting.category,category:"
+msgid "Category"
+msgstr "Categoria"
+
+msgctxt "field:sale.reporting.category,time_series:"
+msgid "Time Series"
+msgstr "Sèries temporals"
+
+msgctxt "field:sale.reporting.category.time_series,category:"
+msgid "Category"
+msgstr "Categoria"
+
+msgctxt "field:sale.reporting.category.time_series,date:"
+msgid "Date"
+msgstr "Data"
+
+msgctxt "field:sale.reporting.category.tree,children:"
+msgid "Children"
+msgstr "Fills"
+
+msgctxt "field:sale.reporting.category.tree,currency_digits:"
+msgid "Currency Digits"
+msgstr "Decimals de la moneda"
+
+msgctxt "field:sale.reporting.category.tree,name:"
+msgid "Name"
+msgstr "Nom"
+
+msgctxt "field:sale.reporting.category.tree,parent:"
+msgid "Parent"
+msgstr "Pare"
+
+msgctxt "field:sale.reporting.category.tree,revenue:"
+msgid "Revenue"
+msgstr "Ingressos"
+
+msgctxt "field:sale.reporting.context,company:"
+msgid "Company"
+msgstr "Empresa"
+
+msgctxt "field:sale.reporting.context,from_date:"
+msgid "From Date"
+msgstr "Des de la data"
+
+msgctxt "field:sale.reporting.context,period:"
+msgid "Period"
+msgstr "Període"
+
+msgctxt "field:sale.reporting.context,to_date:"
+msgid "To Date"
+msgstr "Fins a la data"
+
+msgctxt "field:sale.reporting.context,warehouse:"
+msgid "Warehouse"
+msgstr "Magatzem"
+
+msgctxt "field:sale.reporting.country,country:"
+msgid "Country"
+msgstr "País"
+
+msgctxt "field:sale.reporting.country,time_series:"
+msgid "Time Series"
+msgstr "Sèries temporals"
+
+msgctxt "field:sale.reporting.country.subdivision,country:"
+msgid "Country"
+msgstr "País"
+
+msgctxt "field:sale.reporting.country.subdivision,subdivision:"
+msgid "Subdivision"
+msgstr "Subdivisió"
+
+msgctxt "field:sale.reporting.country.subdivision,time_series:"
+msgid "Time Series"
+msgstr "Sèries temporals"
+
+msgctxt "field:sale.reporting.country.subdivision.time_series,country:"
+msgid "Country"
+msgstr "País"
+
+msgctxt "field:sale.reporting.country.subdivision.time_series,date:"
+msgid "Date"
+msgstr "Data"
+
+msgctxt "field:sale.reporting.country.subdivision.time_series,subdivision:"
+msgid "Subdivision"
+msgstr "Subdivisió"
+
+msgctxt "field:sale.reporting.country.time_series,country:"
+msgid "Country"
+msgstr "País"
+
+msgctxt "field:sale.reporting.country.time_series,date:"
+msgid "Date"
+msgstr "Data"
+
+msgctxt "field:sale.reporting.customer,customer:"
+msgid "Customer"
+msgstr "Client"
+
+msgctxt "field:sale.reporting.customer,time_series:"
+msgid "Time Series"
+msgstr "Sèries temporals"
+
+msgctxt "field:sale.reporting.customer.time_series,customer:"
+msgid "Customer"
+msgstr "Client"
+
+msgctxt "field:sale.reporting.customer.time_series,date:"
+msgid "Date"
+msgstr "Data"
+
+msgctxt "field:sale.reporting.product,product:"
+msgid "Product"
+msgstr "Producte"
+
+msgctxt "field:sale.reporting.product,time_series:"
+msgid "Time Series"
+msgstr "Sèries temporals"
+
+msgctxt "field:sale.reporting.product.time_series,date:"
+msgid "Date"
+msgstr "Data"
+
+msgctxt "field:sale.reporting.product.time_series,product:"
+msgid "Product"
+msgstr "Producte"
+
+msgctxt "field:sale.reporting.region,children:"
+msgid "Children"
+msgstr "Fills"
+
+msgctxt "field:sale.reporting.region,parent:"
+msgid "Parent"
+msgstr "Pare"
+
+msgctxt "field:sale.reporting.region,region:"
+msgid "Region"
+msgstr "Regió"
+
+msgctxt "field:sale.sale,comment:"
+msgid "Comment"
+msgstr "Comentari"
+
+msgctxt "field:sale.sale,company:"
+msgid "Company"
+msgstr "Empresa"
+
+msgctxt "field:sale.sale,confirmed_by:"
+msgid "Confirmed By"
+msgstr "Confirmada per"
+
+msgctxt "field:sale.sale,contact:"
+msgid "Contact"
+msgstr "Contacte"
+
+msgctxt "field:sale.sale,currency:"
+msgid "Currency"
+msgstr "Moneda"
+
+msgctxt "field:sale.sale,currency_digits:"
+msgid "Currency Digits"
+msgstr "Decimals de la moneda"
+
+msgctxt "field:sale.sale,description:"
+msgid "Description"
+msgstr "Descripció"
+
+msgctxt "field:sale.sale,invoice_address:"
+msgid "Invoice Address"
+msgstr "Adreça de facturació"
+
+msgctxt "field:sale.sale,invoice_method:"
+msgid "Invoice Method"
+msgstr "Mètode de facturació"
+
+msgctxt "field:sale.sale,invoice_party:"
+msgid "Invoice Party"
+msgstr "Tercer de la factura"
+
+msgctxt "field:sale.sale,invoice_state:"
+msgid "Invoice State"
+msgstr "Estat de la factura"
+
+msgctxt "field:sale.sale,invoices:"
+msgid "Invoices"
+msgstr "Factures"
+
+msgctxt "field:sale.sale,invoices_ignored:"
+msgid "Ignored Invoices"
+msgstr "Factures ignorades"
+
+msgctxt "field:sale.sale,invoices_recreated:"
+msgid "Recreated Invoices"
+msgstr "Factures recreades"
+
+msgctxt "field:sale.sale,lines:"
+msgid "Lines"
+msgstr "Línies"
+
+msgctxt "field:sale.sale,moves:"
+msgid "Moves"
+msgstr "Moviments"
+
+msgctxt "field:sale.sale,number:"
+msgid "Number"
+msgstr "Número"
+
+msgctxt "field:sale.sale,origin:"
+msgid "Origin"
+msgstr "Origen"
+
+msgctxt "field:sale.sale,party:"
+msgid "Party"
+msgstr "Tercer"
+
+msgctxt "field:sale.sale,party_lang:"
+msgid "Party Language"
+msgstr "Idioma del tercer"
+
+msgctxt "field:sale.sale,payment_term:"
+msgid "Payment Term"
+msgstr "Termini de pagament"
+
+msgctxt "field:sale.sale,quoted_by:"
+msgid "Quoted By"
+msgstr "Pressupostada per"
+
+msgctxt "field:sale.sale,reference:"
+msgid "Reference"
+msgstr "Referència"
+
+msgctxt "field:sale.sale,sale_date:"
+msgid "Sale Date"
+msgstr "Data venda"
+
+msgctxt "field:sale.sale,shipment_address:"
+msgid "Shipment Address"
+msgstr "Adreça d'enviament"
+
+msgctxt "field:sale.sale,shipment_method:"
+msgid "Shipment Method"
+msgstr "Mètode d'enviament"
+
+msgctxt "field:sale.sale,shipment_party:"
+msgid "Shipment Party"
+msgstr "Tercer de l'enviament"
+
+msgctxt "field:sale.sale,shipment_returns:"
+msgid "Shipment Returns"
+msgstr "Albarans de devolució"
+
+msgctxt "field:sale.sale,shipment_state:"
+msgid "Shipment State"
+msgstr "Estat enviament"
+
+msgctxt "field:sale.sale,shipments:"
+msgid "Shipments"
+msgstr "Albarans"
+
+msgctxt "field:sale.sale,shipping_date:"
+msgid "Shipping Date"
+msgstr "Data d'enviament"
+
+msgctxt "field:sale.sale,state:"
+msgid "State"
+msgstr "Estat"
+
+msgctxt "field:sale.sale,tax_amount:"
+msgid "Tax"
+msgstr "Impost"
+
+msgctxt "field:sale.sale,tax_amount_cache:"
+msgid "Tax Cache"
+msgstr "Impostos precalculats"
+
+msgctxt "field:sale.sale,total_amount:"
+msgid "Total"
+msgstr "Total"
+
+msgctxt "field:sale.sale,total_amount_cache:"
+msgid "Total Cache"
+msgstr "Total precalculat"
+
+msgctxt "field:sale.sale,untaxed_amount:"
+msgid "Untaxed"
+msgstr "Base imposable"
+
+msgctxt "field:sale.sale,untaxed_amount_cache:"
+msgid "Untaxed Cache"
+msgstr "Base imposable precalculada"
+
+msgctxt "field:sale.sale,warehouse:"
+msgid "Warehouse"
+msgstr "Magatzem"
+
+msgctxt "field:sale.sale-ignored-account.invoice,invoice:"
+msgid "Invoice"
+msgstr "Factura"
+
+msgctxt "field:sale.sale-ignored-account.invoice,sale:"
+msgid "Sale"
+msgstr "Venda"
+
+msgctxt "field:sale.sale-recreated-account.invoice,invoice:"
+msgid "Invoice"
+msgstr "Factura"
+
+msgctxt "field:sale.sale-recreated-account.invoice,sale:"
+msgid "Sale"
+msgstr "Venda"
+
+msgctxt "field:stock.move,sale:"
+msgid "Sale"
+msgstr "Venda"
+
+msgctxt "field:stock.move,sale_exception_state:"
+msgid "Exception State"
+msgstr "Estat excepció"
+
+msgctxt "help:product.configuration,default_lead_time:"
+msgid ""
+"The time from confirming the sales order to sending the products.\n"
+"Used for products without a lead time."
+msgstr ""
+"El temps desde la confirmació de la venda fins que s'envien els productes.\n"
+"Utilitzats als productes sense temps d'espera."
+
+msgctxt "help:product.product,lead_time:"
+msgid ""
+"The time from confirming the sales order to sending the products.\n"
+"If empty the default lead time from the configuration is used."
+msgstr ""
+"El temps desde que es confirma la comanda fins que s'envien els productes.\n"
+"Si es deixa en blanc s'utilitza el temps d'enviament per defecte de la configuració."
+
+msgctxt "help:product.template,lead_time:"
+msgid ""
+"The time from confirming the sales order to sending the products.\n"
+"If empty the default lead time from the configuration is used."
+msgstr ""
+"El temps desde que es confirma la comanda fins que s'envien els productes.\n"
+"Si es deixa en blanc s'utilitza el temps d'enviament per defecte de la configuració."
+
+msgctxt "help:sale.configuration,sale_process_after:"
+msgid ""
+"The grace period during which confirmed sale can still be reset to draft.\n"
+"Applied if a worker queue is activated."
+msgstr ""
+"El període durant el qual una venda confirmada es pot tornar a passar a esborrany.\n"
+"Aplica només si la cua de treballs està activada."
+
+msgctxt "help:sale.handle.invoice.exception.ask,recreate_invoices:"
+msgid ""
+"The selected invoices will be recreated. The other ones will be ignored."
+msgstr ""
+"Les factures seleccionades seran recreades. Les altres seran ignorades."
+
+msgctxt "help:sale.sale,shipping_date:"
+msgid "When the shipping of goods should start."
+msgstr "Quan hauria de començar a enviar els bens."
+
+msgctxt "model:ir.action,name:act_invoice_form"
+msgid "Invoices"
+msgstr "Factures"
+
+msgctxt "model:ir.action,name:act_open_customer"
+msgid "Parties associated to Sales"
+msgstr "Tercers amb vendes"
+
+msgctxt "model:ir.action,name:act_product"
+msgid "Products"
+msgstr "Productes"
+
+msgctxt "model:ir.action,name:act_reporting_category"
+msgid "Sales per Category"
+msgstr "Vendes per categoria"
+
+msgctxt "model:ir.action,name:act_reporting_category_time_series"
+msgid "Sales per Category"
+msgstr "Vendes per categoria"
+
+msgctxt "model:ir.action,name:act_reporting_category_tree"
+msgid "Sales per Category"
+msgstr "Vendes per categoria"
+
+msgctxt "model:ir.action,name:act_reporting_country_subdivision_time_series"
+msgid "Sales per Subdivision"
+msgstr "Vendes per subdivisió"
+
+msgctxt "model:ir.action,name:act_reporting_country_time_series"
+msgid "Sales per Country"
+msgstr "Vendes per país"
+
+msgctxt "model:ir.action,name:act_reporting_customer"
+msgid "Sales per Customer"
+msgstr "Vendes per client"
+
+msgctxt "model:ir.action,name:act_reporting_customer_time_series"
+msgid "Sales per Customer"
+msgstr "Vendes per client"
+
+msgctxt "model:ir.action,name:act_reporting_product"
+msgid "Sales per Product"
+msgstr "Vendes per producte"
+
+msgctxt "model:ir.action,name:act_reporting_product_time_series"
+msgid "Sales per Product"
+msgstr "Vendes per regió"
+
+msgctxt "model:ir.action,name:act_reporting_region"
+msgid "Sales per Region"
+msgstr "Vendes per regió"
+
+msgctxt "model:ir.action,name:act_return_form"
+msgid "Returns"
+msgstr "Albarans de devolució"
+
+msgctxt "model:ir.action,name:act_sale_configuration_form"
+msgid "Configuration"
+msgstr "Configuració"
+
+msgctxt "model:ir.action,name:act_sale_form"
+msgid "Sales"
+msgstr "Vendes"
+
+msgctxt "model:ir.action,name:act_sale_form2"
+msgid "Sales"
+msgstr "Vendes"
+
+msgctxt "model:ir.action,name:act_sale_invoice_relate"
+msgid "Sales"
+msgstr "Vendes"
+
+msgctxt "model:ir.action,name:act_sale_move_relate"
+msgid "Moves"
+msgstr "Moviments"
+
+msgctxt "model:ir.action,name:act_sale_shipment_returns_relate"
+msgid "Sales"
+msgstr "Vendes"
+
+msgctxt "model:ir.action,name:act_sale_shipments_relate"
+msgid "Sales"
+msgstr "Vendes"
+
+msgctxt "model:ir.action,name:act_shipment_form"
+msgid "Shipments"
+msgstr "Albarans"
+
+msgctxt "model:ir.action,name:report_sale"
+msgid "Sale"
+msgstr "Venda"
+
+msgctxt "model:ir.action,name:wizard_invoice_handle_exception"
+msgid "Handle Invoice Exception"
+msgstr "Gestiona l'excepció de factura"
+
+msgctxt "model:ir.action,name:wizard_modify_header"
+msgid "Modify Header"
+msgstr "Modificar capçalera"
+
+msgctxt "model:ir.action,name:wizard_reporting_region_open"
+msgid "Open Region"
+msgstr "Obre regió"
+
+msgctxt "model:ir.action,name:wizard_return_sale"
+msgid "Return Sale"
+msgstr "Retorna la venda"
+
+msgctxt "model:ir.action,name:wizard_shipment_handle_exception"
+msgid "Handle Shipment Exception"
+msgstr "Gestiona l'excepció d'enviament"
+
+msgctxt "model:ir.action.act_window.domain,name:act_sale_form_domain_all"
+msgid "All"
+msgstr "Tot"
+
+msgctxt ""
+"model:ir.action.act_window.domain,name:act_sale_form_domain_confirmed"
+msgid "Confirmed"
+msgstr "Confirmada"
+
+msgctxt "model:ir.action.act_window.domain,name:act_sale_form_domain_draft"
+msgid "Draft"
+msgstr "Esborrany"
+
+msgctxt ""
+"model:ir.action.act_window.domain,name:act_sale_form_domain_exception"
+msgid "Exception"
+msgstr "Excepció"
+
+msgctxt ""
+"model:ir.action.act_window.domain,name:act_sale_form_domain_processing"
+msgid "Processing"
+msgstr "En procés"
+
+msgctxt ""
+"model:ir.action.act_window.domain,name:act_sale_form_domain_quotation"
+msgid "Quotation"
+msgstr "Pressupost"
+
+msgctxt "model:ir.message,text:msg_erase_party_pending_sale"
+msgid ""
+"You cannot erase party \"%(party)s\" while they have pending sales with "
+"company \"%(company)s\"."
+msgstr ""
+"No podeu eliminar el tercer \"%(party)s\" mentre tingui vendes pendents amb "
+"l'empresa \"%(company)s\"."
+
+msgctxt "model:ir.message,text:msg_sale_customer_location_required"
+msgid ""
+"To process sale \"%(sale)s\" you must set a customer location on party "
+"\"%(party)s\"."
+msgstr ""
+"Per processar la venda \"%(sale)s\" heu de definir una ubicació de client "
+"pel tercer \"%(party)s\"."
+
+msgctxt "model:ir.message,text:msg_sale_delete_cancel"
+msgid "To delete sale \"%(sale)s\" you must cancel it."
+msgstr "Per eliminar la venda \"%(venda)s\" l'heu de cancel·lar primer."
+
+msgctxt "model:ir.message,text:msg_sale_invalid_method"
+msgid ""
+"You cannot use together invoice \"%(invoice_method)s\" and shipment "
+"\"%(shipment_method)s\" on sale \"%(sale)s\"."
+msgstr ""
+"No podeu utilitzar a la vegada el mètode de facturació "
+"\"%(invoice_method)s\" i el mètode d'enviament \"%(shipment_method)s\" a la "
+"venta \"%(sale)s\"."
+
+msgctxt ""
+"model:ir.message,text:msg_sale_invoice_address_required_for_quotation"
+msgid "To get a quote for sale \"%(sale)s\" you must enter an invoice address."
+msgstr ""
+"Per obtenir un pressupost de la venda \"%(sale)s\" heu d'introduir una "
+"adreça de facturació."
+
+msgctxt "model:ir.message,text:msg_sale_invoice_reset_draft"
+msgid ""
+"You cannot reset invoice \"%(invoice)s\" to draft because it was generated "
+"by a sale."
+msgstr ""
+"No podeu restablir la factura \"%(invoice)s\" a esborrany perquè es va "
+"generar des d'una venda."
+
+msgctxt "model:ir.message,text:msg_sale_line_delete_cancel_draft"
+msgid ""
+"To delete line \"%(line)s\" you must cancel or reset to draft sale "
+"\"%(sale)s\"."
+msgstr ""
+"Per eliminar la línia \"%(line)s\" heu de cancel·lar o restablir a esborrany"
+" la venda \"%(sale)s\"."
+
+msgctxt "model:ir.message,text:msg_sale_missing_account_revenue"
+msgid "To invoice sale \"%(sale)s\" you must configure a default account revenue."
+msgstr ""
+"Per facturar la venda \"%(sale)s\" heu de configurar un compte de ingressos "
+"per defecte."
+
+msgctxt "model:ir.message,text:msg_sale_modify_header_draft"
+msgid "To modify the header of sale \"%(sale)s\", it must be in \"draft\" state."
+msgstr ""
+"Per modificar la capçalera de la venda \"%(sale)s\" ha d'estar en estat "
+"\"esborrany\"."
+
+msgctxt "model:ir.message,text:msg_sale_move_reset_draft"
+msgid ""
+"You cannot reset move \"%(move)s\" to draft because it was generated by a "
+"sale."
+msgstr ""
+"No podeu restablir el moviment \"%(move)s\" a esborrany perquè es va generar"
+" des d'un venda."
+
+msgctxt "model:ir.message,text:msg_sale_product_missing_account_revenue"
+msgid ""
+"To invoice sale \"%(sale)s\" you must define an account revenue for product "
+"\"%(product)s\"."
+msgstr ""
+"Per facturar la venda \"%(sale)s\" heu de definir un compte d'ingressos pel "
+"producte \"%(product)s\"."
+
+msgctxt "model:ir.message,text:msg_sale_reporting_company"
+msgid "Company"
+msgstr "Empresa"
+
+msgctxt "model:ir.message,text:msg_sale_reporting_currency"
+msgid "Currency"
+msgstr "Moneda"
+
+msgctxt "model:ir.message,text:msg_sale_reporting_currency_digits"
+msgid "Currency Digits"
+msgstr "Decimals de la moneda"
+
+msgctxt "model:ir.message,text:msg_sale_reporting_number"
+msgid "#"
+msgstr "#"
+
+msgctxt "model:ir.message,text:msg_sale_reporting_number_help"
+msgid "Number of sales"
+msgstr "Número de vendes"
+
+msgctxt "model:ir.message,text:msg_sale_reporting_revenue"
+msgid "Revenue"
+msgstr "Ingressos"
+
+msgctxt "model:ir.message,text:msg_sale_reporting_revenue_trend"
+msgid "Revenue Trend"
+msgstr "Tendència ingressos"
+
+msgctxt ""
+"model:ir.message,text:msg_sale_shipment_address_required_for_quotation"
+msgid "To get a quote for sale \"%(sale)s\" you must enter a shipment address."
+msgstr ""
+"Per obtenir un pressupost de la venda \"%(sale)s\" heu d'introduir una "
+"adreça d'enviament."
+
+msgctxt "model:ir.message,text:msg_sale_warehouse_required_for_quotation"
+msgid "To get a quote for sale \"%(sale)s\" you must enter a warehouse."
+msgstr ""
+"Per obtenir un pressupost de la venda \"%(sale)s\" heu d'introduir un "
+"magatzem."
+
+msgctxt "model:ir.model.button,string:sale_cancel_button"
+msgid "Cancel"
+msgstr "Cancel·la"
+
+msgctxt "model:ir.model.button,string:sale_confirm_button"
+msgid "Confirm"
+msgstr "Confirma"
+
+msgctxt "model:ir.model.button,string:sale_draft_button"
+msgid "Draft"
+msgstr "Esborrany"
+
+msgctxt "model:ir.model.button,string:sale_handle_invoice_exception_button"
+msgid "Handle Invoice Exception"
+msgstr "Gestiona excepció de factura"
+
+msgctxt "model:ir.model.button,string:sale_handle_shipment_exception_button"
+msgid "Handle Shipment Exception"
+msgstr "Gestiona excepció d'enviament"
+
+msgctxt "model:ir.model.button,string:sale_modify_header_button"
+msgid "Modify Header"
+msgstr "Modificar capçalera"
+
+msgctxt "model:ir.model.button,string:sale_process_button"
+msgid "Process"
+msgstr "Processa"
+
+msgctxt "model:ir.model.button,string:sale_quote_button"
+msgid "Quote"
+msgstr "Pressupost"
+
+msgctxt "model:ir.rule.group,name:rule_group_reporting_category_companies"
+msgid "User in companies"
+msgstr "Usuari a les empreses"
+
+msgctxt ""
+"model:ir.rule.group,name:rule_group_reporting_category_time_series_companies"
+msgid "User in companies"
+msgstr "Usuari a les empreses"
+
+msgctxt ""
+"model:ir.rule.group,name:rule_group_reporting_country_subdivision_time_series_companies"
+msgid "User in companies"
+msgstr "Usuari a les empreses"
+
+msgctxt ""
+"model:ir.rule.group,name:rule_group_reporting_country_time_series_companies"
+msgid "User in companies"
+msgstr "Usuari a les empreses"
+
+msgctxt "model:ir.rule.group,name:rule_group_reporting_customer_companies"
+msgid "User in companies"
+msgstr "Usuari a les empreses"
+
+msgctxt ""
+"model:ir.rule.group,name:rule_group_reporting_customer_time_series_companies"
+msgid "User in companies"
+msgstr "Usuari a les empreses"
+
+msgctxt "model:ir.rule.group,name:rule_group_reporting_product_companies"
+msgid "User in companies"
+msgstr "Usuari a les empreses"
+
+msgctxt ""
+"model:ir.rule.group,name:rule_group_reporting_product_time_series_companies"
+msgid "User in companies"
+msgstr "Usuari a les empreses"
+
+msgctxt "model:ir.rule.group,name:rule_group_reporting_region_companies"
+msgid "User in companies"
+msgstr "Usuari a les empreses"
+
+msgctxt "model:ir.rule.group,name:rule_group_sale_companies"
+msgid "User in companies"
+msgstr "Usuari a les empreses"
+
+msgctxt "model:ir.sequence,name:sequence_sale"
+msgid "Sale"
+msgstr "Venda"
+
+msgctxt "model:ir.sequence.type,name:sequence_type_sale"
+msgid "Sale"
+msgstr "Venda"
+
+msgctxt "model:ir.ui.menu,name:menu_configuration"
+msgid "Configuration"
+msgstr "Configuració"
+
+msgctxt "model:ir.ui.menu,name:menu_customer"
+msgid "Associated to Sales"
+msgstr "Amb vendes"
+
+msgctxt "model:ir.ui.menu,name:menu_product"
+msgid "Products"
+msgstr "Productes"
+
+msgctxt "model:ir.ui.menu,name:menu_reporting"
+msgid "Reporting"
+msgstr "Informes"
+
+msgctxt "model:ir.ui.menu,name:menu_reporting_sale"
+msgid "Sales"
+msgstr "Vendes"
+
+msgctxt "model:ir.ui.menu,name:menu_sale"
+msgid "Sales"
+msgstr "Vendes"
+
+msgctxt "model:ir.ui.menu,name:menu_sale_configuration"
+msgid "Configuration"
+msgstr "Configuració"
+
+msgctxt "model:ir.ui.menu,name:menu_sale_form"
+msgid "Sales"
+msgstr "Vendes"
+
+msgctxt "model:product.configuration.default_lead_time,name:"
+msgid "Product Default Lead Time"
+msgstr "Temps d'enviament per defecte del producte"
+
+msgctxt "model:product.sale.context,name:"
+msgid "Product Sale Context"
+msgstr "Context productes vendibles"
+
+msgctxt "model:res.group,name:group_sale"
+msgid "Sales"
+msgstr "Vendes"
+
+msgctxt "model:res.group,name:group_sale_admin"
+msgid "Sales Administrator"
+msgstr "Administració de vendes"
+
+msgctxt "model:sale.configuration,name:"
+msgid "Sale Configuration"
+msgstr "Configuració de les vendes"
+
+msgctxt "model:sale.configuration.sale_method,name:"
+msgid "Sale Configuration Sale Method"
+msgstr "Configuració del mètode de venda"
+
+msgctxt "model:sale.configuration.sequence,name:"
+msgid "Sale Configuration Sequence"
+msgstr "Configuració de les seqüencies de venda"
+
+msgctxt "model:sale.handle.invoice.exception.ask,name:"
+msgid "Handle Invoice Exception"
+msgstr "Gestiona excepció de factura"
+
+msgctxt "model:sale.handle.shipment.exception.ask,name:"
+msgid "Handle Shipment Exception"
+msgstr "Gestiona excepció d'enviament"
+
+msgctxt "model:sale.line,name:"
+msgid "Sale Line"
+msgstr "Línia de venda"
+
+msgctxt "model:sale.line-account.tax,name:"
+msgid "Sale Line - Tax"
+msgstr "Línia de venda - Impost"
+
+msgctxt "model:sale.line-ignored-stock.move,name:"
+msgid "Sale Line - Ignored Move"
+msgstr "Línia de venda - Moviment ignorat"
+
+msgctxt "model:sale.line-recreated-stock.move,name:"
+msgid "Sale Line - Recreated Move"
+msgstr "Línia de venda - Moviment recreat"
+
+msgctxt "model:sale.reporting.category,name:"
+msgid "Sale Reporting per Category"
+msgstr "Informe de vendes per categoria"
+
+msgctxt "model:sale.reporting.category.time_series,name:"
+msgid "Sale Reporting per Category"
+msgstr "Informe de vendes per categoria"
+
+msgctxt "model:sale.reporting.category.tree,name:"
+msgid "Sale Reporting per Category"
+msgstr "Informe de vendes per categoria"
+
+msgctxt "model:sale.reporting.context,name:"
+msgid "Sale Reporting Context"
+msgstr "Context informe de vendes"
+
+msgctxt "model:sale.reporting.country,name:"
+msgid "Sale Reporting per Country"
+msgstr "Informe de vendes per país"
+
+msgctxt "model:sale.reporting.country.subdivision,name:"
+msgid "Sale Reporting per Subdivision"
+msgstr "Informe de vendes per subdivisió"
+
+msgctxt "model:sale.reporting.country.subdivision.time_series,name:"
+msgid "Sale Reporting per Subdivision"
+msgstr "Informe de vendes per subdivisió"
+
+msgctxt "model:sale.reporting.country.time_series,name:"
+msgid "Sale Reporting per Country"
+msgstr "Informe de vendes per país"
+
+msgctxt "model:sale.reporting.customer,name:"
+msgid "Sale Reporting per Customer"
+msgstr "Informe de vendes per client"
+
+msgctxt "model:sale.reporting.customer.time_series,name:"
+msgid "Sale Reporting per Customer"
+msgstr "Informe de vendes per client"
+
+msgctxt "model:sale.reporting.product,name:"
+msgid "Sale Reporting per Product"
+msgstr "Informe de vendes per producte"
+
+msgctxt "model:sale.reporting.product.time_series,name:"
+msgid "Sale Reporting per Product"
+msgstr "Informe de vendes per producte"
+
+msgctxt "model:sale.reporting.region,name:"
+msgid "Sale Reporting per Region"
+msgstr "Informe de vendes per regió"
+
+msgctxt "model:sale.return_sale.start,name:"
+msgid "Return Sale"
+msgstr "Retorna la venda"
+
+msgctxt "model:sale.sale,name:"
+msgid "Sale"
+msgstr "Venda"
+
+msgctxt "model:sale.sale-ignored-account.invoice,name:"
+msgid "Sale - Ignored Invoice"
+msgstr "Venda - Factura ignorada"
+
+msgctxt "model:sale.sale-recreated-account.invoice,name:"
+msgid "Sale - Recreated Invoice"
+msgstr "Venda - Factura recreada"
+
+msgctxt "report:sale.sale:"
+msgid ":"
+msgstr ":"
+
+msgctxt "report:sale.sale:"
+msgid "Amount"
+msgstr "Import"
+
+msgctxt "report:sale.sale:"
+msgid "Date:"
+msgstr "Data:"
+
+msgctxt "report:sale.sale:"
+msgid "Description"
+msgstr "Descripció"
+
+msgctxt "report:sale.sale:"
+msgid "Description:"
+msgstr "Descripció:"
+
+msgctxt "report:sale.sale:"
+msgid "Draft Sale Order"
+msgstr "Venda esborrany"
+
+msgctxt "report:sale.sale:"
+msgid "Quantity"
+msgstr "Quantitat"
+
+msgctxt "report:sale.sale:"
+msgid "Quotation N°:"
+msgstr "Pressupost Núm.:"
+
+msgctxt "report:sale.sale:"
+msgid "Reference:"
+msgstr "Referència:"
+
+msgctxt "report:sale.sale:"
+msgid "Sale Order N°:"
+msgstr "Venta Núm.:"
+
+msgctxt "report:sale.sale:"
+msgid "Taxes"
+msgstr "Impostos"
+
+msgctxt "report:sale.sale:"
+msgid "Taxes:"
+msgstr "Impostos:"
+
+msgctxt "report:sale.sale:"
+msgid "Total (excl. taxes):"
+msgstr "Base imposable:"
+
+msgctxt "report:sale.sale:"
+msgid "Total:"
+msgstr "Total:"
+
+msgctxt "report:sale.sale:"
+msgid "Unit Price"
+msgstr "Preu unitari"
+
+msgctxt "selection:account.invoice,sale_exception_state:"
+msgid "Ignored"
+msgstr "Ignorat"
+
+msgctxt "selection:account.invoice,sale_exception_state:"
+msgid "Recreated"
+msgstr "Recreada"
+
+msgctxt "selection:sale.line,type:"
+msgid "Comment"
+msgstr "Comentari"
+
+msgctxt "selection:sale.line,type:"
+msgid "Line"
+msgstr "Línia"
+
+msgctxt "selection:sale.line,type:"
+msgid "Subtotal"
+msgstr "Subtotal"
+
+msgctxt "selection:sale.line,type:"
+msgid "Title"
+msgstr "Títol"
+
+msgctxt "selection:sale.reporting.context,period:"
+msgid "Day"
+msgstr "Dia"
+
+msgctxt "selection:sale.reporting.context,period:"
+msgid "Month"
+msgstr "Mes"
+
+msgctxt "selection:sale.reporting.context,period:"
+msgid "Year"
+msgstr "Any"
+
+msgctxt "selection:sale.sale,invoice_method:"
+msgid "Manual"
+msgstr "Manual"
+
+msgctxt "selection:sale.sale,invoice_method:"
+msgid "On Order Processed"
+msgstr "Al processar la comanda"
+
+msgctxt "selection:sale.sale,invoice_method:"
+msgid "On Shipment Sent"
+msgstr "Al enviar-ho"
+
+msgctxt "selection:sale.sale,invoice_state:"
+msgid "Exception"
+msgstr "Excepció"
+
+msgctxt "selection:sale.sale,invoice_state:"
+msgid "None"
+msgstr "Cap"
+
+msgctxt "selection:sale.sale,invoice_state:"
+msgid "Paid"
+msgstr "Pagada"
+
+msgctxt "selection:sale.sale,invoice_state:"
+msgid "Waiting"
+msgstr "En espera"
+
+msgctxt "selection:sale.sale,shipment_method:"
+msgid "Manual"
+msgstr "Manual"
+
+msgctxt "selection:sale.sale,shipment_method:"
+msgid "On Invoice Paid"
+msgstr "Al pagar la factura"
+
+msgctxt "selection:sale.sale,shipment_method:"
+msgid "On Order Processed"
+msgstr "Al processar la comanda"
+
+msgctxt "selection:sale.sale,shipment_state:"
+msgid "Exception"
+msgstr "Excepció"
+
+msgctxt "selection:sale.sale,shipment_state:"
+msgid "None"
+msgstr "Cap"
+
+msgctxt "selection:sale.sale,shipment_state:"
+msgid "Sent"
+msgstr "Enviada"
+
+msgctxt "selection:sale.sale,shipment_state:"
+msgid "Waiting"
+msgstr "En espera"
+
+msgctxt "selection:sale.sale,state:"
+msgid "Cancelled"
+msgstr "Cancel·lada"
+
+msgctxt "selection:sale.sale,state:"
+msgid "Confirmed"
+msgstr "Confirmada"
+
+msgctxt "selection:sale.sale,state:"
+msgid "Done"
+msgstr "Finalitzada"
+
+msgctxt "selection:sale.sale,state:"
+msgid "Draft"
+msgstr "Esborrany"
+
+msgctxt "selection:sale.sale,state:"
+msgid "Processing"
+msgstr "En procés"
+
+msgctxt "selection:sale.sale,state:"
+msgid "Quotation"
+msgstr "Pressupost"
+
+msgctxt "selection:stock.move,sale_exception_state:"
+msgid "Ignored"
+msgstr "Ignorat"
+
+msgctxt "selection:stock.move,sale_exception_state:"
+msgid "Recreated"
+msgstr "Recreat"
+
+msgctxt "view:party.party:"
+msgid "Sale"
+msgstr "Venda"
+
+msgctxt "view:product.template:"
+msgid "Customers"
+msgstr "Clients"
+
+msgctxt "view:sale.handle.invoice.exception.ask:"
+msgid "Choose invoices to recreate:"
+msgstr "Seleccioneu les factures a recrear:"
+
+msgctxt "view:sale.handle.shipment.exception.ask:"
+msgid "Choose move to recreate:"
+msgstr "Seleccioneu els moviments a recrear:"
+
+msgctxt "view:sale.line:"
+msgid "General"
+msgstr "General"
+
+msgctxt "view:sale.line:"
+msgid "Notes"
+msgstr "Notes"
+
+msgctxt "view:sale.line:"
+msgid "Taxes"
+msgstr "Impostos"
+
+msgctxt "view:sale.return_sale.start:"
+msgid "Are you sure to return these/this sale(s)?"
+msgstr "Esteu segur de retornar aquestes comandes de venda?"
+
+msgctxt "view:sale.sale:"
+msgid "Other Info"
+msgstr "Informació addicional"
+
+msgctxt "view:sale.sale:"
+msgid "Sale"
+msgstr "Venda"
+
+msgctxt "wizard_button:sale.handle.invoice.exception,ask,end:"
+msgid "Cancel"
+msgstr "Cancel·la"
+
+msgctxt "wizard_button:sale.handle.invoice.exception,ask,handle:"
+msgid "OK"
+msgstr "D'acord"
+
+msgctxt "wizard_button:sale.handle.shipment.exception,ask,end:"
+msgid "Cancel"
+msgstr "Cancel·la"
+
+msgctxt "wizard_button:sale.handle.shipment.exception,ask,handle:"
+msgid "OK"
+msgstr "D'acord"
+
+msgctxt "wizard_button:sale.modify_header,start,end:"
+msgid "Cancel"
+msgstr "Cancel·la"
+
+msgctxt "wizard_button:sale.modify_header,start,modify:"
+msgid "Modify"
+msgstr "Modifica"
+
+msgctxt "wizard_button:sale.return_sale,start,end:"
+msgid "Cancel"
+msgstr "Cancel·la"
+
+msgctxt "wizard_button:sale.return_sale,start,return_:"
+msgid "Return"
+msgstr "Retorna"
diff --git a/modules/sale/locale/cs.po b/modules/sale/locale/cs.po
new file mode 100644
index 0000000000..b1e0e41144
--- /dev/null
+++ b/modules/sale/locale/cs.po
@@ -0,0 +1,1384 @@
+#
+msgid ""
+msgstr "Content-Type: text/plain; charset=utf-8\n"
+
+msgctxt "field:account.invoice,sale_exception_state:"
+msgid "Exception State"
+msgstr ""
+
+#, fuzzy
+msgctxt "field:account.invoice,sales:"
+msgid "Sales"
+msgstr "Sales"
+
+msgctxt "field:product.configuration,default_lead_time:"
+msgid "Default Lead Time"
+msgstr ""
+
+msgctxt "field:product.configuration.default_lead_time,company:"
+msgid "Company"
+msgstr ""
+
+msgctxt "field:product.configuration.default_lead_time,default_lead_time:"
+msgid "Default Lead Time"
+msgstr ""
+
+msgctxt "field:product.product,lead_time:"
+msgid "Lead Time"
+msgstr ""
+
+msgctxt "field:product.product,salable:"
+msgid "Salable"
+msgstr ""
+
+msgctxt "field:product.product,sale_price_uom:"
+msgid "Sale Price"
+msgstr ""
+
+msgctxt "field:product.product,sale_uom:"
+msgid "Sale UOM"
+msgstr ""
+
+msgctxt "field:product.sale.context,company:"
+msgid "Company"
+msgstr ""
+
+msgctxt "field:product.sale.context,currency:"
+msgid "Currency"
+msgstr ""
+
+#, fuzzy
+msgctxt "field:product.sale.context,customer:"
+msgid "Customer"
+msgstr "Sales per Customer"
+
+msgctxt "field:product.sale.context,locations:"
+msgid "Warehouses"
+msgstr ""
+
+msgctxt "field:product.sale.context,quantity:"
+msgid "Quantity"
+msgstr ""
+
+#, fuzzy
+msgctxt "field:product.sale.context,sale_date:"
+msgid "Sale Date"
+msgstr "Sales"
+
+msgctxt "field:product.sale.context,stock_date_end:"
+msgid "Stock End Date"
+msgstr ""
+
+msgctxt "field:product.template,lead_time:"
+msgid "Lead Time"
+msgstr ""
+
+msgctxt "field:product.template,salable:"
+msgid "Salable"
+msgstr ""
+
+msgctxt "field:product.template,sale_uom:"
+msgid "Sale UOM"
+msgstr ""
+
+msgctxt "field:sale.configuration,sale_invoice_method:"
+msgid "Sale Invoice Method"
+msgstr ""
+
+msgctxt "field:sale.configuration,sale_process_after:"
+msgid "Process Sale after"
+msgstr ""
+
+msgctxt "field:sale.configuration,sale_sequence:"
+msgid "Sale Sequence"
+msgstr ""
+
+msgctxt "field:sale.configuration,sale_shipment_method:"
+msgid "Sale Shipment Method"
+msgstr ""
+
+msgctxt "field:sale.configuration.sale_method,sale_invoice_method:"
+msgid "Sale Invoice Method"
+msgstr ""
+
+msgctxt "field:sale.configuration.sale_method,sale_shipment_method:"
+msgid "Sale Shipment Method"
+msgstr ""
+
+msgctxt "field:sale.configuration.sequence,company:"
+msgid "Company"
+msgstr ""
+
+msgctxt "field:sale.configuration.sequence,sale_sequence:"
+msgid "Sale Sequence"
+msgstr ""
+
+msgctxt "field:sale.handle.invoice.exception.ask,domain_invoices:"
+msgid "Domain Invoices"
+msgstr ""
+
+msgctxt "field:sale.handle.invoice.exception.ask,recreate_invoices:"
+msgid "Recreate Invoices"
+msgstr ""
+
+msgctxt "field:sale.handle.shipment.exception.ask,domain_moves:"
+msgid "Domain Moves"
+msgstr ""
+
+msgctxt "field:sale.handle.shipment.exception.ask,recreate_moves:"
+msgid "Recreate Moves"
+msgstr ""
+
+msgctxt "field:sale.line,actual_quantity:"
+msgid "Actual Quantity"
+msgstr ""
+
+msgctxt "field:sale.line,amount:"
+msgid "Amount"
+msgstr ""
+
+msgctxt "field:sale.line,company:"
+msgid "Company"
+msgstr ""
+
+msgctxt "field:sale.line,currency:"
+msgid "Currency"
+msgstr ""
+
+msgctxt "field:sale.line,description:"
+msgid "Description"
+msgstr ""
+
+msgctxt "field:sale.line,from_location:"
+msgid "From Location"
+msgstr ""
+
+msgctxt "field:sale.line,invoice_lines:"
+msgid "Invoice Lines"
+msgstr ""
+
+msgctxt "field:sale.line,move_done:"
+msgid "Moves Done"
+msgstr ""
+
+msgctxt "field:sale.line,move_exception:"
+msgid "Moves Exception"
+msgstr ""
+
+msgctxt "field:sale.line,moves:"
+msgid "Moves"
+msgstr ""
+
+msgctxt "field:sale.line,moves_ignored:"
+msgid "Ignored Moves"
+msgstr ""
+
+msgctxt "field:sale.line,moves_recreated:"
+msgid "Recreated Moves"
+msgstr ""
+
+msgctxt "field:sale.line,note:"
+msgid "Note"
+msgstr ""
+
+msgctxt "field:sale.line,product:"
+msgid "Product"
+msgstr ""
+
+msgctxt "field:sale.line,product_uom_category:"
+msgid "Product Uom Category"
+msgstr ""
+
+msgctxt "field:sale.line,quantity:"
+msgid "Quantity"
+msgstr ""
+
+#, fuzzy
+msgctxt "field:sale.line,sale:"
+msgid "Sale"
+msgstr "Sales"
+
+msgctxt "field:sale.line,sale_state:"
+msgid "Sale State"
+msgstr ""
+
+msgctxt "field:sale.line,shipping_date:"
+msgid "Shipping Date"
+msgstr ""
+
+msgctxt "field:sale.line,summary:"
+msgid "Summary"
+msgstr ""
+
+msgctxt "field:sale.line,taxes:"
+msgid "Taxes"
+msgstr ""
+
+msgctxt "field:sale.line,to_location:"
+msgid "To Location"
+msgstr ""
+
+msgctxt "field:sale.line,type:"
+msgid "Type"
+msgstr ""
+
+msgctxt "field:sale.line,unit:"
+msgid "Unit"
+msgstr ""
+
+msgctxt "field:sale.line,unit_digits:"
+msgid "Unit Digits"
+msgstr ""
+
+msgctxt "field:sale.line,unit_price:"
+msgid "Unit Price"
+msgstr ""
+
+msgctxt "field:sale.line,warehouse:"
+msgid "Warehouse"
+msgstr ""
+
+msgctxt "field:sale.line-account.tax,line:"
+msgid "Sale Line"
+msgstr ""
+
+msgctxt "field:sale.line-account.tax,tax:"
+msgid "Tax"
+msgstr ""
+
+msgctxt "field:sale.line-ignored-stock.move,move:"
+msgid "Move"
+msgstr ""
+
+msgctxt "field:sale.line-ignored-stock.move,sale_line:"
+msgid "Sale Line"
+msgstr ""
+
+msgctxt "field:sale.line-recreated-stock.move,move:"
+msgid "Move"
+msgstr ""
+
+msgctxt "field:sale.line-recreated-stock.move,sale_line:"
+msgid "Sale Line"
+msgstr ""
+
+msgctxt "field:sale.reporting.category,category:"
+msgid "Category"
+msgstr ""
+
+msgctxt "field:sale.reporting.category,time_series:"
+msgid "Time Series"
+msgstr ""
+
+msgctxt "field:sale.reporting.category.time_series,category:"
+msgid "Category"
+msgstr ""
+
+msgctxt "field:sale.reporting.category.time_series,date:"
+msgid "Date"
+msgstr ""
+
+msgctxt "field:sale.reporting.category.tree,children:"
+msgid "Children"
+msgstr ""
+
+msgctxt "field:sale.reporting.category.tree,currency_digits:"
+msgid "Currency Digits"
+msgstr ""
+
+#, fuzzy
+msgctxt "field:sale.reporting.category.tree,name:"
+msgid "Name"
+msgstr "Namu"
+
+msgctxt "field:sale.reporting.category.tree,parent:"
+msgid "Parent"
+msgstr ""
+
+msgctxt "field:sale.reporting.category.tree,revenue:"
+msgid "Revenue"
+msgstr ""
+
+msgctxt "field:sale.reporting.context,company:"
+msgid "Company"
+msgstr ""
+
+msgctxt "field:sale.reporting.context,from_date:"
+msgid "From Date"
+msgstr ""
+
+msgctxt "field:sale.reporting.context,period:"
+msgid "Period"
+msgstr ""
+
+msgctxt "field:sale.reporting.context,to_date:"
+msgid "To Date"
+msgstr ""
+
+msgctxt "field:sale.reporting.context,warehouse:"
+msgid "Warehouse"
+msgstr ""
+
+msgctxt "field:sale.reporting.country,country:"
+msgid "Country"
+msgstr ""
+
+msgctxt "field:sale.reporting.country,time_series:"
+msgid "Time Series"
+msgstr ""
+
+msgctxt "field:sale.reporting.country.subdivision,country:"
+msgid "Country"
+msgstr ""
+
+msgctxt "field:sale.reporting.country.subdivision,subdivision:"
+msgid "Subdivision"
+msgstr ""
+
+msgctxt "field:sale.reporting.country.subdivision,time_series:"
+msgid "Time Series"
+msgstr ""
+
+msgctxt "field:sale.reporting.country.subdivision.time_series,country:"
+msgid "Country"
+msgstr ""
+
+msgctxt "field:sale.reporting.country.subdivision.time_series,date:"
+msgid "Date"
+msgstr ""
+
+msgctxt "field:sale.reporting.country.subdivision.time_series,subdivision:"
+msgid "Subdivision"
+msgstr ""
+
+msgctxt "field:sale.reporting.country.time_series,country:"
+msgid "Country"
+msgstr ""
+
+msgctxt "field:sale.reporting.country.time_series,date:"
+msgid "Date"
+msgstr ""
+
+msgctxt "field:sale.reporting.customer,customer:"
+msgid "Customer"
+msgstr ""
+
+msgctxt "field:sale.reporting.customer,time_series:"
+msgid "Time Series"
+msgstr ""
+
+msgctxt "field:sale.reporting.customer.time_series,customer:"
+msgid "Customer"
+msgstr ""
+
+msgctxt "field:sale.reporting.customer.time_series,date:"
+msgid "Date"
+msgstr ""
+
+msgctxt "field:sale.reporting.product,product:"
+msgid "Product"
+msgstr ""
+
+msgctxt "field:sale.reporting.product,time_series:"
+msgid "Time Series"
+msgstr ""
+
+msgctxt "field:sale.reporting.product.time_series,date:"
+msgid "Date"
+msgstr ""
+
+msgctxt "field:sale.reporting.product.time_series,product:"
+msgid "Product"
+msgstr ""
+
+msgctxt "field:sale.reporting.region,children:"
+msgid "Children"
+msgstr ""
+
+msgctxt "field:sale.reporting.region,parent:"
+msgid "Parent"
+msgstr ""
+
+msgctxt "field:sale.reporting.region,region:"
+msgid "Region"
+msgstr ""
+
+msgctxt "field:sale.sale,comment:"
+msgid "Comment"
+msgstr ""
+
+msgctxt "field:sale.sale,company:"
+msgid "Company"
+msgstr ""
+
+#, fuzzy
+msgctxt "field:sale.sale,confirmed_by:"
+msgid "Confirmed By"
+msgstr "Confirmed"
+
+msgctxt "field:sale.sale,contact:"
+msgid "Contact"
+msgstr ""
+
+msgctxt "field:sale.sale,currency:"
+msgid "Currency"
+msgstr ""
+
+msgctxt "field:sale.sale,currency_digits:"
+msgid "Currency Digits"
+msgstr ""
+
+msgctxt "field:sale.sale,description:"
+msgid "Description"
+msgstr ""
+
+msgctxt "field:sale.sale,invoice_address:"
+msgid "Invoice Address"
+msgstr ""
+
+msgctxt "field:sale.sale,invoice_method:"
+msgid "Invoice Method"
+msgstr ""
+
+#, fuzzy
+msgctxt "field:sale.sale,invoice_party:"
+msgid "Invoice Party"
+msgstr "Invoices"
+
+msgctxt "field:sale.sale,invoice_state:"
+msgid "Invoice State"
+msgstr ""
+
+#, fuzzy
+msgctxt "field:sale.sale,invoices:"
+msgid "Invoices"
+msgstr "Invoices"
+
+msgctxt "field:sale.sale,invoices_ignored:"
+msgid "Ignored Invoices"
+msgstr ""
+
+msgctxt "field:sale.sale,invoices_recreated:"
+msgid "Recreated Invoices"
+msgstr ""
+
+msgctxt "field:sale.sale,lines:"
+msgid "Lines"
+msgstr ""
+
+msgctxt "field:sale.sale,moves:"
+msgid "Moves"
+msgstr ""
+
+msgctxt "field:sale.sale,number:"
+msgid "Number"
+msgstr ""
+
+msgctxt "field:sale.sale,origin:"
+msgid "Origin"
+msgstr ""
+
+msgctxt "field:sale.sale,party:"
+msgid "Party"
+msgstr ""
+
+msgctxt "field:sale.sale,party_lang:"
+msgid "Party Language"
+msgstr ""
+
+msgctxt "field:sale.sale,payment_term:"
+msgid "Payment Term"
+msgstr ""
+
+#, fuzzy
+msgctxt "field:sale.sale,quoted_by:"
+msgid "Quoted By"
+msgstr "Quote"
+
+msgctxt "field:sale.sale,reference:"
+msgid "Reference"
+msgstr ""
+
+msgctxt "field:sale.sale,sale_date:"
+msgid "Sale Date"
+msgstr ""
+
+msgctxt "field:sale.sale,shipment_address:"
+msgid "Shipment Address"
+msgstr ""
+
+msgctxt "field:sale.sale,shipment_method:"
+msgid "Shipment Method"
+msgstr ""
+
+msgctxt "field:sale.sale,shipment_party:"
+msgid "Shipment Party"
+msgstr ""
+
+msgctxt "field:sale.sale,shipment_returns:"
+msgid "Shipment Returns"
+msgstr ""
+
+msgctxt "field:sale.sale,shipment_state:"
+msgid "Shipment State"
+msgstr ""
+
+#, fuzzy
+msgctxt "field:sale.sale,shipments:"
+msgid "Shipments"
+msgstr "Shipments"
+
+msgctxt "field:sale.sale,shipping_date:"
+msgid "Shipping Date"
+msgstr ""
+
+msgctxt "field:sale.sale,state:"
+msgid "State"
+msgstr ""
+
+msgctxt "field:sale.sale,tax_amount:"
+msgid "Tax"
+msgstr ""
+
+msgctxt "field:sale.sale,tax_amount_cache:"
+msgid "Tax Cache"
+msgstr ""
+
+msgctxt "field:sale.sale,total_amount:"
+msgid "Total"
+msgstr ""
+
+msgctxt "field:sale.sale,total_amount_cache:"
+msgid "Total Cache"
+msgstr ""
+
+msgctxt "field:sale.sale,untaxed_amount:"
+msgid "Untaxed"
+msgstr ""
+
+msgctxt "field:sale.sale,untaxed_amount_cache:"
+msgid "Untaxed Cache"
+msgstr ""
+
+msgctxt "field:sale.sale,warehouse:"
+msgid "Warehouse"
+msgstr ""
+
+#, fuzzy
+msgctxt "field:sale.sale-ignored-account.invoice,invoice:"
+msgid "Invoice"
+msgstr "Invoices"
+
+#, fuzzy
+msgctxt "field:sale.sale-ignored-account.invoice,sale:"
+msgid "Sale"
+msgstr "Sales"
+
+#, fuzzy
+msgctxt "field:sale.sale-recreated-account.invoice,invoice:"
+msgid "Invoice"
+msgstr "Invoices"
+
+#, fuzzy
+msgctxt "field:sale.sale-recreated-account.invoice,sale:"
+msgid "Sale"
+msgstr "Sales"
+
+#, fuzzy
+msgctxt "field:stock.move,sale:"
+msgid "Sale"
+msgstr "Sales"
+
+msgctxt "field:stock.move,sale_exception_state:"
+msgid "Exception State"
+msgstr ""
+
+msgctxt "help:product.configuration,default_lead_time:"
+msgid ""
+"The time from confirming the sales order to sending the products.\n"
+"Used for products without a lead time."
+msgstr ""
+
+msgctxt "help:product.product,lead_time:"
+msgid ""
+"The time from confirming the sales order to sending the products.\n"
+"If empty the default lead time from the configuration is used."
+msgstr ""
+
+msgctxt "help:product.template,lead_time:"
+msgid ""
+"The time from confirming the sales order to sending the products.\n"
+"If empty the default lead time from the configuration is used."
+msgstr ""
+
+msgctxt "help:sale.configuration,sale_process_after:"
+msgid ""
+"The grace period during which confirmed sale can still be reset to draft.\n"
+"Applied if a worker queue is activated."
+msgstr ""
+
+msgctxt "help:sale.handle.invoice.exception.ask,recreate_invoices:"
+msgid ""
+"The selected invoices will be recreated. The other ones will be ignored."
+msgstr ""
+
+msgctxt "help:sale.sale,shipping_date:"
+msgid "When the shipping of goods should start."
+msgstr ""
+
+msgctxt "model:ir.action,name:act_invoice_form"
+msgid "Invoices"
+msgstr "Invoices"
+
+msgctxt "model:ir.action,name:act_open_customer"
+msgid "Parties associated to Sales"
+msgstr "Parties associated to Sales"
+
+#, fuzzy
+msgctxt "model:ir.action,name:act_product"
+msgid "Products"
+msgstr "Sales per Product"
+
+msgctxt "model:ir.action,name:act_reporting_category"
+msgid "Sales per Category"
+msgstr "Sales per Category"
+
+msgctxt "model:ir.action,name:act_reporting_category_time_series"
+msgid "Sales per Category"
+msgstr "Sales per Category"
+
+msgctxt "model:ir.action,name:act_reporting_category_tree"
+msgid "Sales per Category"
+msgstr "Sales per Category"
+
+msgctxt "model:ir.action,name:act_reporting_country_subdivision_time_series"
+msgid "Sales per Subdivision"
+msgstr "Sales per Subdivision"
+
+msgctxt "model:ir.action,name:act_reporting_country_time_series"
+msgid "Sales per Country"
+msgstr "Sales per Country"
+
+msgctxt "model:ir.action,name:act_reporting_customer"
+msgid "Sales per Customer"
+msgstr "Sales per Customer"
+
+msgctxt "model:ir.action,name:act_reporting_customer_time_series"
+msgid "Sales per Customer"
+msgstr "Sales per Customer"
+
+msgctxt "model:ir.action,name:act_reporting_product"
+msgid "Sales per Product"
+msgstr "Sales per Product"
+
+msgctxt "model:ir.action,name:act_reporting_product_time_series"
+msgid "Sales per Product"
+msgstr "Sales per Product"
+
+msgctxt "model:ir.action,name:act_reporting_region"
+msgid "Sales per Region"
+msgstr "Sales per Region"
+
+msgctxt "model:ir.action,name:act_return_form"
+msgid "Returns"
+msgstr "Returns"
+
+#, fuzzy
+msgctxt "model:ir.action,name:act_sale_configuration_form"
+msgid "Configuration"
+msgstr "Configuration"
+
+msgctxt "model:ir.action,name:act_sale_form"
+msgid "Sales"
+msgstr "Sales"
+
+msgctxt "model:ir.action,name:act_sale_form2"
+msgid "Sales"
+msgstr "Sales"
+
+msgctxt "model:ir.action,name:act_sale_invoice_relate"
+msgid "Sales"
+msgstr "Sales"
+
+msgctxt "model:ir.action,name:act_sale_move_relate"
+msgid "Moves"
+msgstr ""
+
+msgctxt "model:ir.action,name:act_sale_shipment_returns_relate"
+msgid "Sales"
+msgstr "Sales"
+
+msgctxt "model:ir.action,name:act_sale_shipments_relate"
+msgid "Sales"
+msgstr "Sales"
+
+msgctxt "model:ir.action,name:act_shipment_form"
+msgid "Shipments"
+msgstr "Shipments"
+
+#, fuzzy
+msgctxt "model:ir.action,name:report_sale"
+msgid "Sale"
+msgstr "Sale"
+
+msgctxt "model:ir.action,name:wizard_invoice_handle_exception"
+msgid "Handle Invoice Exception"
+msgstr "Handle Invoice Exception"
+
+msgctxt "model:ir.action,name:wizard_modify_header"
+msgid "Modify Header"
+msgstr "Modify Header"
+
+msgctxt "model:ir.action,name:wizard_reporting_region_open"
+msgid "Open Region"
+msgstr "Open Region"
+
+msgctxt "model:ir.action,name:wizard_return_sale"
+msgid "Return Sale"
+msgstr "Return Sale"
+
+msgctxt "model:ir.action,name:wizard_shipment_handle_exception"
+msgid "Handle Shipment Exception"
+msgstr "Handle Shipment Exception"
+
+msgctxt "model:ir.action.act_window.domain,name:act_sale_form_domain_all"
+msgid "All"
+msgstr "All"
+
+#, fuzzy
+msgctxt ""
+"model:ir.action.act_window.domain,name:act_sale_form_domain_confirmed"
+msgid "Confirmed"
+msgstr "Confirmed"
+
+msgctxt "model:ir.action.act_window.domain,name:act_sale_form_domain_draft"
+msgid "Draft"
+msgstr "Draft"
+
+msgctxt ""
+"model:ir.action.act_window.domain,name:act_sale_form_domain_exception"
+msgid "Exception"
+msgstr ""
+
+msgctxt ""
+"model:ir.action.act_window.domain,name:act_sale_form_domain_processing"
+msgid "Processing"
+msgstr "Processing"
+
+msgctxt ""
+"model:ir.action.act_window.domain,name:act_sale_form_domain_quotation"
+msgid "Quotation"
+msgstr "Quotation"
+
+msgctxt "model:ir.message,text:msg_erase_party_pending_sale"
+msgid ""
+"You cannot erase party \"%(party)s\" while they have pending sales with "
+"company \"%(company)s\"."
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_sale_customer_location_required"
+msgid ""
+"To process sale \"%(sale)s\" you must set a customer location on party "
+"\"%(party)s\"."
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_sale_delete_cancel"
+msgid "To delete sale \"%(sale)s\" you must cancel it."
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_sale_invalid_method"
+msgid ""
+"You cannot use together invoice \"%(invoice_method)s\" and shipment "
+"\"%(shipment_method)s\" on sale \"%(sale)s\"."
+msgstr ""
+
+msgctxt ""
+"model:ir.message,text:msg_sale_invoice_address_required_for_quotation"
+msgid "To get a quote for sale \"%(sale)s\" you must enter an invoice address."
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_sale_invoice_reset_draft"
+msgid ""
+"You cannot reset invoice \"%(invoice)s\" to draft because it was generated "
+"by a sale."
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_sale_line_delete_cancel_draft"
+msgid ""
+"To delete line \"%(line)s\" you must cancel or reset to draft sale "
+"\"%(sale)s\"."
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_sale_missing_account_revenue"
+msgid "To invoice sale \"%(sale)s\" you must configure a default account revenue."
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_sale_modify_header_draft"
+msgid "To modify the header of sale \"%(sale)s\", it must be in \"draft\" state."
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_sale_move_reset_draft"
+msgid ""
+"You cannot reset move \"%(move)s\" to draft because it was generated by a "
+"sale."
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_sale_product_missing_account_revenue"
+msgid ""
+"To invoice sale \"%(sale)s\" you must define an account revenue for product "
+"\"%(product)s\"."
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_sale_reporting_company"
+msgid "Company"
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_sale_reporting_currency"
+msgid "Currency"
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_sale_reporting_currency_digits"
+msgid "Currency Digits"
+msgstr ""
+
+#, fuzzy
+msgctxt "model:ir.message,text:msg_sale_reporting_number"
+msgid "#"
+msgstr "#"
+
+msgctxt "model:ir.message,text:msg_sale_reporting_number_help"
+msgid "Number of sales"
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_sale_reporting_revenue"
+msgid "Revenue"
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_sale_reporting_revenue_trend"
+msgid "Revenue Trend"
+msgstr ""
+
+msgctxt ""
+"model:ir.message,text:msg_sale_shipment_address_required_for_quotation"
+msgid "To get a quote for sale \"%(sale)s\" you must enter a shipment address."
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_sale_warehouse_required_for_quotation"
+msgid "To get a quote for sale \"%(sale)s\" you must enter a warehouse."
+msgstr ""
+
+msgctxt "model:ir.model.button,string:sale_cancel_button"
+msgid "Cancel"
+msgstr "Cancel"
+
+msgctxt "model:ir.model.button,string:sale_confirm_button"
+msgid "Confirm"
+msgstr "Confirm"
+
+msgctxt "model:ir.model.button,string:sale_draft_button"
+msgid "Draft"
+msgstr "Draft"
+
+msgctxt "model:ir.model.button,string:sale_handle_invoice_exception_button"
+msgid "Handle Invoice Exception"
+msgstr "Handle Invoice Exception"
+
+msgctxt "model:ir.model.button,string:sale_handle_shipment_exception_button"
+msgid "Handle Shipment Exception"
+msgstr "Handle Shipment Exception"
+
+msgctxt "model:ir.model.button,string:sale_modify_header_button"
+msgid "Modify Header"
+msgstr "Modify Header"
+
+msgctxt "model:ir.model.button,string:sale_process_button"
+msgid "Process"
+msgstr "Process"
+
+msgctxt "model:ir.model.button,string:sale_quote_button"
+msgid "Quote"
+msgstr "Quote"
+
+msgctxt "model:ir.rule.group,name:rule_group_reporting_category_companies"
+msgid "User in companies"
+msgstr ""
+
+msgctxt ""
+"model:ir.rule.group,name:rule_group_reporting_category_time_series_companies"
+msgid "User in companies"
+msgstr ""
+
+msgctxt ""
+"model:ir.rule.group,name:rule_group_reporting_country_subdivision_time_series_companies"
+msgid "User in companies"
+msgstr ""
+
+msgctxt ""
+"model:ir.rule.group,name:rule_group_reporting_country_time_series_companies"
+msgid "User in companies"
+msgstr ""
+
+msgctxt "model:ir.rule.group,name:rule_group_reporting_customer_companies"
+msgid "User in companies"
+msgstr ""
+
+msgctxt ""
+"model:ir.rule.group,name:rule_group_reporting_customer_time_series_companies"
+msgid "User in companies"
+msgstr ""
+
+msgctxt "model:ir.rule.group,name:rule_group_reporting_product_companies"
+msgid "User in companies"
+msgstr ""
+
+msgctxt ""
+"model:ir.rule.group,name:rule_group_reporting_product_time_series_companies"
+msgid "User in companies"
+msgstr ""
+
+msgctxt "model:ir.rule.group,name:rule_group_reporting_region_companies"
+msgid "User in companies"
+msgstr ""
+
+msgctxt "model:ir.rule.group,name:rule_group_sale_companies"
+msgid "User in companies"
+msgstr ""
+
+#, fuzzy
+msgctxt "model:ir.sequence,name:sequence_sale"
+msgid "Sale"
+msgstr "Sale"
+
+#, fuzzy
+msgctxt "model:ir.sequence.type,name:sequence_type_sale"
+msgid "Sale"
+msgstr "Sale"
+
+msgctxt "model:ir.ui.menu,name:menu_configuration"
+msgid "Configuration"
+msgstr "Configuration"
+
+#, fuzzy
+msgctxt "model:ir.ui.menu,name:menu_customer"
+msgid "Associated to Sales"
+msgstr "Parties associated to Sales"
+
+#, fuzzy
+msgctxt "model:ir.ui.menu,name:menu_product"
+msgid "Products"
+msgstr "Sales per Product"
+
+msgctxt "model:ir.ui.menu,name:menu_reporting"
+msgid "Reporting"
+msgstr "Reporting"
+
+msgctxt "model:ir.ui.menu,name:menu_reporting_sale"
+msgid "Sales"
+msgstr "Sales"
+
+msgctxt "model:ir.ui.menu,name:menu_sale"
+msgid "Sales"
+msgstr "Sales"
+
+#, fuzzy
+msgctxt "model:ir.ui.menu,name:menu_sale_configuration"
+msgid "Configuration"
+msgstr "Configuration"
+
+msgctxt "model:ir.ui.menu,name:menu_sale_form"
+msgid "Sales"
+msgstr "Sales"
+
+msgctxt "model:product.configuration.default_lead_time,name:"
+msgid "Product Default Lead Time"
+msgstr ""
+
+msgctxt "model:product.sale.context,name:"
+msgid "Product Sale Context"
+msgstr ""
+
+msgctxt "model:res.group,name:group_sale"
+msgid "Sales"
+msgstr "Sales"
+
+msgctxt "model:res.group,name:group_sale_admin"
+msgid "Sales Administrator"
+msgstr "Sales Administrator"
+
+#, fuzzy
+msgctxt "model:sale.configuration,name:"
+msgid "Sale Configuration"
+msgstr "Sales Configuration"
+
+msgctxt "model:sale.configuration.sale_method,name:"
+msgid "Sale Configuration Sale Method"
+msgstr ""
+
+msgctxt "model:sale.configuration.sequence,name:"
+msgid "Sale Configuration Sequence"
+msgstr ""
+
+#, fuzzy
+msgctxt "model:sale.handle.invoice.exception.ask,name:"
+msgid "Handle Invoice Exception"
+msgstr "Handle Invoice Exception"
+
+#, fuzzy
+msgctxt "model:sale.handle.shipment.exception.ask,name:"
+msgid "Handle Shipment Exception"
+msgstr "Handle Shipment Exception"
+
+msgctxt "model:sale.line,name:"
+msgid "Sale Line"
+msgstr ""
+
+msgctxt "model:sale.line-account.tax,name:"
+msgid "Sale Line - Tax"
+msgstr ""
+
+msgctxt "model:sale.line-ignored-stock.move,name:"
+msgid "Sale Line - Ignored Move"
+msgstr ""
+
+msgctxt "model:sale.line-recreated-stock.move,name:"
+msgid "Sale Line - Recreated Move"
+msgstr ""
+
+msgctxt "model:sale.reporting.category,name:"
+msgid "Sale Reporting per Category"
+msgstr ""
+
+msgctxt "model:sale.reporting.category.time_series,name:"
+msgid "Sale Reporting per Category"
+msgstr ""
+
+msgctxt "model:sale.reporting.category.tree,name:"
+msgid "Sale Reporting per Category"
+msgstr ""
+
+msgctxt "model:sale.reporting.context,name:"
+msgid "Sale Reporting Context"
+msgstr ""
+
+msgctxt "model:sale.reporting.country,name:"
+msgid "Sale Reporting per Country"
+msgstr ""
+
+msgctxt "model:sale.reporting.country.subdivision,name:"
+msgid "Sale Reporting per Subdivision"
+msgstr ""
+
+msgctxt "model:sale.reporting.country.subdivision.time_series,name:"
+msgid "Sale Reporting per Subdivision"
+msgstr ""
+
+msgctxt "model:sale.reporting.country.time_series,name:"
+msgid "Sale Reporting per Country"
+msgstr ""
+
+msgctxt "model:sale.reporting.customer,name:"
+msgid "Sale Reporting per Customer"
+msgstr ""
+
+msgctxt "model:sale.reporting.customer.time_series,name:"
+msgid "Sale Reporting per Customer"
+msgstr ""
+
+msgctxt "model:sale.reporting.product,name:"
+msgid "Sale Reporting per Product"
+msgstr ""
+
+msgctxt "model:sale.reporting.product.time_series,name:"
+msgid "Sale Reporting per Product"
+msgstr ""
+
+msgctxt "model:sale.reporting.region,name:"
+msgid "Sale Reporting per Region"
+msgstr ""
+
+#, fuzzy
+msgctxt "model:sale.return_sale.start,name:"
+msgid "Return Sale"
+msgstr "Return Sale"
+
+#, fuzzy
+msgctxt "model:sale.sale,name:"
+msgid "Sale"
+msgstr "Sales"
+
+msgctxt "model:sale.sale-ignored-account.invoice,name:"
+msgid "Sale - Ignored Invoice"
+msgstr ""
+
+msgctxt "model:sale.sale-recreated-account.invoice,name:"
+msgid "Sale - Recreated Invoice"
+msgstr ""
+
+#, fuzzy
+msgctxt "report:sale.sale:"
+msgid ":"
+msgstr ":"
+
+msgctxt "report:sale.sale:"
+msgid "Amount"
+msgstr ""
+
+msgctxt "report:sale.sale:"
+msgid "Date:"
+msgstr ""
+
+msgctxt "report:sale.sale:"
+msgid "Description"
+msgstr ""
+
+msgctxt "report:sale.sale:"
+msgid "Description:"
+msgstr ""
+
+msgctxt "report:sale.sale:"
+msgid "Draft Sale Order"
+msgstr ""
+
+msgctxt "report:sale.sale:"
+msgid "Quantity"
+msgstr ""
+
+msgctxt "report:sale.sale:"
+msgid "Quotation N°:"
+msgstr ""
+
+msgctxt "report:sale.sale:"
+msgid "Reference:"
+msgstr ""
+
+msgctxt "report:sale.sale:"
+msgid "Sale Order N°:"
+msgstr ""
+
+msgctxt "report:sale.sale:"
+msgid "Taxes"
+msgstr ""
+
+msgctxt "report:sale.sale:"
+msgid "Taxes:"
+msgstr ""
+
+msgctxt "report:sale.sale:"
+msgid "Total (excl. taxes):"
+msgstr ""
+
+msgctxt "report:sale.sale:"
+msgid "Total:"
+msgstr ""
+
+msgctxt "report:sale.sale:"
+msgid "Unit Price"
+msgstr ""
+
+msgctxt "selection:account.invoice,sale_exception_state:"
+msgid "Ignored"
+msgstr ""
+
+msgctxt "selection:account.invoice,sale_exception_state:"
+msgid "Recreated"
+msgstr ""
+
+msgctxt "selection:sale.line,type:"
+msgid "Comment"
+msgstr ""
+
+msgctxt "selection:sale.line,type:"
+msgid "Line"
+msgstr ""
+
+msgctxt "selection:sale.line,type:"
+msgid "Subtotal"
+msgstr ""
+
+msgctxt "selection:sale.line,type:"
+msgid "Title"
+msgstr ""
+
+msgctxt "selection:sale.reporting.context,period:"
+msgid "Day"
+msgstr ""
+
+msgctxt "selection:sale.reporting.context,period:"
+msgid "Month"
+msgstr ""
+
+msgctxt "selection:sale.reporting.context,period:"
+msgid "Year"
+msgstr ""
+
+msgctxt "selection:sale.sale,invoice_method:"
+msgid "Manual"
+msgstr ""
+
+msgctxt "selection:sale.sale,invoice_method:"
+msgid "On Order Processed"
+msgstr ""
+
+msgctxt "selection:sale.sale,invoice_method:"
+msgid "On Shipment Sent"
+msgstr ""
+
+msgctxt "selection:sale.sale,invoice_state:"
+msgid "Exception"
+msgstr ""
+
+msgctxt "selection:sale.sale,invoice_state:"
+msgid "None"
+msgstr ""
+
+msgctxt "selection:sale.sale,invoice_state:"
+msgid "Paid"
+msgstr ""
+
+msgctxt "selection:sale.sale,invoice_state:"
+msgid "Waiting"
+msgstr ""
+
+msgctxt "selection:sale.sale,shipment_method:"
+msgid "Manual"
+msgstr ""
+
+msgctxt "selection:sale.sale,shipment_method:"
+msgid "On Invoice Paid"
+msgstr ""
+
+msgctxt "selection:sale.sale,shipment_method:"
+msgid "On Order Processed"
+msgstr ""
+
+msgctxt "selection:sale.sale,shipment_state:"
+msgid "Exception"
+msgstr ""
+
+msgctxt "selection:sale.sale,shipment_state:"
+msgid "None"
+msgstr ""
+
+msgctxt "selection:sale.sale,shipment_state:"
+msgid "Sent"
+msgstr ""
+
+msgctxt "selection:sale.sale,shipment_state:"
+msgid "Waiting"
+msgstr ""
+
+#, fuzzy
+msgctxt "selection:sale.sale,state:"
+msgid "Cancelled"
+msgstr "Cancel"
+
+#, fuzzy
+msgctxt "selection:sale.sale,state:"
+msgid "Confirmed"
+msgstr "Confirm"
+
+msgctxt "selection:sale.sale,state:"
+msgid "Done"
+msgstr ""
+
+#, fuzzy
+msgctxt "selection:sale.sale,state:"
+msgid "Draft"
+msgstr "Draft"
+
+#, fuzzy
+msgctxt "selection:sale.sale,state:"
+msgid "Processing"
+msgstr "Processing"
+
+#, fuzzy
+msgctxt "selection:sale.sale,state:"
+msgid "Quotation"
+msgstr "Quotation"
+
+msgctxt "selection:stock.move,sale_exception_state:"
+msgid "Ignored"
+msgstr ""
+
+msgctxt "selection:stock.move,sale_exception_state:"
+msgid "Recreated"
+msgstr ""
+
+#, fuzzy
+msgctxt "view:party.party:"
+msgid "Sale"
+msgstr "Sales"
+
+msgctxt "view:product.template:"
+msgid "Customers"
+msgstr ""
+
+msgctxt "view:sale.handle.invoice.exception.ask:"
+msgid "Choose invoices to recreate:"
+msgstr ""
+
+msgctxt "view:sale.handle.shipment.exception.ask:"
+msgid "Choose move to recreate:"
+msgstr ""
+
+msgctxt "view:sale.line:"
+msgid "General"
+msgstr ""
+
+msgctxt "view:sale.line:"
+msgid "Notes"
+msgstr ""
+
+msgctxt "view:sale.line:"
+msgid "Taxes"
+msgstr ""
+
+msgctxt "view:sale.return_sale.start:"
+msgid "Are you sure to return these/this sale(s)?"
+msgstr ""
+
+msgctxt "view:sale.sale:"
+msgid "Other Info"
+msgstr ""
+
+#, fuzzy
+msgctxt "view:sale.sale:"
+msgid "Sale"
+msgstr "Sales"
+
+#, fuzzy
+msgctxt "wizard_button:sale.handle.invoice.exception,ask,end:"
+msgid "Cancel"
+msgstr "Cancel"
+
+msgctxt "wizard_button:sale.handle.invoice.exception,ask,handle:"
+msgid "OK"
+msgstr ""
+
+#, fuzzy
+msgctxt "wizard_button:sale.handle.shipment.exception,ask,end:"
+msgid "Cancel"
+msgstr "Cancel"
+
+msgctxt "wizard_button:sale.handle.shipment.exception,ask,handle:"
+msgid "OK"
+msgstr ""
+
+#, fuzzy
+msgctxt "wizard_button:sale.modify_header,start,end:"
+msgid "Cancel"
+msgstr "Cancel"
+
+msgctxt "wizard_button:sale.modify_header,start,modify:"
+msgid "Modify"
+msgstr ""
+
+#, fuzzy
+msgctxt "wizard_button:sale.return_sale,start,end:"
+msgid "Cancel"
+msgstr "Cancel"
+
+#, fuzzy
+msgctxt "wizard_button:sale.return_sale,start,return_:"
+msgid "Return"
+msgstr "Returns"
diff --git a/modules/sale/locale/de.po b/modules/sale/locale/de.po
new file mode 100644
index 0000000000..ced150f11f
--- /dev/null
+++ b/modules/sale/locale/de.po
@@ -0,0 +1,1380 @@
+#
+msgid ""
+msgstr "Content-Type: text/plain; charset=utf-8\n"
+
+msgctxt "field:account.invoice,sale_exception_state:"
+msgid "Exception State"
+msgstr "Vorbehalt Status"
+
+msgctxt "field:account.invoice,sales:"
+msgid "Sales"
+msgstr "Verkäufe"
+
+msgctxt "field:product.configuration,default_lead_time:"
+msgid "Default Lead Time"
+msgstr "Standard Beschaffungszeit"
+
+msgctxt "field:product.configuration.default_lead_time,company:"
+msgid "Company"
+msgstr "Unternehmen"
+
+msgctxt "field:product.configuration.default_lead_time,default_lead_time:"
+msgid "Default Lead Time"
+msgstr "Standard Beschaffungszeit"
+
+msgctxt "field:product.product,lead_time:"
+msgid "Lead Time"
+msgstr "Beschaffungszeit"
+
+msgctxt "field:product.product,salable:"
+msgid "Salable"
+msgstr "Verkäuflich"
+
+msgctxt "field:product.product,sale_price_uom:"
+msgid "Sale Price"
+msgstr "Verkaufspreis"
+
+msgctxt "field:product.product,sale_uom:"
+msgid "Sale UOM"
+msgstr "Maßeinheit Verkauf"
+
+msgctxt "field:product.sale.context,company:"
+msgid "Company"
+msgstr "Unternehmen"
+
+msgctxt "field:product.sale.context,currency:"
+msgid "Currency"
+msgstr "Währung"
+
+msgctxt "field:product.sale.context,customer:"
+msgid "Customer"
+msgstr "Kunde"
+
+msgctxt "field:product.sale.context,locations:"
+msgid "Warehouses"
+msgstr "Warenlager"
+
+msgctxt "field:product.sale.context,quantity:"
+msgid "Quantity"
+msgstr "Menge"
+
+msgctxt "field:product.sale.context,sale_date:"
+msgid "Sale Date"
+msgstr "Verkaufsdatum"
+
+msgctxt "field:product.sale.context,stock_date_end:"
+msgid "Stock End Date"
+msgstr "Lager Enddatum"
+
+msgctxt "field:product.template,lead_time:"
+msgid "Lead Time"
+msgstr "Beschaffungszeit"
+
+msgctxt "field:product.template,salable:"
+msgid "Salable"
+msgstr "Verkäuflich"
+
+msgctxt "field:product.template,sale_uom:"
+msgid "Sale UOM"
+msgstr "Maßeinheit Verkauf"
+
+msgctxt "field:sale.configuration,sale_invoice_method:"
+msgid "Sale Invoice Method"
+msgstr "Rechnungsstellung Verkauf"
+
+msgctxt "field:sale.configuration,sale_process_after:"
+msgid "Process Sale after"
+msgstr "Verkauf ausführen nach"
+
+msgctxt "field:sale.configuration,sale_sequence:"
+msgid "Sale Sequence"
+msgstr "Nummernkreis Verkauf"
+
+msgctxt "field:sale.configuration,sale_shipment_method:"
+msgid "Sale Shipment Method"
+msgstr "Liefermethode Verkauf"
+
+msgctxt "field:sale.configuration.sale_method,sale_invoice_method:"
+msgid "Sale Invoice Method"
+msgstr "Rechnungsstellung Verkauf"
+
+msgctxt "field:sale.configuration.sale_method,sale_shipment_method:"
+msgid "Sale Shipment Method"
+msgstr "Liefermethode Verkauf"
+
+msgctxt "field:sale.configuration.sequence,company:"
+msgid "Company"
+msgstr "Unternehmen"
+
+msgctxt "field:sale.configuration.sequence,sale_sequence:"
+msgid "Sale Sequence"
+msgstr "Nummernkreis Verkauf"
+
+msgctxt "field:sale.handle.invoice.exception.ask,domain_invoices:"
+msgid "Domain Invoices"
+msgstr "Wertebereich Rechnungen (Domain)"
+
+msgctxt "field:sale.handle.invoice.exception.ask,recreate_invoices:"
+msgid "Recreate Invoices"
+msgstr "Rechnungen neu erstellen"
+
+msgctxt "field:sale.handle.shipment.exception.ask,domain_moves:"
+msgid "Domain Moves"
+msgstr "Wertebereich Lagerbewegungen (Domain)"
+
+msgctxt "field:sale.handle.shipment.exception.ask,recreate_moves:"
+msgid "Recreate Moves"
+msgstr "Lagerbewegungen neu erstellen"
+
+msgctxt "field:sale.line,actual_quantity:"
+msgid "Actual Quantity"
+msgstr "Tatsächliche Menge"
+
+msgctxt "field:sale.line,amount:"
+msgid "Amount"
+msgstr "Betrag"
+
+msgctxt "field:sale.line,company:"
+msgid "Company"
+msgstr "Unternehmen"
+
+msgctxt "field:sale.line,currency:"
+msgid "Currency"
+msgstr "Währung"
+
+msgctxt "field:sale.line,description:"
+msgid "Description"
+msgstr "Beschreibung"
+
+msgctxt "field:sale.line,from_location:"
+msgid "From Location"
+msgstr "Von Lagerort"
+
+msgctxt "field:sale.line,invoice_lines:"
+msgid "Invoice Lines"
+msgstr "Rechnungspositionen"
+
+msgctxt "field:sale.line,move_done:"
+msgid "Moves Done"
+msgstr "Erledigte Lagerbewegungen"
+
+msgctxt "field:sale.line,move_exception:"
+msgid "Moves Exception"
+msgstr "Lagerbewegungen Vorbehalt"
+
+msgctxt "field:sale.line,moves:"
+msgid "Moves"
+msgstr "Lagerbewegungen"
+
+msgctxt "field:sale.line,moves_ignored:"
+msgid "Ignored Moves"
+msgstr "Ignorierte Lagerbewegungen"
+
+msgctxt "field:sale.line,moves_recreated:"
+msgid "Recreated Moves"
+msgstr "Neu erstellte Lagerbewegungen"
+
+msgctxt "field:sale.line,note:"
+msgid "Note"
+msgstr "Notiz"
+
+msgctxt "field:sale.line,product:"
+msgid "Product"
+msgstr "Artikel"
+
+msgctxt "field:sale.line,product_uom_category:"
+msgid "Product Uom Category"
+msgstr "Maßeinheitenkategorie"
+
+msgctxt "field:sale.line,quantity:"
+msgid "Quantity"
+msgstr "Menge"
+
+msgctxt "field:sale.line,sale:"
+msgid "Sale"
+msgstr "Verkauf"
+
+msgctxt "field:sale.line,sale_state:"
+msgid "Sale State"
+msgstr "Verkaufsstatus"
+
+msgctxt "field:sale.line,shipping_date:"
+msgid "Shipping Date"
+msgstr "Lieferdatum"
+
+msgctxt "field:sale.line,summary:"
+msgid "Summary"
+msgstr "Kurzbeschreibung"
+
+msgctxt "field:sale.line,taxes:"
+msgid "Taxes"
+msgstr "Steuern"
+
+msgctxt "field:sale.line,to_location:"
+msgid "To Location"
+msgstr "Zu Lagerort"
+
+msgctxt "field:sale.line,type:"
+msgid "Type"
+msgstr "Typ"
+
+msgctxt "field:sale.line,unit:"
+msgid "Unit"
+msgstr "Einheit"
+
+msgctxt "field:sale.line,unit_digits:"
+msgid "Unit Digits"
+msgstr "Nachkommastellen"
+
+msgctxt "field:sale.line,unit_price:"
+msgid "Unit Price"
+msgstr "Einzelpreis"
+
+msgctxt "field:sale.line,warehouse:"
+msgid "Warehouse"
+msgstr "Warenlager"
+
+msgctxt "field:sale.line-account.tax,line:"
+msgid "Sale Line"
+msgstr "Verkaufsposition"
+
+msgctxt "field:sale.line-account.tax,tax:"
+msgid "Tax"
+msgstr "Steuer"
+
+msgctxt "field:sale.line-ignored-stock.move,move:"
+msgid "Move"
+msgstr "Lagerbewegung"
+
+msgctxt "field:sale.line-ignored-stock.move,sale_line:"
+msgid "Sale Line"
+msgstr "Verkaufsposition"
+
+msgctxt "field:sale.line-recreated-stock.move,move:"
+msgid "Move"
+msgstr "Lagerbewegung"
+
+msgctxt "field:sale.line-recreated-stock.move,sale_line:"
+msgid "Sale Line"
+msgstr "Verkaufsposition"
+
+msgctxt "field:sale.reporting.category,category:"
+msgid "Category"
+msgstr "Kategorie"
+
+msgctxt "field:sale.reporting.category,time_series:"
+msgid "Time Series"
+msgstr "Zeitliche Serien"
+
+msgctxt "field:sale.reporting.category.time_series,category:"
+msgid "Category"
+msgstr "Kategorie"
+
+msgctxt "field:sale.reporting.category.time_series,date:"
+msgid "Date"
+msgstr "Datum"
+
+msgctxt "field:sale.reporting.category.tree,children:"
+msgid "Children"
+msgstr "Untergeordnet (Kategorien)"
+
+msgctxt "field:sale.reporting.category.tree,currency_digits:"
+msgid "Currency Digits"
+msgstr "Nachkommastellen Währung"
+
+msgctxt "field:sale.reporting.category.tree,name:"
+msgid "Name"
+msgstr "Kategorie Name"
+
+msgctxt "field:sale.reporting.category.tree,parent:"
+msgid "Parent"
+msgstr "Übergeordnet (Kategorie)"
+
+msgctxt "field:sale.reporting.category.tree,revenue:"
+msgid "Revenue"
+msgstr "Ertrag"
+
+msgctxt "field:sale.reporting.context,company:"
+msgid "Company"
+msgstr "Unternehmen"
+
+msgctxt "field:sale.reporting.context,from_date:"
+msgid "From Date"
+msgstr "Von Datum"
+
+msgctxt "field:sale.reporting.context,period:"
+msgid "Period"
+msgstr "Verkaufszeitraum"
+
+msgctxt "field:sale.reporting.context,to_date:"
+msgid "To Date"
+msgstr "Bis Datum"
+
+msgctxt "field:sale.reporting.context,warehouse:"
+msgid "Warehouse"
+msgstr "Warenlager"
+
+msgctxt "field:sale.reporting.country,country:"
+msgid "Country"
+msgstr "Staat"
+
+msgctxt "field:sale.reporting.country,time_series:"
+msgid "Time Series"
+msgstr "Zeitliche Serien"
+
+msgctxt "field:sale.reporting.country.subdivision,country:"
+msgid "Country"
+msgstr "Staat"
+
+msgctxt "field:sale.reporting.country.subdivision,subdivision:"
+msgid "Subdivision"
+msgstr "Subnationale Einheit"
+
+msgctxt "field:sale.reporting.country.subdivision,time_series:"
+msgid "Time Series"
+msgstr "Zeitliche Serien"
+
+msgctxt "field:sale.reporting.country.subdivision.time_series,country:"
+msgid "Country"
+msgstr "Staat"
+
+msgctxt "field:sale.reporting.country.subdivision.time_series,date:"
+msgid "Date"
+msgstr "Datum"
+
+msgctxt "field:sale.reporting.country.subdivision.time_series,subdivision:"
+msgid "Subdivision"
+msgstr "Subnationale Einheit"
+
+msgctxt "field:sale.reporting.country.time_series,country:"
+msgid "Country"
+msgstr "Staat"
+
+msgctxt "field:sale.reporting.country.time_series,date:"
+msgid "Date"
+msgstr "Datum"
+
+msgctxt "field:sale.reporting.customer,customer:"
+msgid "Customer"
+msgstr "Kunde"
+
+msgctxt "field:sale.reporting.customer,time_series:"
+msgid "Time Series"
+msgstr "Zeitliche Serien"
+
+msgctxt "field:sale.reporting.customer.time_series,customer:"
+msgid "Customer"
+msgstr "Kunde"
+
+msgctxt "field:sale.reporting.customer.time_series,date:"
+msgid "Date"
+msgstr "Datum"
+
+msgctxt "field:sale.reporting.product,product:"
+msgid "Product"
+msgstr "Artikel"
+
+msgctxt "field:sale.reporting.product,time_series:"
+msgid "Time Series"
+msgstr "Zeitliche Serien"
+
+msgctxt "field:sale.reporting.product.time_series,date:"
+msgid "Date"
+msgstr "Datum"
+
+msgctxt "field:sale.reporting.product.time_series,product:"
+msgid "Product"
+msgstr "Artikel"
+
+msgctxt "field:sale.reporting.region,children:"
+msgid "Children"
+msgstr "Untergeordnet"
+
+msgctxt "field:sale.reporting.region,parent:"
+msgid "Parent"
+msgstr "Übergeordnet"
+
+msgctxt "field:sale.reporting.region,region:"
+msgid "Region"
+msgstr "Region"
+
+msgctxt "field:sale.sale,comment:"
+msgid "Comment"
+msgstr "Kommentar"
+
+msgctxt "field:sale.sale,company:"
+msgid "Company"
+msgstr "Unternehmen"
+
+msgctxt "field:sale.sale,confirmed_by:"
+msgid "Confirmed By"
+msgstr "Bestätigt von"
+
+msgctxt "field:sale.sale,contact:"
+msgid "Contact"
+msgstr "Kontakt"
+
+msgctxt "field:sale.sale,currency:"
+msgid "Currency"
+msgstr "Währung"
+
+msgctxt "field:sale.sale,currency_digits:"
+msgid "Currency Digits"
+msgstr "Nachkommastellen Währung"
+
+msgctxt "field:sale.sale,description:"
+msgid "Description"
+msgstr "Beschreibung"
+
+msgctxt "field:sale.sale,invoice_address:"
+msgid "Invoice Address"
+msgstr "Rechnungsadresse"
+
+msgctxt "field:sale.sale,invoice_method:"
+msgid "Invoice Method"
+msgstr "Rechnungsstellung"
+
+msgctxt "field:sale.sale,invoice_party:"
+msgid "Invoice Party"
+msgstr "Rechnungsempfänger"
+
+msgctxt "field:sale.sale,invoice_state:"
+msgid "Invoice State"
+msgstr "Rechnungsstatus"
+
+msgctxt "field:sale.sale,invoices:"
+msgid "Invoices"
+msgstr "Rechnungen"
+
+msgctxt "field:sale.sale,invoices_ignored:"
+msgid "Ignored Invoices"
+msgstr "Ignorierte Rechnungen"
+
+msgctxt "field:sale.sale,invoices_recreated:"
+msgid "Recreated Invoices"
+msgstr "Neu erstellte Rechnungen"
+
+msgctxt "field:sale.sale,lines:"
+msgid "Lines"
+msgstr "Positionen"
+
+msgctxt "field:sale.sale,moves:"
+msgid "Moves"
+msgstr "Lagerbewegungen"
+
+msgctxt "field:sale.sale,number:"
+msgid "Number"
+msgstr "Nummer"
+
+msgctxt "field:sale.sale,origin:"
+msgid "Origin"
+msgstr "Herkunft"
+
+msgctxt "field:sale.sale,party:"
+msgid "Party"
+msgstr "Partei"
+
+msgctxt "field:sale.sale,party_lang:"
+msgid "Party Language"
+msgstr "Sprache Partei"
+
+msgctxt "field:sale.sale,payment_term:"
+msgid "Payment Term"
+msgstr "Zahlungsbedingung"
+
+msgctxt "field:sale.sale,quoted_by:"
+msgid "Quoted By"
+msgstr "Angeboten von"
+
+msgctxt "field:sale.sale,reference:"
+msgid "Reference"
+msgstr "Referenz"
+
+msgctxt "field:sale.sale,sale_date:"
+msgid "Sale Date"
+msgstr "Verkaufsdatum"
+
+msgctxt "field:sale.sale,shipment_address:"
+msgid "Shipment Address"
+msgstr "Lieferadresse"
+
+msgctxt "field:sale.sale,shipment_method:"
+msgid "Shipment Method"
+msgstr "Liefermethode"
+
+msgctxt "field:sale.sale,shipment_party:"
+msgid "Shipment Party"
+msgstr "Lieferpartei"
+
+msgctxt "field:sale.sale,shipment_returns:"
+msgid "Shipment Returns"
+msgstr "Lieferposten Rücknahmen"
+
+msgctxt "field:sale.sale,shipment_state:"
+msgid "Shipment State"
+msgstr "Lieferstatus"
+
+msgctxt "field:sale.sale,shipments:"
+msgid "Shipments"
+msgstr "Lieferposten"
+
+msgctxt "field:sale.sale,shipping_date:"
+msgid "Shipping Date"
+msgstr "Lieferdatum"
+
+msgctxt "field:sale.sale,state:"
+msgid "State"
+msgstr "Status"
+
+msgctxt "field:sale.sale,tax_amount:"
+msgid "Tax"
+msgstr "Steuer"
+
+msgctxt "field:sale.sale,tax_amount_cache:"
+msgid "Tax Cache"
+msgstr "Steuer Cache"
+
+msgctxt "field:sale.sale,total_amount:"
+msgid "Total"
+msgstr "Gesamt"
+
+msgctxt "field:sale.sale,total_amount_cache:"
+msgid "Total Cache"
+msgstr "Gesamt Cache"
+
+msgctxt "field:sale.sale,untaxed_amount:"
+msgid "Untaxed"
+msgstr "Netto"
+
+msgctxt "field:sale.sale,untaxed_amount_cache:"
+msgid "Untaxed Cache"
+msgstr "Netto Cache"
+
+msgctxt "field:sale.sale,warehouse:"
+msgid "Warehouse"
+msgstr "Warenlager"
+
+msgctxt "field:sale.sale-ignored-account.invoice,invoice:"
+msgid "Invoice"
+msgstr "Rechnung"
+
+msgctxt "field:sale.sale-ignored-account.invoice,sale:"
+msgid "Sale"
+msgstr "Verkauf"
+
+msgctxt "field:sale.sale-recreated-account.invoice,invoice:"
+msgid "Invoice"
+msgstr "Rechnung"
+
+msgctxt "field:sale.sale-recreated-account.invoice,sale:"
+msgid "Sale"
+msgstr "Verkauf"
+
+msgctxt "field:stock.move,sale:"
+msgid "Sale"
+msgstr "Verkauf"
+
+msgctxt "field:stock.move,sale_exception_state:"
+msgid "Exception State"
+msgstr "Status Vorbehalt"
+
+msgctxt "help:product.configuration,default_lead_time:"
+msgid ""
+"The time from confirming the sales order to sending the products.\n"
+"Used for products without a lead time."
+msgstr ""
+"Die Zeit zwischen der Auftragsbestätigung und dem Versand der Ware.\n"
+"Wird für Artikel genutzt für die keine Beschaffungszeit erfasst wurde."
+
+msgctxt "help:product.product,lead_time:"
+msgid ""
+"The time from confirming the sales order to sending the products.\n"
+"If empty the default lead time from the configuration is used."
+msgstr ""
+"Die Zeit zwischen der Auftragsbestätigung und dem Versand der Ware.\n"
+"Wenn leer wird die Standardbeschaffungszeit aus den Einstellungen benutzt."
+
+msgctxt "help:product.template,lead_time:"
+msgid ""
+"The time from confirming the sales order to sending the products.\n"
+"If empty the default lead time from the configuration is used."
+msgstr ""
+"Die Zeit zwischen der Auftragsbestätigung und dem Versand der Ware.\n"
+"Wenn leer wird die Standardbeschaffungszeit aus den Einstellungen benutzt."
+
+msgctxt "help:sale.configuration,sale_process_after:"
+msgid ""
+"The grace period during which confirmed sale can still be reset to draft.\n"
+"Applied if a worker queue is activated."
+msgstr ""
+"Frist innerhalb der ein bestätigter Verkauf noch auf Entwurf zurückgesetzt werden kann.\n"
+"Wird nur angewandt, wenn die Warteschlange aktiviert ist."
+
+msgctxt "help:sale.handle.invoice.exception.ask,recreate_invoices:"
+msgid ""
+"The selected invoices will be recreated. The other ones will be ignored."
+msgstr ""
+"Die ausgewählten Rechnungen werden neu erstellt. Alle anderen werden "
+"ignoriert."
+
+msgctxt "help:sale.sale,shipping_date:"
+msgid "When the shipping of goods should start."
+msgstr "Tag an dem die Lieferung der Ware erfolgen soll."
+
+msgctxt "model:ir.action,name:act_invoice_form"
+msgid "Invoices"
+msgstr "Rechnungen"
+
+msgctxt "model:ir.action,name:act_open_customer"
+msgid "Parties associated to Sales"
+msgstr "Parteien mit Verkäufen"
+
+msgctxt "model:ir.action,name:act_product"
+msgid "Products"
+msgstr "Artikel"
+
+msgctxt "model:ir.action,name:act_reporting_category"
+msgid "Sales per Category"
+msgstr "Verkäufe pro Kategorie"
+
+msgctxt "model:ir.action,name:act_reporting_category_time_series"
+msgid "Sales per Category"
+msgstr "Verkäufe pro Kategorie"
+
+msgctxt "model:ir.action,name:act_reporting_category_tree"
+msgid "Sales per Category"
+msgstr "Verkäufe pro Kategorie"
+
+msgctxt "model:ir.action,name:act_reporting_country_subdivision_time_series"
+msgid "Sales per Subdivision"
+msgstr "Verkäufe pro subnationaler Einheit"
+
+msgctxt "model:ir.action,name:act_reporting_country_time_series"
+msgid "Sales per Country"
+msgstr "Verkäufe pro Land"
+
+msgctxt "model:ir.action,name:act_reporting_customer"
+msgid "Sales per Customer"
+msgstr "Verkäufe nach Kunde"
+
+msgctxt "model:ir.action,name:act_reporting_customer_time_series"
+msgid "Sales per Customer"
+msgstr "Verkäufe pro Kunde"
+
+msgctxt "model:ir.action,name:act_reporting_product"
+msgid "Sales per Product"
+msgstr "Verkäufe pro Artikel"
+
+msgctxt "model:ir.action,name:act_reporting_product_time_series"
+msgid "Sales per Product"
+msgstr "Verkäufe pro Artikel"
+
+msgctxt "model:ir.action,name:act_reporting_region"
+msgid "Sales per Region"
+msgstr "Verkäufe pro Region"
+
+msgctxt "model:ir.action,name:act_return_form"
+msgid "Returns"
+msgstr "Warenrücknahmen"
+
+msgctxt "model:ir.action,name:act_sale_configuration_form"
+msgid "Configuration"
+msgstr "Einstellungen"
+
+msgctxt "model:ir.action,name:act_sale_form"
+msgid "Sales"
+msgstr "Verkauf"
+
+msgctxt "model:ir.action,name:act_sale_form2"
+msgid "Sales"
+msgstr "Verkauf"
+
+msgctxt "model:ir.action,name:act_sale_invoice_relate"
+msgid "Sales"
+msgstr "Verkauf"
+
+msgctxt "model:ir.action,name:act_sale_move_relate"
+msgid "Moves"
+msgstr "Lagerbewegungen"
+
+msgctxt "model:ir.action,name:act_sale_shipment_returns_relate"
+msgid "Sales"
+msgstr "Verkäufe"
+
+msgctxt "model:ir.action,name:act_sale_shipments_relate"
+msgid "Sales"
+msgstr "Verkäufe"
+
+msgctxt "model:ir.action,name:act_shipment_form"
+msgid "Shipments"
+msgstr "Lieferungen"
+
+msgctxt "model:ir.action,name:report_sale"
+msgid "Sale"
+msgstr "Verkauf"
+
+msgctxt "model:ir.action,name:wizard_invoice_handle_exception"
+msgid "Handle Invoice Exception"
+msgstr "Rechnungsvorbehalt bearbeiten"
+
+msgctxt "model:ir.action,name:wizard_modify_header"
+msgid "Modify Header"
+msgstr "Kopfdaten bearbeiten"
+
+msgctxt "model:ir.action,name:wizard_reporting_region_open"
+msgid "Open Region"
+msgstr "Region öffnen"
+
+msgctxt "model:ir.action,name:wizard_return_sale"
+msgid "Return Sale"
+msgstr "Rücknahme erstellen"
+
+msgctxt "model:ir.action,name:wizard_shipment_handle_exception"
+msgid "Handle Shipment Exception"
+msgstr "Liefervorbehalt bearbeiten"
+
+msgctxt "model:ir.action.act_window.domain,name:act_sale_form_domain_all"
+msgid "All"
+msgstr "Alle"
+
+msgctxt ""
+"model:ir.action.act_window.domain,name:act_sale_form_domain_confirmed"
+msgid "Confirmed"
+msgstr "Bestätigt"
+
+msgctxt "model:ir.action.act_window.domain,name:act_sale_form_domain_draft"
+msgid "Draft"
+msgstr "Entwurf"
+
+msgctxt ""
+"model:ir.action.act_window.domain,name:act_sale_form_domain_exception"
+msgid "Exception"
+msgstr "Vorbehalt"
+
+msgctxt ""
+"model:ir.action.act_window.domain,name:act_sale_form_domain_processing"
+msgid "Processing"
+msgstr "In Ausführung"
+
+msgctxt ""
+"model:ir.action.act_window.domain,name:act_sale_form_domain_quotation"
+msgid "Quotation"
+msgstr "Angebot"
+
+msgctxt "model:ir.message,text:msg_erase_party_pending_sale"
+msgid ""
+"You cannot erase party \"%(party)s\" while they have pending sales with "
+"company \"%(company)s\"."
+msgstr ""
+"Die Partei \"%(party)s\" kann nicht gelöscht werden, solange es für sie "
+"unerledigte Verkäufe bei Unternehmen \"%(company)s\" gibt."
+
+msgctxt "model:ir.message,text:msg_sale_customer_location_required"
+msgid ""
+"To process sale \"%(sale)s\" you must set a customer location on party "
+"\"%(party)s\"."
+msgstr ""
+"Damit der Verkauf \"%(sale)s\" ausgeführt werden kann, muss ein Lagerort "
+"Kunde auf Partei \"%(party)s\" konfiguriert werden."
+
+msgctxt "model:ir.message,text:msg_sale_delete_cancel"
+msgid "To delete sale \"%(sale)s\" you must cancel it."
+msgstr ""
+"Damit der Verkauf \"%(sale)s\" gelöscht werden kann, muss er zuerst "
+"annulliert werden."
+
+msgctxt "model:ir.message,text:msg_sale_invalid_method"
+msgid ""
+"You cannot use together invoice \"%(invoice_method)s\" and shipment "
+"\"%(shipment_method)s\" on sale \"%(sale)s\"."
+msgstr ""
+"Die Kombination aus Rechnungsmethode \"%(invoice_method)s\" and "
+"Liefermethode \"%(shipment_method)s\" auf Verkauf \"%(sale)s\" kann nicht "
+"verwendet werden."
+
+msgctxt ""
+"model:ir.message,text:msg_sale_invoice_address_required_for_quotation"
+msgid "To get a quote for sale \"%(sale)s\" you must enter an invoice address."
+msgstr ""
+"Um ein Angebot für Verkauf \"%(sale)s\" erstellen zu können, muss zuerst "
+"eine Rechnungsadresse erfasst werden."
+
+msgctxt "model:ir.message,text:msg_sale_invoice_reset_draft"
+msgid ""
+"You cannot reset invoice \"%(invoice)s\" to draft because it was generated "
+"by a sale."
+msgstr ""
+"Die Rechnung \"%(invoice)s\" kann nicht auf den Entwurfsstatus zurückgesetzt"
+" werden, weil sie automatisch aus einem Verkauf erstellt wurde."
+
+msgctxt "model:ir.message,text:msg_sale_line_delete_cancel_draft"
+msgid ""
+"To delete line \"%(line)s\" you must cancel or reset to draft sale "
+"\"%(sale)s\"."
+msgstr ""
+"Damit die Verkaufsposition \"%(line)s\" gelöscht werden kann, muss zuerst "
+"der Verkauf \"%(sale)s\" annulliert oder auf den Entwurfsstatus "
+"zurückgesetzt werden."
+
+msgctxt "model:ir.message,text:msg_sale_missing_account_revenue"
+msgid "To invoice sale \"%(sale)s\" you must configure a default account revenue."
+msgstr ""
+"Damit der Verkauf \"%(sale)s\" fakturiert werden kann, muss zuerst ein "
+"Standardertragskonto konfiguriert werden."
+
+msgctxt "model:ir.message,text:msg_sale_modify_header_draft"
+msgid "To modify the header of sale \"%(sale)s\", it must be in \"draft\" state."
+msgstr ""
+"Damit die Kopfdaten des Verkaufs \"%(sale)s\" bearbeitet werden können, muss"
+" der Verkauf im Entwurfsstatus sein."
+
+msgctxt "model:ir.message,text:msg_sale_move_reset_draft"
+msgid ""
+"You cannot reset move \"%(move)s\" to draft because it was generated by a "
+"sale."
+msgstr ""
+"Der Buchungssatz \"%(move)s\" kann nicht in den Entwurfsstatus zurückgesetzt"
+" werden, weil er automatisch aus einem Verkauf erstellt wurde."
+
+msgctxt "model:ir.message,text:msg_sale_product_missing_account_revenue"
+msgid ""
+"To invoice sale \"%(sale)s\" you must define an account revenue for product "
+"\"%(product)s\"."
+msgstr ""
+"Damit der Verkauf \"%(sale)s\" fakturiert werden kann, muss zuerst ein "
+"Ertragskonto für den Artikel \"%(product)s\" konfiguriert werden."
+
+msgctxt "model:ir.message,text:msg_sale_reporting_company"
+msgid "Company"
+msgstr "Unternehmen"
+
+msgctxt "model:ir.message,text:msg_sale_reporting_currency"
+msgid "Currency"
+msgstr "Währung"
+
+msgctxt "model:ir.message,text:msg_sale_reporting_currency_digits"
+msgid "Currency Digits"
+msgstr "Nachkommastellen Währung"
+
+msgctxt "model:ir.message,text:msg_sale_reporting_number"
+msgid "#"
+msgstr "#"
+
+msgctxt "model:ir.message,text:msg_sale_reporting_number_help"
+msgid "Number of sales"
+msgstr "Anzahl der Verkäufe"
+
+msgctxt "model:ir.message,text:msg_sale_reporting_revenue"
+msgid "Revenue"
+msgstr "Ertrag"
+
+msgctxt "model:ir.message,text:msg_sale_reporting_revenue_trend"
+msgid "Revenue Trend"
+msgstr "Umsatztrend"
+
+msgctxt ""
+"model:ir.message,text:msg_sale_shipment_address_required_for_quotation"
+msgid "To get a quote for sale \"%(sale)s\" you must enter a shipment address."
+msgstr ""
+"Um ein Angebot für Verkauf \"%(sale)s\" erstellen zu können, muss zuerst "
+"eine Lieferadresse erfasst werden."
+
+msgctxt "model:ir.message,text:msg_sale_warehouse_required_for_quotation"
+msgid "To get a quote for sale \"%(sale)s\" you must enter a warehouse."
+msgstr ""
+"Um ein Angebot für Verkauf \"%(sale)s\" erstellen zu können, muss zuerst ein"
+" Warenlager erfasst werden."
+
+msgctxt "model:ir.model.button,string:sale_cancel_button"
+msgid "Cancel"
+msgstr "Annullieren"
+
+msgctxt "model:ir.model.button,string:sale_confirm_button"
+msgid "Confirm"
+msgstr "Bestätigen"
+
+msgctxt "model:ir.model.button,string:sale_draft_button"
+msgid "Draft"
+msgstr "Entwurf"
+
+msgctxt "model:ir.model.button,string:sale_handle_invoice_exception_button"
+msgid "Handle Invoice Exception"
+msgstr "Rechnungsvorbehalt bearbeiten"
+
+msgctxt "model:ir.model.button,string:sale_handle_shipment_exception_button"
+msgid "Handle Shipment Exception"
+msgstr "Liefervorbehalt bearbeiten"
+
+msgctxt "model:ir.model.button,string:sale_modify_header_button"
+msgid "Modify Header"
+msgstr "Kopfdaten bearbeiten"
+
+msgctxt "model:ir.model.button,string:sale_process_button"
+msgid "Process"
+msgstr "Ausführen"
+
+msgctxt "model:ir.model.button,string:sale_quote_button"
+msgid "Quote"
+msgstr "Angebot"
+
+msgctxt "model:ir.rule.group,name:rule_group_reporting_category_companies"
+msgid "User in companies"
+msgstr "Benutzer im Unternehmen"
+
+msgctxt ""
+"model:ir.rule.group,name:rule_group_reporting_category_time_series_companies"
+msgid "User in companies"
+msgstr "Benutzer im Unternehmen"
+
+msgctxt ""
+"model:ir.rule.group,name:rule_group_reporting_country_subdivision_time_series_companies"
+msgid "User in companies"
+msgstr "Benutzer im Unternehmen"
+
+msgctxt ""
+"model:ir.rule.group,name:rule_group_reporting_country_time_series_companies"
+msgid "User in companies"
+msgstr "Benutzer im Unternehmen"
+
+msgctxt "model:ir.rule.group,name:rule_group_reporting_customer_companies"
+msgid "User in companies"
+msgstr "Benutzer im Unternehmen"
+
+msgctxt ""
+"model:ir.rule.group,name:rule_group_reporting_customer_time_series_companies"
+msgid "User in companies"
+msgstr "Benutzer im Unternehmen"
+
+msgctxt "model:ir.rule.group,name:rule_group_reporting_product_companies"
+msgid "User in companies"
+msgstr "Benutzer im Unternehmen"
+
+msgctxt ""
+"model:ir.rule.group,name:rule_group_reporting_product_time_series_companies"
+msgid "User in companies"
+msgstr "Benutzer im Unternehmen"
+
+msgctxt "model:ir.rule.group,name:rule_group_reporting_region_companies"
+msgid "User in companies"
+msgstr "Benutzer im Unternehmen"
+
+msgctxt "model:ir.rule.group,name:rule_group_sale_companies"
+msgid "User in companies"
+msgstr "Benutzer im Unternehmen"
+
+msgctxt "model:ir.sequence,name:sequence_sale"
+msgid "Sale"
+msgstr "Verkauf"
+
+msgctxt "model:ir.sequence.type,name:sequence_type_sale"
+msgid "Sale"
+msgstr "Verkauf"
+
+msgctxt "model:ir.ui.menu,name:menu_configuration"
+msgid "Configuration"
+msgstr "Einstellungen"
+
+msgctxt "model:ir.ui.menu,name:menu_customer"
+msgid "Associated to Sales"
+msgstr "Parteien mit Verkäufen"
+
+msgctxt "model:ir.ui.menu,name:menu_product"
+msgid "Products"
+msgstr "Artikel"
+
+msgctxt "model:ir.ui.menu,name:menu_reporting"
+msgid "Reporting"
+msgstr "Auswertungen"
+
+msgctxt "model:ir.ui.menu,name:menu_reporting_sale"
+msgid "Sales"
+msgstr "Verkäufe"
+
+msgctxt "model:ir.ui.menu,name:menu_sale"
+msgid "Sales"
+msgstr "Verkauf"
+
+msgctxt "model:ir.ui.menu,name:menu_sale_configuration"
+msgid "Configuration"
+msgstr "Einstellungen"
+
+msgctxt "model:ir.ui.menu,name:menu_sale_form"
+msgid "Sales"
+msgstr "Verkauf"
+
+msgctxt "model:product.configuration.default_lead_time,name:"
+msgid "Product Default Lead Time"
+msgstr "Artikel Standardbeschaffungszeit"
+
+msgctxt "model:product.sale.context,name:"
+msgid "Product Sale Context"
+msgstr "Artikel Verkauf Kontext"
+
+msgctxt "model:res.group,name:group_sale"
+msgid "Sales"
+msgstr "Verkauf"
+
+msgctxt "model:res.group,name:group_sale_admin"
+msgid "Sales Administrator"
+msgstr "Verkauf Administration"
+
+msgctxt "model:sale.configuration,name:"
+msgid "Sale Configuration"
+msgstr "Einstellungen Verkauf"
+
+msgctxt "model:sale.configuration.sale_method,name:"
+msgid "Sale Configuration Sale Method"
+msgstr "Einstellungen Verkauf Verkaufsmethode"
+
+msgctxt "model:sale.configuration.sequence,name:"
+msgid "Sale Configuration Sequence"
+msgstr "Einstellungen Verkauf Nummernkreis"
+
+msgctxt "model:sale.handle.invoice.exception.ask,name:"
+msgid "Handle Invoice Exception"
+msgstr "Nachfrage Rechnungsvorbehalt"
+
+msgctxt "model:sale.handle.shipment.exception.ask,name:"
+msgid "Handle Shipment Exception"
+msgstr "Nachfrage Liefervorbehalt"
+
+msgctxt "model:sale.line,name:"
+msgid "Sale Line"
+msgstr "Verkaufsposition"
+
+msgctxt "model:sale.line-account.tax,name:"
+msgid "Sale Line - Tax"
+msgstr "Verkaufsposition - Steuer"
+
+msgctxt "model:sale.line-ignored-stock.move,name:"
+msgid "Sale Line - Ignored Move"
+msgstr "Verkaufsposition - Ignorierte Lagerbewegung"
+
+msgctxt "model:sale.line-recreated-stock.move,name:"
+msgid "Sale Line - Recreated Move"
+msgstr "Verkaufsposition - Neu erstellte Lagerbewegung"
+
+msgctxt "model:sale.reporting.category,name:"
+msgid "Sale Reporting per Category"
+msgstr "Verkaufsauswertung pro Kategorie"
+
+msgctxt "model:sale.reporting.category.time_series,name:"
+msgid "Sale Reporting per Category"
+msgstr "Verkaufsauswertung pro Kategorie"
+
+msgctxt "model:sale.reporting.category.tree,name:"
+msgid "Sale Reporting per Category"
+msgstr "Verkaufsauswertung pro Kategorie"
+
+msgctxt "model:sale.reporting.context,name:"
+msgid "Sale Reporting Context"
+msgstr "Kontext Verkaufsauswertung"
+
+msgctxt "model:sale.reporting.country,name:"
+msgid "Sale Reporting per Country"
+msgstr "Verkaufsauswertung pro Staat"
+
+msgctxt "model:sale.reporting.country.subdivision,name:"
+msgid "Sale Reporting per Subdivision"
+msgstr "Verkaufsauswertung pro subnationaler Einheit"
+
+msgctxt "model:sale.reporting.country.subdivision.time_series,name:"
+msgid "Sale Reporting per Subdivision"
+msgstr "Verkaufsauswertung pro subnationaler Einheit"
+
+msgctxt "model:sale.reporting.country.time_series,name:"
+msgid "Sale Reporting per Country"
+msgstr "Verkaufsauswertung pro Staat"
+
+msgctxt "model:sale.reporting.customer,name:"
+msgid "Sale Reporting per Customer"
+msgstr "Verkaufsauswertung pro Kunde"
+
+msgctxt "model:sale.reporting.customer.time_series,name:"
+msgid "Sale Reporting per Customer"
+msgstr "Verkaufsauswertung pro Kunde"
+
+msgctxt "model:sale.reporting.product,name:"
+msgid "Sale Reporting per Product"
+msgstr "Verkaufsauswertung pro Artikel"
+
+msgctxt "model:sale.reporting.product.time_series,name:"
+msgid "Sale Reporting per Product"
+msgstr "Verkaufsauswertung pro Artikel"
+
+msgctxt "model:sale.reporting.region,name:"
+msgid "Sale Reporting per Region"
+msgstr "Verkaufsauswertung pro subnationaler Einheit"
+
+msgctxt "model:sale.return_sale.start,name:"
+msgid "Return Sale"
+msgstr "Rücknahme erstellen"
+
+msgctxt "model:sale.sale,name:"
+msgid "Sale"
+msgstr "Verkauf"
+
+msgctxt "model:sale.sale-ignored-account.invoice,name:"
+msgid "Sale - Ignored Invoice"
+msgstr "Verkauf - Rechnung Ignoriert"
+
+msgctxt "model:sale.sale-recreated-account.invoice,name:"
+msgid "Sale - Recreated Invoice"
+msgstr "Verkauf - Neu erstellte Rechnung"
+
+msgctxt "report:sale.sale:"
+msgid ":"
+msgstr ":"
+
+msgctxt "report:sale.sale:"
+msgid "Amount"
+msgstr "Betrag"
+
+msgctxt "report:sale.sale:"
+msgid "Date:"
+msgstr "Datum:"
+
+msgctxt "report:sale.sale:"
+msgid "Description"
+msgstr "Beschreibung"
+
+msgctxt "report:sale.sale:"
+msgid "Description:"
+msgstr "Beschreibung:"
+
+msgctxt "report:sale.sale:"
+msgid "Draft Sale Order"
+msgstr "Auftrag (Entwurf)"
+
+msgctxt "report:sale.sale:"
+msgid "Quantity"
+msgstr "Menge"
+
+msgctxt "report:sale.sale:"
+msgid "Quotation N°:"
+msgstr "Angebot Nr.:"
+
+msgctxt "report:sale.sale:"
+msgid "Reference:"
+msgstr "Referenz:"
+
+msgctxt "report:sale.sale:"
+msgid "Sale Order N°:"
+msgstr "Auftrag Nr.:"
+
+msgctxt "report:sale.sale:"
+msgid "Taxes"
+msgstr "Steuern"
+
+msgctxt "report:sale.sale:"
+msgid "Taxes:"
+msgstr "Steuern:"
+
+msgctxt "report:sale.sale:"
+msgid "Total (excl. taxes):"
+msgstr "Netto:"
+
+msgctxt "report:sale.sale:"
+msgid "Total:"
+msgstr "Gesamt:"
+
+msgctxt "report:sale.sale:"
+msgid "Unit Price"
+msgstr "Einzelpreis"
+
+msgctxt "selection:account.invoice,sale_exception_state:"
+msgid "Ignored"
+msgstr "Ignoriert"
+
+msgctxt "selection:account.invoice,sale_exception_state:"
+msgid "Recreated"
+msgstr "Neu erstellt"
+
+msgctxt "selection:sale.line,type:"
+msgid "Comment"
+msgstr "Kommentar"
+
+msgctxt "selection:sale.line,type:"
+msgid "Line"
+msgstr "Position"
+
+msgctxt "selection:sale.line,type:"
+msgid "Subtotal"
+msgstr "Zwischensumme"
+
+msgctxt "selection:sale.line,type:"
+msgid "Title"
+msgstr "Überschrift"
+
+msgctxt "selection:sale.reporting.context,period:"
+msgid "Day"
+msgstr "Tag"
+
+msgctxt "selection:sale.reporting.context,period:"
+msgid "Month"
+msgstr "Monat"
+
+msgctxt "selection:sale.reporting.context,period:"
+msgid "Year"
+msgstr "Jahr"
+
+msgctxt "selection:sale.sale,invoice_method:"
+msgid "Manual"
+msgstr "Manuell"
+
+msgctxt "selection:sale.sale,invoice_method:"
+msgid "On Order Processed"
+msgstr "Bei Auftragsausführung"
+
+msgctxt "selection:sale.sale,invoice_method:"
+msgid "On Shipment Sent"
+msgstr "Bei Lieferung"
+
+msgctxt "selection:sale.sale,invoice_state:"
+msgid "Exception"
+msgstr "Vorbehalt"
+
+msgctxt "selection:sale.sale,invoice_state:"
+msgid "None"
+msgstr "Kein"
+
+msgctxt "selection:sale.sale,invoice_state:"
+msgid "Paid"
+msgstr "Bezahlt"
+
+msgctxt "selection:sale.sale,invoice_state:"
+msgid "Waiting"
+msgstr "Wartend"
+
+msgctxt "selection:sale.sale,shipment_method:"
+msgid "Manual"
+msgstr "Manuell"
+
+msgctxt "selection:sale.sale,shipment_method:"
+msgid "On Invoice Paid"
+msgstr "Bei Bezahlung"
+
+msgctxt "selection:sale.sale,shipment_method:"
+msgid "On Order Processed"
+msgstr "Bei Auftragsausführung"
+
+msgctxt "selection:sale.sale,shipment_state:"
+msgid "Exception"
+msgstr "Vorbehalt"
+
+msgctxt "selection:sale.sale,shipment_state:"
+msgid "None"
+msgstr "Kein"
+
+msgctxt "selection:sale.sale,shipment_state:"
+msgid "Sent"
+msgstr "Gesendet"
+
+msgctxt "selection:sale.sale,shipment_state:"
+msgid "Waiting"
+msgstr "Wartend"
+
+msgctxt "selection:sale.sale,state:"
+msgid "Cancelled"
+msgstr "Annulliert"
+
+msgctxt "selection:sale.sale,state:"
+msgid "Confirmed"
+msgstr "Beauftragt"
+
+msgctxt "selection:sale.sale,state:"
+msgid "Done"
+msgstr "Erledigt"
+
+msgctxt "selection:sale.sale,state:"
+msgid "Draft"
+msgstr "Entwurf"
+
+msgctxt "selection:sale.sale,state:"
+msgid "Processing"
+msgstr "In Ausführung"
+
+msgctxt "selection:sale.sale,state:"
+msgid "Quotation"
+msgstr "Angebot"
+
+msgctxt "selection:stock.move,sale_exception_state:"
+msgid "Ignored"
+msgstr "Ignoriert"
+
+msgctxt "selection:stock.move,sale_exception_state:"
+msgid "Recreated"
+msgstr "Neu erstellt"
+
+msgctxt "view:party.party:"
+msgid "Sale"
+msgstr "Verkauf"
+
+msgctxt "view:product.template:"
+msgid "Customers"
+msgstr "Kunden"
+
+msgctxt "view:sale.handle.invoice.exception.ask:"
+msgid "Choose invoices to recreate:"
+msgstr "Rechnungen zur Neuerstellung auswählen:"
+
+msgctxt "view:sale.handle.shipment.exception.ask:"
+msgid "Choose move to recreate:"
+msgstr "Lagerbewegungen zur Neuerstellung auswählen:"
+
+msgctxt "view:sale.line:"
+msgid "General"
+msgstr "Allgemein"
+
+msgctxt "view:sale.line:"
+msgid "Notes"
+msgstr "Notizen"
+
+msgctxt "view:sale.line:"
+msgid "Taxes"
+msgstr "Steuern"
+
+msgctxt "view:sale.return_sale.start:"
+msgid "Are you sure to return these/this sale(s)?"
+msgstr ""
+"Mit der Rücknahme dieses Verkaufs/dieser Verkäufe wirklich fortfahren?"
+
+msgctxt "view:sale.sale:"
+msgid "Other Info"
+msgstr "Sonstiges"
+
+msgctxt "view:sale.sale:"
+msgid "Sale"
+msgstr "Verkauf"
+
+msgctxt "wizard_button:sale.handle.invoice.exception,ask,end:"
+msgid "Cancel"
+msgstr "Abbrechen"
+
+msgctxt "wizard_button:sale.handle.invoice.exception,ask,handle:"
+msgid "OK"
+msgstr "OK"
+
+msgctxt "wizard_button:sale.handle.shipment.exception,ask,end:"
+msgid "Cancel"
+msgstr "Abbrechen"
+
+msgctxt "wizard_button:sale.handle.shipment.exception,ask,handle:"
+msgid "OK"
+msgstr "OK"
+
+msgctxt "wizard_button:sale.modify_header,start,end:"
+msgid "Cancel"
+msgstr "Abbrechen"
+
+msgctxt "wizard_button:sale.modify_header,start,modify:"
+msgid "Modify"
+msgstr "Ändern"
+
+msgctxt "wizard_button:sale.return_sale,start,end:"
+msgid "Cancel"
+msgstr "Abbrechen"
+
+msgctxt "wizard_button:sale.return_sale,start,return_:"
+msgid "Return"
+msgstr "Rücknahme durchführen"
diff --git a/modules/sale/locale/es.po b/modules/sale/locale/es.po
new file mode 100644
index 0000000000..c66019229d
--- /dev/null
+++ b/modules/sale/locale/es.po
@@ -0,0 +1,1374 @@
+#
+msgid ""
+msgstr "Content-Type: text/plain; charset=utf-8\n"
+
+msgctxt "field:account.invoice,sale_exception_state:"
+msgid "Exception State"
+msgstr "Estado excepción"
+
+msgctxt "field:account.invoice,sales:"
+msgid "Sales"
+msgstr "Ventas"
+
+msgctxt "field:product.configuration,default_lead_time:"
+msgid "Default Lead Time"
+msgstr "Tiempo de espera por defecto"
+
+msgctxt "field:product.configuration.default_lead_time,company:"
+msgid "Company"
+msgstr "Empresa"
+
+msgctxt "field:product.configuration.default_lead_time,default_lead_time:"
+msgid "Default Lead Time"
+msgstr "Tiempo de espera por defecto"
+
+msgctxt "field:product.product,lead_time:"
+msgid "Lead Time"
+msgstr "Tiempo de espera"
+
+msgctxt "field:product.product,salable:"
+msgid "Salable"
+msgstr "Vendible"
+
+msgctxt "field:product.product,sale_price_uom:"
+msgid "Sale Price"
+msgstr "Precio de venta"
+
+msgctxt "field:product.product,sale_uom:"
+msgid "Sale UOM"
+msgstr "UdM de venta"
+
+msgctxt "field:product.sale.context,company:"
+msgid "Company"
+msgstr "Empresa"
+
+msgctxt "field:product.sale.context,currency:"
+msgid "Currency"
+msgstr "Moneda"
+
+msgctxt "field:product.sale.context,customer:"
+msgid "Customer"
+msgstr "Cliente"
+
+msgctxt "field:product.sale.context,locations:"
+msgid "Warehouses"
+msgstr "Almacenes"
+
+msgctxt "field:product.sale.context,quantity:"
+msgid "Quantity"
+msgstr "Cantidad"
+
+msgctxt "field:product.sale.context,sale_date:"
+msgid "Sale Date"
+msgstr "Fecha venta"
+
+msgctxt "field:product.sale.context,stock_date_end:"
+msgid "Stock End Date"
+msgstr "Fecha fina existèncias"
+
+msgctxt "field:product.template,lead_time:"
+msgid "Lead Time"
+msgstr "Tiempo de espera"
+
+msgctxt "field:product.template,salable:"
+msgid "Salable"
+msgstr "Vendible"
+
+msgctxt "field:product.template,sale_uom:"
+msgid "Sale UOM"
+msgstr "UdM de venta"
+
+msgctxt "field:sale.configuration,sale_invoice_method:"
+msgid "Sale Invoice Method"
+msgstr "Método de facturación"
+
+msgctxt "field:sale.configuration,sale_process_after:"
+msgid "Process Sale after"
+msgstr "Procesar las ventas después de"
+
+msgctxt "field:sale.configuration,sale_sequence:"
+msgid "Sale Sequence"
+msgstr "Secuencia de venta"
+
+msgctxt "field:sale.configuration,sale_shipment_method:"
+msgid "Sale Shipment Method"
+msgstr "Método de envío"
+
+msgctxt "field:sale.configuration.sale_method,sale_invoice_method:"
+msgid "Sale Invoice Method"
+msgstr "Método de facturación"
+
+msgctxt "field:sale.configuration.sale_method,sale_shipment_method:"
+msgid "Sale Shipment Method"
+msgstr "Método de envío"
+
+msgctxt "field:sale.configuration.sequence,company:"
+msgid "Company"
+msgstr "Empresa"
+
+msgctxt "field:sale.configuration.sequence,sale_sequence:"
+msgid "Sale Sequence"
+msgstr "Secuencia de venta"
+
+msgctxt "field:sale.handle.invoice.exception.ask,domain_invoices:"
+msgid "Domain Invoices"
+msgstr "Dominio de facturas"
+
+msgctxt "field:sale.handle.invoice.exception.ask,recreate_invoices:"
+msgid "Recreate Invoices"
+msgstr "Recrear facturas"
+
+msgctxt "field:sale.handle.shipment.exception.ask,domain_moves:"
+msgid "Domain Moves"
+msgstr "Dominio de movimientos"
+
+msgctxt "field:sale.handle.shipment.exception.ask,recreate_moves:"
+msgid "Recreate Moves"
+msgstr "Recrear movimientos"
+
+msgctxt "field:sale.line,actual_quantity:"
+msgid "Actual Quantity"
+msgstr "Cantidad actual"
+
+msgctxt "field:sale.line,amount:"
+msgid "Amount"
+msgstr "Importe"
+
+msgctxt "field:sale.line,company:"
+msgid "Company"
+msgstr "Empresa"
+
+msgctxt "field:sale.line,currency:"
+msgid "Currency"
+msgstr "Moneda"
+
+msgctxt "field:sale.line,description:"
+msgid "Description"
+msgstr "Descripción"
+
+msgctxt "field:sale.line,from_location:"
+msgid "From Location"
+msgstr "Desde ubicación"
+
+msgctxt "field:sale.line,invoice_lines:"
+msgid "Invoice Lines"
+msgstr "Líneas de factura"
+
+msgctxt "field:sale.line,move_done:"
+msgid "Moves Done"
+msgstr "Movimientos finalizados"
+
+msgctxt "field:sale.line,move_exception:"
+msgid "Moves Exception"
+msgstr "Movimientos en excepción"
+
+msgctxt "field:sale.line,moves:"
+msgid "Moves"
+msgstr "Movimientos"
+
+msgctxt "field:sale.line,moves_ignored:"
+msgid "Ignored Moves"
+msgstr "Movimientos ignorados"
+
+msgctxt "field:sale.line,moves_recreated:"
+msgid "Recreated Moves"
+msgstr "Movimientos recreados"
+
+msgctxt "field:sale.line,note:"
+msgid "Note"
+msgstr "Nota"
+
+msgctxt "field:sale.line,product:"
+msgid "Product"
+msgstr "Producto"
+
+msgctxt "field:sale.line,product_uom_category:"
+msgid "Product Uom Category"
+msgstr "Categoría UdM del producto"
+
+msgctxt "field:sale.line,quantity:"
+msgid "Quantity"
+msgstr "Cantidad"
+
+msgctxt "field:sale.line,sale:"
+msgid "Sale"
+msgstr "Venta"
+
+msgctxt "field:sale.line,sale_state:"
+msgid "Sale State"
+msgstr "Estado de venta"
+
+msgctxt "field:sale.line,shipping_date:"
+msgid "Shipping Date"
+msgstr "Fecha envío"
+
+msgctxt "field:sale.line,summary:"
+msgid "Summary"
+msgstr "Resumen"
+
+msgctxt "field:sale.line,taxes:"
+msgid "Taxes"
+msgstr "Impuestos"
+
+msgctxt "field:sale.line,to_location:"
+msgid "To Location"
+msgstr "A ubicación"
+
+msgctxt "field:sale.line,type:"
+msgid "Type"
+msgstr "Tipo"
+
+msgctxt "field:sale.line,unit:"
+msgid "Unit"
+msgstr "Unidad"
+
+msgctxt "field:sale.line,unit_digits:"
+msgid "Unit Digits"
+msgstr "Dígitos de la unidad"
+
+msgctxt "field:sale.line,unit_price:"
+msgid "Unit Price"
+msgstr "Precio unitario"
+
+msgctxt "field:sale.line,warehouse:"
+msgid "Warehouse"
+msgstr "Almacén"
+
+msgctxt "field:sale.line-account.tax,line:"
+msgid "Sale Line"
+msgstr "Línea de venta"
+
+msgctxt "field:sale.line-account.tax,tax:"
+msgid "Tax"
+msgstr "Impuesto"
+
+msgctxt "field:sale.line-ignored-stock.move,move:"
+msgid "Move"
+msgstr "Movimiento"
+
+msgctxt "field:sale.line-ignored-stock.move,sale_line:"
+msgid "Sale Line"
+msgstr "Línea de venta"
+
+msgctxt "field:sale.line-recreated-stock.move,move:"
+msgid "Move"
+msgstr "Movimiento"
+
+msgctxt "field:sale.line-recreated-stock.move,sale_line:"
+msgid "Sale Line"
+msgstr "Línea de venta"
+
+msgctxt "field:sale.reporting.category,category:"
+msgid "Category"
+msgstr "Categoría"
+
+msgctxt "field:sale.reporting.category,time_series:"
+msgid "Time Series"
+msgstr "Series temporales"
+
+msgctxt "field:sale.reporting.category.time_series,category:"
+msgid "Category"
+msgstr "Categoría"
+
+msgctxt "field:sale.reporting.category.time_series,date:"
+msgid "Date"
+msgstr "Fecha"
+
+msgctxt "field:sale.reporting.category.tree,children:"
+msgid "Children"
+msgstr "Hijos"
+
+msgctxt "field:sale.reporting.category.tree,currency_digits:"
+msgid "Currency Digits"
+msgstr "Decimales de la moneda"
+
+msgctxt "field:sale.reporting.category.tree,name:"
+msgid "Name"
+msgstr "Nombre"
+
+msgctxt "field:sale.reporting.category.tree,parent:"
+msgid "Parent"
+msgstr "Padre"
+
+msgctxt "field:sale.reporting.category.tree,revenue:"
+msgid "Revenue"
+msgstr "Ingresos"
+
+msgctxt "field:sale.reporting.context,company:"
+msgid "Company"
+msgstr "Empresa"
+
+msgctxt "field:sale.reporting.context,from_date:"
+msgid "From Date"
+msgstr "Desde la fecha"
+
+msgctxt "field:sale.reporting.context,period:"
+msgid "Period"
+msgstr "Período"
+
+msgctxt "field:sale.reporting.context,to_date:"
+msgid "To Date"
+msgstr "Hasta la fecha"
+
+msgctxt "field:sale.reporting.context,warehouse:"
+msgid "Warehouse"
+msgstr "Almacén"
+
+msgctxt "field:sale.reporting.country,country:"
+msgid "Country"
+msgstr "País"
+
+msgctxt "field:sale.reporting.country,time_series:"
+msgid "Time Series"
+msgstr "Series temporales"
+
+msgctxt "field:sale.reporting.country.subdivision,country:"
+msgid "Country"
+msgstr "País"
+
+msgctxt "field:sale.reporting.country.subdivision,subdivision:"
+msgid "Subdivision"
+msgstr "Provincia"
+
+msgctxt "field:sale.reporting.country.subdivision,time_series:"
+msgid "Time Series"
+msgstr "Series temporales"
+
+msgctxt "field:sale.reporting.country.subdivision.time_series,country:"
+msgid "Country"
+msgstr "País"
+
+msgctxt "field:sale.reporting.country.subdivision.time_series,date:"
+msgid "Date"
+msgstr "Fecha"
+
+msgctxt "field:sale.reporting.country.subdivision.time_series,subdivision:"
+msgid "Subdivision"
+msgstr "Subdivisión"
+
+msgctxt "field:sale.reporting.country.time_series,country:"
+msgid "Country"
+msgstr "País"
+
+msgctxt "field:sale.reporting.country.time_series,date:"
+msgid "Date"
+msgstr "Fecha"
+
+msgctxt "field:sale.reporting.customer,customer:"
+msgid "Customer"
+msgstr "Cliente"
+
+msgctxt "field:sale.reporting.customer,time_series:"
+msgid "Time Series"
+msgstr "Series temporales"
+
+msgctxt "field:sale.reporting.customer.time_series,customer:"
+msgid "Customer"
+msgstr "Cliente"
+
+msgctxt "field:sale.reporting.customer.time_series,date:"
+msgid "Date"
+msgstr "Fecha"
+
+msgctxt "field:sale.reporting.product,product:"
+msgid "Product"
+msgstr "Producto"
+
+msgctxt "field:sale.reporting.product,time_series:"
+msgid "Time Series"
+msgstr "Series temporales"
+
+msgctxt "field:sale.reporting.product.time_series,date:"
+msgid "Date"
+msgstr "Fecha"
+
+msgctxt "field:sale.reporting.product.time_series,product:"
+msgid "Product"
+msgstr "Producto"
+
+msgctxt "field:sale.reporting.region,children:"
+msgid "Children"
+msgstr "Hijos"
+
+msgctxt "field:sale.reporting.region,parent:"
+msgid "Parent"
+msgstr "Padre"
+
+msgctxt "field:sale.reporting.region,region:"
+msgid "Region"
+msgstr "Región"
+
+msgctxt "field:sale.sale,comment:"
+msgid "Comment"
+msgstr "Comentario"
+
+msgctxt "field:sale.sale,company:"
+msgid "Company"
+msgstr "Empresa"
+
+msgctxt "field:sale.sale,confirmed_by:"
+msgid "Confirmed By"
+msgstr "Confirmada por"
+
+msgctxt "field:sale.sale,contact:"
+msgid "Contact"
+msgstr "Contacto"
+
+msgctxt "field:sale.sale,currency:"
+msgid "Currency"
+msgstr "Moneda"
+
+msgctxt "field:sale.sale,currency_digits:"
+msgid "Currency Digits"
+msgstr "Decimales de la moneda"
+
+msgctxt "field:sale.sale,description:"
+msgid "Description"
+msgstr "Descripción"
+
+msgctxt "field:sale.sale,invoice_address:"
+msgid "Invoice Address"
+msgstr "Dirección de facturación"
+
+msgctxt "field:sale.sale,invoice_method:"
+msgid "Invoice Method"
+msgstr "Método de facturación"
+
+msgctxt "field:sale.sale,invoice_party:"
+msgid "Invoice Party"
+msgstr "Tercero de la factura"
+
+msgctxt "field:sale.sale,invoice_state:"
+msgid "Invoice State"
+msgstr "Estado de la factura"
+
+msgctxt "field:sale.sale,invoices:"
+msgid "Invoices"
+msgstr "Facturas"
+
+msgctxt "field:sale.sale,invoices_ignored:"
+msgid "Ignored Invoices"
+msgstr "Facturas ignoradas"
+
+msgctxt "field:sale.sale,invoices_recreated:"
+msgid "Recreated Invoices"
+msgstr "Facturas recreadas"
+
+msgctxt "field:sale.sale,lines:"
+msgid "Lines"
+msgstr "Líneas"
+
+msgctxt "field:sale.sale,moves:"
+msgid "Moves"
+msgstr "Movimientos"
+
+msgctxt "field:sale.sale,number:"
+msgid "Number"
+msgstr "Número"
+
+msgctxt "field:sale.sale,origin:"
+msgid "Origin"
+msgstr "Origen"
+
+msgctxt "field:sale.sale,party:"
+msgid "Party"
+msgstr "Tercero"
+
+msgctxt "field:sale.sale,party_lang:"
+msgid "Party Language"
+msgstr "Idioma del tercero"
+
+msgctxt "field:sale.sale,payment_term:"
+msgid "Payment Term"
+msgstr "Plazo de pago"
+
+msgctxt "field:sale.sale,quoted_by:"
+msgid "Quoted By"
+msgstr "Presupuestada por"
+
+msgctxt "field:sale.sale,reference:"
+msgid "Reference"
+msgstr "Referencia"
+
+msgctxt "field:sale.sale,sale_date:"
+msgid "Sale Date"
+msgstr "Fecha venta"
+
+msgctxt "field:sale.sale,shipment_address:"
+msgid "Shipment Address"
+msgstr "Dirección de envío"
+
+msgctxt "field:sale.sale,shipment_method:"
+msgid "Shipment Method"
+msgstr "Método de envío"
+
+msgctxt "field:sale.sale,shipment_party:"
+msgid "Shipment Party"
+msgstr "Tercero del envío"
+
+msgctxt "field:sale.sale,shipment_returns:"
+msgid "Shipment Returns"
+msgstr "Albaranes de devolución"
+
+msgctxt "field:sale.sale,shipment_state:"
+msgid "Shipment State"
+msgstr "Estado envío"
+
+msgctxt "field:sale.sale,shipments:"
+msgid "Shipments"
+msgstr "Albaranes"
+
+msgctxt "field:sale.sale,shipping_date:"
+msgid "Shipping Date"
+msgstr "Fecha envío"
+
+msgctxt "field:sale.sale,state:"
+msgid "State"
+msgstr "Estado"
+
+msgctxt "field:sale.sale,tax_amount:"
+msgid "Tax"
+msgstr "Impuesto"
+
+msgctxt "field:sale.sale,tax_amount_cache:"
+msgid "Tax Cache"
+msgstr "Impuestos precalculado"
+
+msgctxt "field:sale.sale,total_amount:"
+msgid "Total"
+msgstr "Total"
+
+msgctxt "field:sale.sale,total_amount_cache:"
+msgid "Total Cache"
+msgstr "Total precalculado"
+
+msgctxt "field:sale.sale,untaxed_amount:"
+msgid "Untaxed"
+msgstr "Base imponible"
+
+msgctxt "field:sale.sale,untaxed_amount_cache:"
+msgid "Untaxed Cache"
+msgstr "Base imponible precalculada"
+
+msgctxt "field:sale.sale,warehouse:"
+msgid "Warehouse"
+msgstr "Almacén"
+
+msgctxt "field:sale.sale-ignored-account.invoice,invoice:"
+msgid "Invoice"
+msgstr "Factura"
+
+msgctxt "field:sale.sale-ignored-account.invoice,sale:"
+msgid "Sale"
+msgstr "Venta"
+
+msgctxt "field:sale.sale-recreated-account.invoice,invoice:"
+msgid "Invoice"
+msgstr "Factura"
+
+msgctxt "field:sale.sale-recreated-account.invoice,sale:"
+msgid "Sale"
+msgstr "Venta"
+
+msgctxt "field:stock.move,sale:"
+msgid "Sale"
+msgstr "Venta"
+
+msgctxt "field:stock.move,sale_exception_state:"
+msgid "Exception State"
+msgstr "Estado excepción"
+
+msgctxt "help:product.configuration,default_lead_time:"
+msgid ""
+"The time from confirming the sales order to sending the products.\n"
+"Used for products without a lead time."
+msgstr ""
+"El tiempo desde que se ha confirmado la de venta hasta que se envian los productos.\n"
+"Usado en los productos sin tiempo de espera."
+
+msgctxt "help:product.product,lead_time:"
+msgid ""
+"The time from confirming the sales order to sending the products.\n"
+"If empty the default lead time from the configuration is used."
+msgstr ""
+"El tiempo desde que se confirma el pedido hasta que se envian los productos.\n"
+"Si se deja en blaco s'utlitza el tiempo de envío por defecto de la configuración."
+
+msgctxt "help:product.template,lead_time:"
+msgid ""
+"The time from confirming the sales order to sending the products.\n"
+"If empty the default lead time from the configuration is used."
+msgstr ""
+"El tiempo desde que se confirma el pedido hasta que se envian los productos.\n"
+"Si se deja en blaco s'utlitza el tiempo de envío por defecto de la configuración."
+
+msgctxt "help:sale.configuration,sale_process_after:"
+msgid ""
+"The grace period during which confirmed sale can still be reset to draft.\n"
+"Applied if a worker queue is activated."
+msgstr ""
+"El periodo durante el cual una venta confirmada se puede volver a estado borrador.\n"
+"Solo aplica si la cola de trabajos está activada."
+
+msgctxt "help:sale.handle.invoice.exception.ask,recreate_invoices:"
+msgid ""
+"The selected invoices will be recreated. The other ones will be ignored."
+msgstr ""
+"Las facturas seleccionadas serán recreadas. Las otras serán ignoradas."
+
+msgctxt "help:sale.sale,shipping_date:"
+msgid "When the shipping of goods should start."
+msgstr "Cuando debería comenzar el envío de los bienes."
+
+msgctxt "model:ir.action,name:act_invoice_form"
+msgid "Invoices"
+msgstr "Facturas"
+
+msgctxt "model:ir.action,name:act_open_customer"
+msgid "Parties associated to Sales"
+msgstr "Terceros con ventas"
+
+msgctxt "model:ir.action,name:act_product"
+msgid "Products"
+msgstr "Productos"
+
+msgctxt "model:ir.action,name:act_reporting_category"
+msgid "Sales per Category"
+msgstr "Ventas por categoría"
+
+msgctxt "model:ir.action,name:act_reporting_category_time_series"
+msgid "Sales per Category"
+msgstr "Ventas por categoría"
+
+msgctxt "model:ir.action,name:act_reporting_category_tree"
+msgid "Sales per Category"
+msgstr "Ventas por categoría"
+
+msgctxt "model:ir.action,name:act_reporting_country_subdivision_time_series"
+msgid "Sales per Subdivision"
+msgstr "Ventas por subdivisión"
+
+msgctxt "model:ir.action,name:act_reporting_country_time_series"
+msgid "Sales per Country"
+msgstr "Ventas por país"
+
+msgctxt "model:ir.action,name:act_reporting_customer"
+msgid "Sales per Customer"
+msgstr "Ventas por cliente"
+
+msgctxt "model:ir.action,name:act_reporting_customer_time_series"
+msgid "Sales per Customer"
+msgstr "Ventas por cliente"
+
+msgctxt "model:ir.action,name:act_reporting_product"
+msgid "Sales per Product"
+msgstr "Ventas por producto"
+
+msgctxt "model:ir.action,name:act_reporting_product_time_series"
+msgid "Sales per Product"
+msgstr "Ventas por región"
+
+msgctxt "model:ir.action,name:act_reporting_region"
+msgid "Sales per Region"
+msgstr "Ventas por región"
+
+msgctxt "model:ir.action,name:act_return_form"
+msgid "Returns"
+msgstr "Albaranes de devolución"
+
+msgctxt "model:ir.action,name:act_sale_configuration_form"
+msgid "Configuration"
+msgstr "Configuración"
+
+msgctxt "model:ir.action,name:act_sale_form"
+msgid "Sales"
+msgstr "Ventas"
+
+msgctxt "model:ir.action,name:act_sale_form2"
+msgid "Sales"
+msgstr "Ventas"
+
+msgctxt "model:ir.action,name:act_sale_invoice_relate"
+msgid "Sales"
+msgstr "Ventas"
+
+msgctxt "model:ir.action,name:act_sale_move_relate"
+msgid "Moves"
+msgstr "Movimientos"
+
+msgctxt "model:ir.action,name:act_sale_shipment_returns_relate"
+msgid "Sales"
+msgstr "Ventas"
+
+msgctxt "model:ir.action,name:act_sale_shipments_relate"
+msgid "Sales"
+msgstr "Ventas"
+
+msgctxt "model:ir.action,name:act_shipment_form"
+msgid "Shipments"
+msgstr "Albaranes"
+
+msgctxt "model:ir.action,name:report_sale"
+msgid "Sale"
+msgstr "Venta"
+
+msgctxt "model:ir.action,name:wizard_invoice_handle_exception"
+msgid "Handle Invoice Exception"
+msgstr "Gestionar excepción de factura"
+
+msgctxt "model:ir.action,name:wizard_modify_header"
+msgid "Modify Header"
+msgstr "Modificar cabecera"
+
+msgctxt "model:ir.action,name:wizard_reporting_region_open"
+msgid "Open Region"
+msgstr "Abrir región"
+
+msgctxt "model:ir.action,name:wizard_return_sale"
+msgid "Return Sale"
+msgstr "Devolver la venta"
+
+msgctxt "model:ir.action,name:wizard_shipment_handle_exception"
+msgid "Handle Shipment Exception"
+msgstr "Gestionar excepción de envío"
+
+msgctxt "model:ir.action.act_window.domain,name:act_sale_form_domain_all"
+msgid "All"
+msgstr "Todo"
+
+msgctxt ""
+"model:ir.action.act_window.domain,name:act_sale_form_domain_confirmed"
+msgid "Confirmed"
+msgstr "Confirmada"
+
+msgctxt "model:ir.action.act_window.domain,name:act_sale_form_domain_draft"
+msgid "Draft"
+msgstr "Borrador"
+
+msgctxt ""
+"model:ir.action.act_window.domain,name:act_sale_form_domain_exception"
+msgid "Exception"
+msgstr "Excepción"
+
+msgctxt ""
+"model:ir.action.act_window.domain,name:act_sale_form_domain_processing"
+msgid "Processing"
+msgstr "En proceso"
+
+msgctxt ""
+"model:ir.action.act_window.domain,name:act_sale_form_domain_quotation"
+msgid "Quotation"
+msgstr "Presupuesto"
+
+msgctxt "model:ir.message,text:msg_erase_party_pending_sale"
+msgid ""
+"You cannot erase party \"%(party)s\" while they have pending sales with "
+"company \"%(company)s\"."
+msgstr ""
+"No puede eliminar el tercero \"%(party)s\" mientras tenga ventas pendientes "
+"en la empresa \"%(company)s\"."
+
+msgctxt "model:ir.message,text:msg_sale_customer_location_required"
+msgid ""
+"To process sale \"%(sale)s\" you must set a customer location on party "
+"\"%(party)s\"."
+msgstr ""
+"Para procesar la venta \"%(sale)s\" debe asignar una ubicación en el tercero"
+" \"%(party)s\"."
+
+msgctxt "model:ir.message,text:msg_sale_delete_cancel"
+msgid "To delete sale \"%(sale)s\" you must cancel it."
+msgstr "Para eliminar la venta \"%(sale)s\" debe cancelarla."
+
+msgctxt "model:ir.message,text:msg_sale_invalid_method"
+msgid ""
+"You cannot use together invoice \"%(invoice_method)s\" and shipment "
+"\"%(shipment_method)s\" on sale \"%(sale)s\"."
+msgstr ""
+"No puede usar conjuntamente el método de facturación \"%(invoice_method)s\" "
+"y el método de envío \"%(shipment_method)s\" en la venta \"%(sale)s\"."
+
+msgctxt ""
+"model:ir.message,text:msg_sale_invoice_address_required_for_quotation"
+msgid "To get a quote for sale \"%(sale)s\" you must enter an invoice address."
+msgstr ""
+"Para obtener un presupuesto para la venta \"%(sale)s\" debe especificar una "
+"dirección de facturación."
+
+msgctxt "model:ir.message,text:msg_sale_invoice_reset_draft"
+msgid ""
+"You cannot reset invoice \"%(invoice)s\" to draft because it was generated "
+"by a sale."
+msgstr ""
+"No puede establecer la factura \"%(invoice)s\" como borrador porque fue "
+"generada desde una venta."
+
+msgctxt "model:ir.message,text:msg_sale_line_delete_cancel_draft"
+msgid ""
+"To delete line \"%(line)s\" you must cancel or reset to draft sale "
+"\"%(sale)s\"."
+msgstr ""
+"Para eliminar la línea \"%(line)s\" debe cancelar o establecer como borrador"
+" la venta \"%(sale)s\"."
+
+msgctxt "model:ir.message,text:msg_sale_missing_account_revenue"
+msgid "To invoice sale \"%(sale)s\" you must configure a default account revenue."
+msgstr ""
+"Para facturar la venta \"%(sale)s\" debe configurar una cuenta de ingresos "
+"por defecto."
+
+msgctxt "model:ir.message,text:msg_sale_modify_header_draft"
+msgid "To modify the header of sale \"%(sale)s\", it must be in \"draft\" state."
+msgstr ""
+"Para modificar la cabecera de la venta \"%(sale)s\", esta debes estar en "
+"estado \"borrador\"."
+
+msgctxt "model:ir.message,text:msg_sale_move_reset_draft"
+msgid ""
+"You cannot reset move \"%(move)s\" to draft because it was generated by a "
+"sale."
+msgstr ""
+"No puede establecer el movimiento \"%(move)s\" como borrador porque fue "
+"generado desde una venta."
+
+msgctxt "model:ir.message,text:msg_sale_product_missing_account_revenue"
+msgid ""
+"To invoice sale \"%(sale)s\" you must define an account revenue for product "
+"\"%(product)s\"."
+msgstr ""
+"Para facturar la venta \"%(sale)s\" debe definir una cuenta de ingresos para"
+" el producto \"%(product)s\"."
+
+msgctxt "model:ir.message,text:msg_sale_reporting_company"
+msgid "Company"
+msgstr "Empresa"
+
+msgctxt "model:ir.message,text:msg_sale_reporting_currency"
+msgid "Currency"
+msgstr "Moneda"
+
+msgctxt "model:ir.message,text:msg_sale_reporting_currency_digits"
+msgid "Currency Digits"
+msgstr "Decimales de la moneda"
+
+msgctxt "model:ir.message,text:msg_sale_reporting_number"
+msgid "#"
+msgstr "#"
+
+msgctxt "model:ir.message,text:msg_sale_reporting_number_help"
+msgid "Number of sales"
+msgstr "Número de ventas"
+
+msgctxt "model:ir.message,text:msg_sale_reporting_revenue"
+msgid "Revenue"
+msgstr "Ingresos"
+
+msgctxt "model:ir.message,text:msg_sale_reporting_revenue_trend"
+msgid "Revenue Trend"
+msgstr "Tendencia de ingresos"
+
+msgctxt ""
+"model:ir.message,text:msg_sale_shipment_address_required_for_quotation"
+msgid "To get a quote for sale \"%(sale)s\" you must enter a shipment address."
+msgstr ""
+"Para obtener un presupuesto para la venta \"%(sale)s\" debe definir una "
+"dirección de envío."
+
+msgctxt "model:ir.message,text:msg_sale_warehouse_required_for_quotation"
+msgid "To get a quote for sale \"%(sale)s\" you must enter a warehouse."
+msgstr ""
+"Para obtener un presupuesto para la venta \"%(sale)s\" debe definir un "
+"almacén."
+
+msgctxt "model:ir.model.button,string:sale_cancel_button"
+msgid "Cancel"
+msgstr "Cancelar"
+
+msgctxt "model:ir.model.button,string:sale_confirm_button"
+msgid "Confirm"
+msgstr "Confirmar"
+
+msgctxt "model:ir.model.button,string:sale_draft_button"
+msgid "Draft"
+msgstr "Borrador"
+
+msgctxt "model:ir.model.button,string:sale_handle_invoice_exception_button"
+msgid "Handle Invoice Exception"
+msgstr "Gestionar excepción de factura"
+
+msgctxt "model:ir.model.button,string:sale_handle_shipment_exception_button"
+msgid "Handle Shipment Exception"
+msgstr "Gestionar excepción de envío"
+
+msgctxt "model:ir.model.button,string:sale_modify_header_button"
+msgid "Modify Header"
+msgstr "Modificar cabecera"
+
+msgctxt "model:ir.model.button,string:sale_process_button"
+msgid "Process"
+msgstr "Procesar"
+
+msgctxt "model:ir.model.button,string:sale_quote_button"
+msgid "Quote"
+msgstr "Presupuesto"
+
+msgctxt "model:ir.rule.group,name:rule_group_reporting_category_companies"
+msgid "User in companies"
+msgstr "Usuario en las empresas"
+
+msgctxt ""
+"model:ir.rule.group,name:rule_group_reporting_category_time_series_companies"
+msgid "User in companies"
+msgstr "Usuario en las empresas"
+
+msgctxt ""
+"model:ir.rule.group,name:rule_group_reporting_country_subdivision_time_series_companies"
+msgid "User in companies"
+msgstr "Usuario en las empresas"
+
+msgctxt ""
+"model:ir.rule.group,name:rule_group_reporting_country_time_series_companies"
+msgid "User in companies"
+msgstr "Usuario en las empresas"
+
+msgctxt "model:ir.rule.group,name:rule_group_reporting_customer_companies"
+msgid "User in companies"
+msgstr "Usuario en las empresas"
+
+msgctxt ""
+"model:ir.rule.group,name:rule_group_reporting_customer_time_series_companies"
+msgid "User in companies"
+msgstr "Usuario en las empresas"
+
+msgctxt "model:ir.rule.group,name:rule_group_reporting_product_companies"
+msgid "User in companies"
+msgstr "Usuario en las empresas"
+
+msgctxt ""
+"model:ir.rule.group,name:rule_group_reporting_product_time_series_companies"
+msgid "User in companies"
+msgstr "Usuario en las empresas"
+
+msgctxt "model:ir.rule.group,name:rule_group_reporting_region_companies"
+msgid "User in companies"
+msgstr "Usuario en las empresas"
+
+msgctxt "model:ir.rule.group,name:rule_group_sale_companies"
+msgid "User in companies"
+msgstr "Usuario en las empresas"
+
+msgctxt "model:ir.sequence,name:sequence_sale"
+msgid "Sale"
+msgstr "Venta"
+
+msgctxt "model:ir.sequence.type,name:sequence_type_sale"
+msgid "Sale"
+msgstr "Venta"
+
+msgctxt "model:ir.ui.menu,name:menu_configuration"
+msgid "Configuration"
+msgstr "Configuración"
+
+msgctxt "model:ir.ui.menu,name:menu_customer"
+msgid "Associated to Sales"
+msgstr "Con ventas"
+
+msgctxt "model:ir.ui.menu,name:menu_product"
+msgid "Products"
+msgstr "Productos"
+
+msgctxt "model:ir.ui.menu,name:menu_reporting"
+msgid "Reporting"
+msgstr "Informes"
+
+msgctxt "model:ir.ui.menu,name:menu_reporting_sale"
+msgid "Sales"
+msgstr "Ventas"
+
+msgctxt "model:ir.ui.menu,name:menu_sale"
+msgid "Sales"
+msgstr "Ventas"
+
+msgctxt "model:ir.ui.menu,name:menu_sale_configuration"
+msgid "Configuration"
+msgstr "Configuración"
+
+msgctxt "model:ir.ui.menu,name:menu_sale_form"
+msgid "Sales"
+msgstr "Ventas"
+
+msgctxt "model:product.configuration.default_lead_time,name:"
+msgid "Product Default Lead Time"
+msgstr "Tiempo de envío defecto del producto"
+
+msgctxt "model:product.sale.context,name:"
+msgid "Product Sale Context"
+msgstr "Contexto productos vendibles"
+
+msgctxt "model:res.group,name:group_sale"
+msgid "Sales"
+msgstr "Ventas"
+
+msgctxt "model:res.group,name:group_sale_admin"
+msgid "Sales Administrator"
+msgstr "Administración de ventas"
+
+msgctxt "model:sale.configuration,name:"
+msgid "Sale Configuration"
+msgstr "Configuración ventas"
+
+msgctxt "model:sale.configuration.sale_method,name:"
+msgid "Sale Configuration Sale Method"
+msgstr "Configuración del método de venta"
+
+msgctxt "model:sale.configuration.sequence,name:"
+msgid "Sale Configuration Sequence"
+msgstr "Configuración de las secuencias de venta"
+
+msgctxt "model:sale.handle.invoice.exception.ask,name:"
+msgid "Handle Invoice Exception"
+msgstr "Gestionar excepción de factura"
+
+msgctxt "model:sale.handle.shipment.exception.ask,name:"
+msgid "Handle Shipment Exception"
+msgstr "Gestionar excepción de envío"
+
+msgctxt "model:sale.line,name:"
+msgid "Sale Line"
+msgstr "Línea de venta"
+
+msgctxt "model:sale.line-account.tax,name:"
+msgid "Sale Line - Tax"
+msgstr "Línea de venta - Impuesto"
+
+msgctxt "model:sale.line-ignored-stock.move,name:"
+msgid "Sale Line - Ignored Move"
+msgstr "Línea de venta - Movimiento ignorado"
+
+msgctxt "model:sale.line-recreated-stock.move,name:"
+msgid "Sale Line - Recreated Move"
+msgstr "Línea de venta - Movimiento recreado"
+
+msgctxt "model:sale.reporting.category,name:"
+msgid "Sale Reporting per Category"
+msgstr "Informe de ventas por categoría"
+
+msgctxt "model:sale.reporting.category.time_series,name:"
+msgid "Sale Reporting per Category"
+msgstr "Informe de ventas por categoría"
+
+msgctxt "model:sale.reporting.category.tree,name:"
+msgid "Sale Reporting per Category"
+msgstr "Informe de ventas por categoría"
+
+msgctxt "model:sale.reporting.context,name:"
+msgid "Sale Reporting Context"
+msgstr "Contexto informe de ventas"
+
+msgctxt "model:sale.reporting.country,name:"
+msgid "Sale Reporting per Country"
+msgstr "Informe de ventas por país"
+
+msgctxt "model:sale.reporting.country.subdivision,name:"
+msgid "Sale Reporting per Subdivision"
+msgstr "Informe de ventas por subdivisión"
+
+msgctxt "model:sale.reporting.country.subdivision.time_series,name:"
+msgid "Sale Reporting per Subdivision"
+msgstr "Informe de ventas por subdivisión"
+
+msgctxt "model:sale.reporting.country.time_series,name:"
+msgid "Sale Reporting per Country"
+msgstr "Informe de ventas por país"
+
+msgctxt "model:sale.reporting.customer,name:"
+msgid "Sale Reporting per Customer"
+msgstr "Informe de ventas por cliente"
+
+msgctxt "model:sale.reporting.customer.time_series,name:"
+msgid "Sale Reporting per Customer"
+msgstr "Informe de ventas por cliente"
+
+msgctxt "model:sale.reporting.product,name:"
+msgid "Sale Reporting per Product"
+msgstr "Informe de ventas por producto"
+
+msgctxt "model:sale.reporting.product.time_series,name:"
+msgid "Sale Reporting per Product"
+msgstr "Informe de ventas por producto"
+
+msgctxt "model:sale.reporting.region,name:"
+msgid "Sale Reporting per Region"
+msgstr "Informe de ventas por región"
+
+msgctxt "model:sale.return_sale.start,name:"
+msgid "Return Sale"
+msgstr "Devolver la venta"
+
+msgctxt "model:sale.sale,name:"
+msgid "Sale"
+msgstr "Venta"
+
+msgctxt "model:sale.sale-ignored-account.invoice,name:"
+msgid "Sale - Ignored Invoice"
+msgstr "Venta - Factura ignorada"
+
+msgctxt "model:sale.sale-recreated-account.invoice,name:"
+msgid "Sale - Recreated Invoice"
+msgstr "Venta - Factura recreada"
+
+msgctxt "report:sale.sale:"
+msgid ":"
+msgstr ":"
+
+msgctxt "report:sale.sale:"
+msgid "Amount"
+msgstr "Importe"
+
+msgctxt "report:sale.sale:"
+msgid "Date:"
+msgstr "Fecha:"
+
+msgctxt "report:sale.sale:"
+msgid "Description"
+msgstr "Descripción"
+
+msgctxt "report:sale.sale:"
+msgid "Description:"
+msgstr "Descripción:"
+
+msgctxt "report:sale.sale:"
+msgid "Draft Sale Order"
+msgstr "Ventas borrador"
+
+msgctxt "report:sale.sale:"
+msgid "Quantity"
+msgstr "Cantidad"
+
+msgctxt "report:sale.sale:"
+msgid "Quotation N°:"
+msgstr "Presupuesto Nº:"
+
+msgctxt "report:sale.sale:"
+msgid "Reference:"
+msgstr "Referencia:"
+
+msgctxt "report:sale.sale:"
+msgid "Sale Order N°:"
+msgstr "Venta Nº:"
+
+msgctxt "report:sale.sale:"
+msgid "Taxes"
+msgstr "Impuestos"
+
+msgctxt "report:sale.sale:"
+msgid "Taxes:"
+msgstr "Impuestos:"
+
+msgctxt "report:sale.sale:"
+msgid "Total (excl. taxes):"
+msgstr "Base imponible:"
+
+msgctxt "report:sale.sale:"
+msgid "Total:"
+msgstr "Total:"
+
+msgctxt "report:sale.sale:"
+msgid "Unit Price"
+msgstr "Precio unitario"
+
+msgctxt "selection:account.invoice,sale_exception_state:"
+msgid "Ignored"
+msgstr "Ignorado"
+
+msgctxt "selection:account.invoice,sale_exception_state:"
+msgid "Recreated"
+msgstr "Recreada"
+
+msgctxt "selection:sale.line,type:"
+msgid "Comment"
+msgstr "Comentario"
+
+msgctxt "selection:sale.line,type:"
+msgid "Line"
+msgstr "Línea"
+
+msgctxt "selection:sale.line,type:"
+msgid "Subtotal"
+msgstr "Subtotal"
+
+msgctxt "selection:sale.line,type:"
+msgid "Title"
+msgstr "Título"
+
+msgctxt "selection:sale.reporting.context,period:"
+msgid "Day"
+msgstr "Día"
+
+msgctxt "selection:sale.reporting.context,period:"
+msgid "Month"
+msgstr "Mes"
+
+msgctxt "selection:sale.reporting.context,period:"
+msgid "Year"
+msgstr "Año"
+
+msgctxt "selection:sale.sale,invoice_method:"
+msgid "Manual"
+msgstr "Manual"
+
+msgctxt "selection:sale.sale,invoice_method:"
+msgid "On Order Processed"
+msgstr "Al procesar el pedido"
+
+msgctxt "selection:sale.sale,invoice_method:"
+msgid "On Shipment Sent"
+msgstr "Al enviar"
+
+msgctxt "selection:sale.sale,invoice_state:"
+msgid "Exception"
+msgstr "Excepción"
+
+msgctxt "selection:sale.sale,invoice_state:"
+msgid "None"
+msgstr "Ninguno"
+
+msgctxt "selection:sale.sale,invoice_state:"
+msgid "Paid"
+msgstr "Pagada"
+
+msgctxt "selection:sale.sale,invoice_state:"
+msgid "Waiting"
+msgstr "En espera"
+
+msgctxt "selection:sale.sale,shipment_method:"
+msgid "Manual"
+msgstr "Manual"
+
+msgctxt "selection:sale.sale,shipment_method:"
+msgid "On Invoice Paid"
+msgstr "Al pagar la factura"
+
+msgctxt "selection:sale.sale,shipment_method:"
+msgid "On Order Processed"
+msgstr "Al procesar el pedido"
+
+msgctxt "selection:sale.sale,shipment_state:"
+msgid "Exception"
+msgstr "Excepción"
+
+msgctxt "selection:sale.sale,shipment_state:"
+msgid "None"
+msgstr "Ninguno"
+
+msgctxt "selection:sale.sale,shipment_state:"
+msgid "Sent"
+msgstr "Enviada"
+
+msgctxt "selection:sale.sale,shipment_state:"
+msgid "Waiting"
+msgstr "En espera"
+
+msgctxt "selection:sale.sale,state:"
+msgid "Cancelled"
+msgstr "Cancelada"
+
+msgctxt "selection:sale.sale,state:"
+msgid "Confirmed"
+msgstr "Confirmada"
+
+msgctxt "selection:sale.sale,state:"
+msgid "Done"
+msgstr "Finalizada"
+
+msgctxt "selection:sale.sale,state:"
+msgid "Draft"
+msgstr "Borrador"
+
+msgctxt "selection:sale.sale,state:"
+msgid "Processing"
+msgstr "En proceso"
+
+msgctxt "selection:sale.sale,state:"
+msgid "Quotation"
+msgstr "Presupuesto"
+
+msgctxt "selection:stock.move,sale_exception_state:"
+msgid "Ignored"
+msgstr "Ignorado"
+
+msgctxt "selection:stock.move,sale_exception_state:"
+msgid "Recreated"
+msgstr "Recreado"
+
+msgctxt "view:party.party:"
+msgid "Sale"
+msgstr "Venta"
+
+msgctxt "view:product.template:"
+msgid "Customers"
+msgstr "Clientes"
+
+msgctxt "view:sale.handle.invoice.exception.ask:"
+msgid "Choose invoices to recreate:"
+msgstr "Seleccione las facturas a recrear:"
+
+msgctxt "view:sale.handle.shipment.exception.ask:"
+msgid "Choose move to recreate:"
+msgstr "Seleccione los movimientos a recrear:"
+
+msgctxt "view:sale.line:"
+msgid "General"
+msgstr "General"
+
+msgctxt "view:sale.line:"
+msgid "Notes"
+msgstr "Notas"
+
+msgctxt "view:sale.line:"
+msgid "Taxes"
+msgstr "Impuestos"
+
+msgctxt "view:sale.return_sale.start:"
+msgid "Are you sure to return these/this sale(s)?"
+msgstr "¿Estás seguro de querer devolver este/os pedido/s de venta?"
+
+msgctxt "view:sale.sale:"
+msgid "Other Info"
+msgstr "Información adicional"
+
+msgctxt "view:sale.sale:"
+msgid "Sale"
+msgstr "Venta"
+
+msgctxt "wizard_button:sale.handle.invoice.exception,ask,end:"
+msgid "Cancel"
+msgstr "Cancelar"
+
+msgctxt "wizard_button:sale.handle.invoice.exception,ask,handle:"
+msgid "OK"
+msgstr "Aceptar"
+
+msgctxt "wizard_button:sale.handle.shipment.exception,ask,end:"
+msgid "Cancel"
+msgstr "Cancelar"
+
+msgctxt "wizard_button:sale.handle.shipment.exception,ask,handle:"
+msgid "OK"
+msgstr "Aceptar"
+
+msgctxt "wizard_button:sale.modify_header,start,end:"
+msgid "Cancel"
+msgstr "Cancelar"
+
+msgctxt "wizard_button:sale.modify_header,start,modify:"
+msgid "Modify"
+msgstr "Modificar"
+
+msgctxt "wizard_button:sale.return_sale,start,end:"
+msgid "Cancel"
+msgstr "Cancelar"
+
+msgctxt "wizard_button:sale.return_sale,start,return_:"
+msgid "Return"
+msgstr "Devolver"
diff --git a/modules/sale/locale/es_419.po b/modules/sale/locale/es_419.po
new file mode 100644
index 0000000000..30a4d236ef
--- /dev/null
+++ b/modules/sale/locale/es_419.po
@@ -0,0 +1,1352 @@
+#
+msgid ""
+msgstr "Content-Type: text/plain; charset=utf-8\n"
+
+msgctxt "field:account.invoice,sale_exception_state:"
+msgid "Exception State"
+msgstr "Estado excepción"
+
+msgctxt "field:account.invoice,sales:"
+msgid "Sales"
+msgstr ""
+
+msgctxt "field:product.configuration,default_lead_time:"
+msgid "Default Lead Time"
+msgstr ""
+
+msgctxt "field:product.configuration.default_lead_time,company:"
+msgid "Company"
+msgstr ""
+
+msgctxt "field:product.configuration.default_lead_time,default_lead_time:"
+msgid "Default Lead Time"
+msgstr ""
+
+msgctxt "field:product.product,lead_time:"
+msgid "Lead Time"
+msgstr ""
+
+msgctxt "field:product.product,salable:"
+msgid "Salable"
+msgstr ""
+
+msgctxt "field:product.product,sale_price_uom:"
+msgid "Sale Price"
+msgstr ""
+
+msgctxt "field:product.product,sale_uom:"
+msgid "Sale UOM"
+msgstr ""
+
+msgctxt "field:product.sale.context,company:"
+msgid "Company"
+msgstr ""
+
+msgctxt "field:product.sale.context,currency:"
+msgid "Currency"
+msgstr ""
+
+msgctxt "field:product.sale.context,customer:"
+msgid "Customer"
+msgstr ""
+
+#, fuzzy
+msgctxt "field:product.sale.context,locations:"
+msgid "Warehouses"
+msgstr "Bodega"
+
+msgctxt "field:product.sale.context,quantity:"
+msgid "Quantity"
+msgstr ""
+
+msgctxt "field:product.sale.context,sale_date:"
+msgid "Sale Date"
+msgstr ""
+
+msgctxt "field:product.sale.context,stock_date_end:"
+msgid "Stock End Date"
+msgstr ""
+
+msgctxt "field:product.template,lead_time:"
+msgid "Lead Time"
+msgstr ""
+
+msgctxt "field:product.template,salable:"
+msgid "Salable"
+msgstr ""
+
+msgctxt "field:product.template,sale_uom:"
+msgid "Sale UOM"
+msgstr ""
+
+msgctxt "field:sale.configuration,sale_invoice_method:"
+msgid "Sale Invoice Method"
+msgstr ""
+
+msgctxt "field:sale.configuration,sale_process_after:"
+msgid "Process Sale after"
+msgstr ""
+
+msgctxt "field:sale.configuration,sale_sequence:"
+msgid "Sale Sequence"
+msgstr ""
+
+msgctxt "field:sale.configuration,sale_shipment_method:"
+msgid "Sale Shipment Method"
+msgstr ""
+
+msgctxt "field:sale.configuration.sale_method,sale_invoice_method:"
+msgid "Sale Invoice Method"
+msgstr ""
+
+msgctxt "field:sale.configuration.sale_method,sale_shipment_method:"
+msgid "Sale Shipment Method"
+msgstr ""
+
+msgctxt "field:sale.configuration.sequence,company:"
+msgid "Company"
+msgstr ""
+
+msgctxt "field:sale.configuration.sequence,sale_sequence:"
+msgid "Sale Sequence"
+msgstr ""
+
+msgctxt "field:sale.handle.invoice.exception.ask,domain_invoices:"
+msgid "Domain Invoices"
+msgstr ""
+
+msgctxt "field:sale.handle.invoice.exception.ask,recreate_invoices:"
+msgid "Recreate Invoices"
+msgstr ""
+
+msgctxt "field:sale.handle.shipment.exception.ask,domain_moves:"
+msgid "Domain Moves"
+msgstr ""
+
+msgctxt "field:sale.handle.shipment.exception.ask,recreate_moves:"
+msgid "Recreate Moves"
+msgstr ""
+
+msgctxt "field:sale.line,actual_quantity:"
+msgid "Actual Quantity"
+msgstr ""
+
+msgctxt "field:sale.line,amount:"
+msgid "Amount"
+msgstr ""
+
+msgctxt "field:sale.line,company:"
+msgid "Company"
+msgstr ""
+
+msgctxt "field:sale.line,currency:"
+msgid "Currency"
+msgstr ""
+
+msgctxt "field:sale.line,description:"
+msgid "Description"
+msgstr ""
+
+msgctxt "field:sale.line,from_location:"
+msgid "From Location"
+msgstr ""
+
+msgctxt "field:sale.line,invoice_lines:"
+msgid "Invoice Lines"
+msgstr ""
+
+msgctxt "field:sale.line,move_done:"
+msgid "Moves Done"
+msgstr ""
+
+msgctxt "field:sale.line,move_exception:"
+msgid "Moves Exception"
+msgstr ""
+
+msgctxt "field:sale.line,moves:"
+msgid "Moves"
+msgstr ""
+
+msgctxt "field:sale.line,moves_ignored:"
+msgid "Ignored Moves"
+msgstr ""
+
+msgctxt "field:sale.line,moves_recreated:"
+msgid "Recreated Moves"
+msgstr ""
+
+msgctxt "field:sale.line,note:"
+msgid "Note"
+msgstr ""
+
+msgctxt "field:sale.line,product:"
+msgid "Product"
+msgstr ""
+
+msgctxt "field:sale.line,product_uom_category:"
+msgid "Product Uom Category"
+msgstr ""
+
+msgctxt "field:sale.line,quantity:"
+msgid "Quantity"
+msgstr ""
+
+msgctxt "field:sale.line,sale:"
+msgid "Sale"
+msgstr ""
+
+msgctxt "field:sale.line,sale_state:"
+msgid "Sale State"
+msgstr ""
+
+msgctxt "field:sale.line,shipping_date:"
+msgid "Shipping Date"
+msgstr ""
+
+msgctxt "field:sale.line,summary:"
+msgid "Summary"
+msgstr ""
+
+msgctxt "field:sale.line,taxes:"
+msgid "Taxes"
+msgstr ""
+
+msgctxt "field:sale.line,to_location:"
+msgid "To Location"
+msgstr ""
+
+msgctxt "field:sale.line,type:"
+msgid "Type"
+msgstr ""
+
+msgctxt "field:sale.line,unit:"
+msgid "Unit"
+msgstr ""
+
+msgctxt "field:sale.line,unit_digits:"
+msgid "Unit Digits"
+msgstr ""
+
+msgctxt "field:sale.line,unit_price:"
+msgid "Unit Price"
+msgstr "Precio unitario"
+
+msgctxt "field:sale.line,warehouse:"
+msgid "Warehouse"
+msgstr "Bodega"
+
+msgctxt "field:sale.line-account.tax,line:"
+msgid "Sale Line"
+msgstr ""
+
+msgctxt "field:sale.line-account.tax,tax:"
+msgid "Tax"
+msgstr ""
+
+msgctxt "field:sale.line-ignored-stock.move,move:"
+msgid "Move"
+msgstr ""
+
+msgctxt "field:sale.line-ignored-stock.move,sale_line:"
+msgid "Sale Line"
+msgstr ""
+
+msgctxt "field:sale.line-recreated-stock.move,move:"
+msgid "Move"
+msgstr ""
+
+msgctxt "field:sale.line-recreated-stock.move,sale_line:"
+msgid "Sale Line"
+msgstr ""
+
+msgctxt "field:sale.reporting.category,category:"
+msgid "Category"
+msgstr ""
+
+msgctxt "field:sale.reporting.category,time_series:"
+msgid "Time Series"
+msgstr ""
+
+msgctxt "field:sale.reporting.category.time_series,category:"
+msgid "Category"
+msgstr ""
+
+msgctxt "field:sale.reporting.category.time_series,date:"
+msgid "Date"
+msgstr ""
+
+msgctxt "field:sale.reporting.category.tree,children:"
+msgid "Children"
+msgstr ""
+
+msgctxt "field:sale.reporting.category.tree,currency_digits:"
+msgid "Currency Digits"
+msgstr ""
+
+msgctxt "field:sale.reporting.category.tree,name:"
+msgid "Name"
+msgstr ""
+
+msgctxt "field:sale.reporting.category.tree,parent:"
+msgid "Parent"
+msgstr ""
+
+msgctxt "field:sale.reporting.category.tree,revenue:"
+msgid "Revenue"
+msgstr ""
+
+msgctxt "field:sale.reporting.context,company:"
+msgid "Company"
+msgstr ""
+
+msgctxt "field:sale.reporting.context,from_date:"
+msgid "From Date"
+msgstr ""
+
+msgctxt "field:sale.reporting.context,period:"
+msgid "Period"
+msgstr ""
+
+msgctxt "field:sale.reporting.context,to_date:"
+msgid "To Date"
+msgstr ""
+
+#, fuzzy
+msgctxt "field:sale.reporting.context,warehouse:"
+msgid "Warehouse"
+msgstr "Bodega"
+
+msgctxt "field:sale.reporting.country,country:"
+msgid "Country"
+msgstr ""
+
+msgctxt "field:sale.reporting.country,time_series:"
+msgid "Time Series"
+msgstr ""
+
+msgctxt "field:sale.reporting.country.subdivision,country:"
+msgid "Country"
+msgstr ""
+
+msgctxt "field:sale.reporting.country.subdivision,subdivision:"
+msgid "Subdivision"
+msgstr ""
+
+msgctxt "field:sale.reporting.country.subdivision,time_series:"
+msgid "Time Series"
+msgstr ""
+
+msgctxt "field:sale.reporting.country.subdivision.time_series,country:"
+msgid "Country"
+msgstr ""
+
+msgctxt "field:sale.reporting.country.subdivision.time_series,date:"
+msgid "Date"
+msgstr ""
+
+msgctxt "field:sale.reporting.country.subdivision.time_series,subdivision:"
+msgid "Subdivision"
+msgstr ""
+
+msgctxt "field:sale.reporting.country.time_series,country:"
+msgid "Country"
+msgstr ""
+
+msgctxt "field:sale.reporting.country.time_series,date:"
+msgid "Date"
+msgstr ""
+
+msgctxt "field:sale.reporting.customer,customer:"
+msgid "Customer"
+msgstr ""
+
+msgctxt "field:sale.reporting.customer,time_series:"
+msgid "Time Series"
+msgstr ""
+
+msgctxt "field:sale.reporting.customer.time_series,customer:"
+msgid "Customer"
+msgstr ""
+
+msgctxt "field:sale.reporting.customer.time_series,date:"
+msgid "Date"
+msgstr ""
+
+msgctxt "field:sale.reporting.product,product:"
+msgid "Product"
+msgstr ""
+
+msgctxt "field:sale.reporting.product,time_series:"
+msgid "Time Series"
+msgstr ""
+
+msgctxt "field:sale.reporting.product.time_series,date:"
+msgid "Date"
+msgstr ""
+
+msgctxt "field:sale.reporting.product.time_series,product:"
+msgid "Product"
+msgstr ""
+
+msgctxt "field:sale.reporting.region,children:"
+msgid "Children"
+msgstr ""
+
+msgctxt "field:sale.reporting.region,parent:"
+msgid "Parent"
+msgstr ""
+
+msgctxt "field:sale.reporting.region,region:"
+msgid "Region"
+msgstr ""
+
+msgctxt "field:sale.sale,comment:"
+msgid "Comment"
+msgstr ""
+
+msgctxt "field:sale.sale,company:"
+msgid "Company"
+msgstr ""
+
+msgctxt "field:sale.sale,confirmed_by:"
+msgid "Confirmed By"
+msgstr ""
+
+msgctxt "field:sale.sale,contact:"
+msgid "Contact"
+msgstr ""
+
+msgctxt "field:sale.sale,currency:"
+msgid "Currency"
+msgstr ""
+
+msgctxt "field:sale.sale,currency_digits:"
+msgid "Currency Digits"
+msgstr ""
+
+msgctxt "field:sale.sale,description:"
+msgid "Description"
+msgstr ""
+
+msgctxt "field:sale.sale,invoice_address:"
+msgid "Invoice Address"
+msgstr ""
+
+msgctxt "field:sale.sale,invoice_method:"
+msgid "Invoice Method"
+msgstr ""
+
+msgctxt "field:sale.sale,invoice_party:"
+msgid "Invoice Party"
+msgstr ""
+
+msgctxt "field:sale.sale,invoice_state:"
+msgid "Invoice State"
+msgstr ""
+
+msgctxt "field:sale.sale,invoices:"
+msgid "Invoices"
+msgstr ""
+
+msgctxt "field:sale.sale,invoices_ignored:"
+msgid "Ignored Invoices"
+msgstr ""
+
+msgctxt "field:sale.sale,invoices_recreated:"
+msgid "Recreated Invoices"
+msgstr ""
+
+msgctxt "field:sale.sale,lines:"
+msgid "Lines"
+msgstr ""
+
+msgctxt "field:sale.sale,moves:"
+msgid "Moves"
+msgstr ""
+
+msgctxt "field:sale.sale,number:"
+msgid "Number"
+msgstr ""
+
+msgctxt "field:sale.sale,origin:"
+msgid "Origin"
+msgstr ""
+
+msgctxt "field:sale.sale,party:"
+msgid "Party"
+msgstr ""
+
+msgctxt "field:sale.sale,party_lang:"
+msgid "Party Language"
+msgstr ""
+
+msgctxt "field:sale.sale,payment_term:"
+msgid "Payment Term"
+msgstr ""
+
+msgctxt "field:sale.sale,quoted_by:"
+msgid "Quoted By"
+msgstr ""
+
+msgctxt "field:sale.sale,reference:"
+msgid "Reference"
+msgstr ""
+
+msgctxt "field:sale.sale,sale_date:"
+msgid "Sale Date"
+msgstr ""
+
+msgctxt "field:sale.sale,shipment_address:"
+msgid "Shipment Address"
+msgstr ""
+
+msgctxt "field:sale.sale,shipment_method:"
+msgid "Shipment Method"
+msgstr ""
+
+msgctxt "field:sale.sale,shipment_party:"
+msgid "Shipment Party"
+msgstr ""
+
+msgctxt "field:sale.sale,shipment_returns:"
+msgid "Shipment Returns"
+msgstr "Devolución"
+
+msgctxt "field:sale.sale,shipment_state:"
+msgid "Shipment State"
+msgstr "Estado de envío"
+
+msgctxt "field:sale.sale,shipments:"
+msgid "Shipments"
+msgstr "Envíos"
+
+#, fuzzy
+msgctxt "field:sale.sale,shipping_date:"
+msgid "Shipping Date"
+msgstr "Estado de envío"
+
+msgctxt "field:sale.sale,state:"
+msgid "State"
+msgstr ""
+
+msgctxt "field:sale.sale,tax_amount:"
+msgid "Tax"
+msgstr ""
+
+msgctxt "field:sale.sale,tax_amount_cache:"
+msgid "Tax Cache"
+msgstr ""
+
+msgctxt "field:sale.sale,total_amount:"
+msgid "Total"
+msgstr ""
+
+#, fuzzy
+msgctxt "field:sale.sale,total_amount_cache:"
+msgid "Total Cache"
+msgstr "Base sin impuesto cache"
+
+msgctxt "field:sale.sale,untaxed_amount:"
+msgid "Untaxed"
+msgstr "Base sin Impuesto"
+
+msgctxt "field:sale.sale,untaxed_amount_cache:"
+msgid "Untaxed Cache"
+msgstr "Base sin impuesto cache"
+
+msgctxt "field:sale.sale,warehouse:"
+msgid "Warehouse"
+msgstr "Bodega"
+
+msgctxt "field:sale.sale-ignored-account.invoice,invoice:"
+msgid "Invoice"
+msgstr ""
+
+msgctxt "field:sale.sale-ignored-account.invoice,sale:"
+msgid "Sale"
+msgstr ""
+
+msgctxt "field:sale.sale-recreated-account.invoice,invoice:"
+msgid "Invoice"
+msgstr ""
+
+msgctxt "field:sale.sale-recreated-account.invoice,sale:"
+msgid "Sale"
+msgstr ""
+
+msgctxt "field:stock.move,sale:"
+msgid "Sale"
+msgstr ""
+
+#, fuzzy
+msgctxt "field:stock.move,sale_exception_state:"
+msgid "Exception State"
+msgstr "Estado excepción"
+
+msgctxt "help:product.configuration,default_lead_time:"
+msgid ""
+"The time from confirming the sales order to sending the products.\n"
+"Used for products without a lead time."
+msgstr ""
+
+msgctxt "help:product.product,lead_time:"
+msgid ""
+"The time from confirming the sales order to sending the products.\n"
+"If empty the default lead time from the configuration is used."
+msgstr ""
+
+msgctxt "help:product.template,lead_time:"
+msgid ""
+"The time from confirming the sales order to sending the products.\n"
+"If empty the default lead time from the configuration is used."
+msgstr ""
+
+msgctxt "help:sale.configuration,sale_process_after:"
+msgid ""
+"The grace period during which confirmed sale can still be reset to draft.\n"
+"Applied if a worker queue is activated."
+msgstr ""
+
+msgctxt "help:sale.handle.invoice.exception.ask,recreate_invoices:"
+msgid ""
+"The selected invoices will be recreated. The other ones will be ignored."
+msgstr ""
+
+msgctxt "help:sale.sale,shipping_date:"
+msgid "When the shipping of goods should start."
+msgstr ""
+
+msgctxt "model:ir.action,name:act_invoice_form"
+msgid "Invoices"
+msgstr ""
+
+msgctxt "model:ir.action,name:act_open_customer"
+msgid "Parties associated to Sales"
+msgstr ""
+
+msgctxt "model:ir.action,name:act_product"
+msgid "Products"
+msgstr ""
+
+msgctxt "model:ir.action,name:act_reporting_category"
+msgid "Sales per Category"
+msgstr ""
+
+msgctxt "model:ir.action,name:act_reporting_category_time_series"
+msgid "Sales per Category"
+msgstr ""
+
+msgctxt "model:ir.action,name:act_reporting_category_tree"
+msgid "Sales per Category"
+msgstr ""
+
+msgctxt "model:ir.action,name:act_reporting_country_subdivision_time_series"
+msgid "Sales per Subdivision"
+msgstr ""
+
+msgctxt "model:ir.action,name:act_reporting_country_time_series"
+msgid "Sales per Country"
+msgstr ""
+
+msgctxt "model:ir.action,name:act_reporting_customer"
+msgid "Sales per Customer"
+msgstr ""
+
+msgctxt "model:ir.action,name:act_reporting_customer_time_series"
+msgid "Sales per Customer"
+msgstr ""
+
+msgctxt "model:ir.action,name:act_reporting_product"
+msgid "Sales per Product"
+msgstr ""
+
+msgctxt "model:ir.action,name:act_reporting_product_time_series"
+msgid "Sales per Product"
+msgstr ""
+
+msgctxt "model:ir.action,name:act_reporting_region"
+msgid "Sales per Region"
+msgstr ""
+
+msgctxt "model:ir.action,name:act_return_form"
+msgid "Returns"
+msgstr ""
+
+msgctxt "model:ir.action,name:act_sale_configuration_form"
+msgid "Configuration"
+msgstr ""
+
+msgctxt "model:ir.action,name:act_sale_form"
+msgid "Sales"
+msgstr ""
+
+msgctxt "model:ir.action,name:act_sale_form2"
+msgid "Sales"
+msgstr ""
+
+msgctxt "model:ir.action,name:act_sale_invoice_relate"
+msgid "Sales"
+msgstr ""
+
+msgctxt "model:ir.action,name:act_sale_move_relate"
+msgid "Moves"
+msgstr ""
+
+msgctxt "model:ir.action,name:act_sale_shipment_returns_relate"
+msgid "Sales"
+msgstr ""
+
+msgctxt "model:ir.action,name:act_sale_shipments_relate"
+msgid "Sales"
+msgstr ""
+
+#, fuzzy
+msgctxt "model:ir.action,name:act_shipment_form"
+msgid "Shipments"
+msgstr "Envíos"
+
+msgctxt "model:ir.action,name:report_sale"
+msgid "Sale"
+msgstr ""
+
+msgctxt "model:ir.action,name:wizard_invoice_handle_exception"
+msgid "Handle Invoice Exception"
+msgstr ""
+
+msgctxt "model:ir.action,name:wizard_modify_header"
+msgid "Modify Header"
+msgstr ""
+
+msgctxt "model:ir.action,name:wizard_reporting_region_open"
+msgid "Open Region"
+msgstr ""
+
+#, fuzzy
+msgctxt "model:ir.action,name:wizard_return_sale"
+msgid "Return Sale"
+msgstr "Crear devolución de venta"
+
+msgctxt "model:ir.action,name:wizard_shipment_handle_exception"
+msgid "Handle Shipment Exception"
+msgstr ""
+
+msgctxt "model:ir.action.act_window.domain,name:act_sale_form_domain_all"
+msgid "All"
+msgstr ""
+
+msgctxt ""
+"model:ir.action.act_window.domain,name:act_sale_form_domain_confirmed"
+msgid "Confirmed"
+msgstr ""
+
+msgctxt "model:ir.action.act_window.domain,name:act_sale_form_domain_draft"
+msgid "Draft"
+msgstr ""
+
+#, fuzzy
+msgctxt ""
+"model:ir.action.act_window.domain,name:act_sale_form_domain_exception"
+msgid "Exception"
+msgstr "Estado excepción"
+
+msgctxt ""
+"model:ir.action.act_window.domain,name:act_sale_form_domain_processing"
+msgid "Processing"
+msgstr ""
+
+#, fuzzy
+msgctxt ""
+"model:ir.action.act_window.domain,name:act_sale_form_domain_quotation"
+msgid "Quotation"
+msgstr "Cotización"
+
+msgctxt "model:ir.message,text:msg_erase_party_pending_sale"
+msgid ""
+"You cannot erase party \"%(party)s\" while they have pending sales with "
+"company \"%(company)s\"."
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_sale_customer_location_required"
+msgid ""
+"To process sale \"%(sale)s\" you must set a customer location on party "
+"\"%(party)s\"."
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_sale_delete_cancel"
+msgid "To delete sale \"%(sale)s\" you must cancel it."
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_sale_invalid_method"
+msgid ""
+"You cannot use together invoice \"%(invoice_method)s\" and shipment "
+"\"%(shipment_method)s\" on sale \"%(sale)s\"."
+msgstr ""
+
+msgctxt ""
+"model:ir.message,text:msg_sale_invoice_address_required_for_quotation"
+msgid "To get a quote for sale \"%(sale)s\" you must enter an invoice address."
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_sale_invoice_reset_draft"
+msgid ""
+"You cannot reset invoice \"%(invoice)s\" to draft because it was generated "
+"by a sale."
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_sale_line_delete_cancel_draft"
+msgid ""
+"To delete line \"%(line)s\" you must cancel or reset to draft sale "
+"\"%(sale)s\"."
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_sale_missing_account_revenue"
+msgid "To invoice sale \"%(sale)s\" you must configure a default account revenue."
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_sale_modify_header_draft"
+msgid "To modify the header of sale \"%(sale)s\", it must be in \"draft\" state."
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_sale_move_reset_draft"
+msgid ""
+"You cannot reset move \"%(move)s\" to draft because it was generated by a "
+"sale."
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_sale_product_missing_account_revenue"
+msgid ""
+"To invoice sale \"%(sale)s\" you must define an account revenue for product "
+"\"%(product)s\"."
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_sale_reporting_company"
+msgid "Company"
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_sale_reporting_currency"
+msgid "Currency"
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_sale_reporting_currency_digits"
+msgid "Currency Digits"
+msgstr ""
+
+#, fuzzy
+msgctxt "model:ir.message,text:msg_sale_reporting_number"
+msgid "#"
+msgstr "#"
+
+msgctxt "model:ir.message,text:msg_sale_reporting_number_help"
+msgid "Number of sales"
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_sale_reporting_revenue"
+msgid "Revenue"
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_sale_reporting_revenue_trend"
+msgid "Revenue Trend"
+msgstr ""
+
+msgctxt ""
+"model:ir.message,text:msg_sale_shipment_address_required_for_quotation"
+msgid "To get a quote for sale \"%(sale)s\" you must enter a shipment address."
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_sale_warehouse_required_for_quotation"
+msgid "To get a quote for sale \"%(sale)s\" you must enter a warehouse."
+msgstr ""
+
+msgctxt "model:ir.model.button,string:sale_cancel_button"
+msgid "Cancel"
+msgstr ""
+
+msgctxt "model:ir.model.button,string:sale_confirm_button"
+msgid "Confirm"
+msgstr ""
+
+msgctxt "model:ir.model.button,string:sale_draft_button"
+msgid "Draft"
+msgstr ""
+
+msgctxt "model:ir.model.button,string:sale_handle_invoice_exception_button"
+msgid "Handle Invoice Exception"
+msgstr ""
+
+msgctxt "model:ir.model.button,string:sale_handle_shipment_exception_button"
+msgid "Handle Shipment Exception"
+msgstr ""
+
+msgctxt "model:ir.model.button,string:sale_modify_header_button"
+msgid "Modify Header"
+msgstr ""
+
+msgctxt "model:ir.model.button,string:sale_process_button"
+msgid "Process"
+msgstr ""
+
+msgctxt "model:ir.model.button,string:sale_quote_button"
+msgid "Quote"
+msgstr ""
+
+msgctxt "model:ir.rule.group,name:rule_group_reporting_category_companies"
+msgid "User in companies"
+msgstr ""
+
+msgctxt ""
+"model:ir.rule.group,name:rule_group_reporting_category_time_series_companies"
+msgid "User in companies"
+msgstr ""
+
+msgctxt ""
+"model:ir.rule.group,name:rule_group_reporting_country_subdivision_time_series_companies"
+msgid "User in companies"
+msgstr ""
+
+msgctxt ""
+"model:ir.rule.group,name:rule_group_reporting_country_time_series_companies"
+msgid "User in companies"
+msgstr ""
+
+msgctxt "model:ir.rule.group,name:rule_group_reporting_customer_companies"
+msgid "User in companies"
+msgstr ""
+
+msgctxt ""
+"model:ir.rule.group,name:rule_group_reporting_customer_time_series_companies"
+msgid "User in companies"
+msgstr ""
+
+msgctxt "model:ir.rule.group,name:rule_group_reporting_product_companies"
+msgid "User in companies"
+msgstr ""
+
+msgctxt ""
+"model:ir.rule.group,name:rule_group_reporting_product_time_series_companies"
+msgid "User in companies"
+msgstr ""
+
+msgctxt "model:ir.rule.group,name:rule_group_reporting_region_companies"
+msgid "User in companies"
+msgstr ""
+
+msgctxt "model:ir.rule.group,name:rule_group_sale_companies"
+msgid "User in companies"
+msgstr ""
+
+msgctxt "model:ir.sequence,name:sequence_sale"
+msgid "Sale"
+msgstr ""
+
+msgctxt "model:ir.sequence.type,name:sequence_type_sale"
+msgid "Sale"
+msgstr ""
+
+msgctxt "model:ir.ui.menu,name:menu_configuration"
+msgid "Configuration"
+msgstr ""
+
+msgctxt "model:ir.ui.menu,name:menu_customer"
+msgid "Associated to Sales"
+msgstr ""
+
+msgctxt "model:ir.ui.menu,name:menu_product"
+msgid "Products"
+msgstr ""
+
+msgctxt "model:ir.ui.menu,name:menu_reporting"
+msgid "Reporting"
+msgstr ""
+
+msgctxt "model:ir.ui.menu,name:menu_reporting_sale"
+msgid "Sales"
+msgstr ""
+
+msgctxt "model:ir.ui.menu,name:menu_sale"
+msgid "Sales"
+msgstr ""
+
+msgctxt "model:ir.ui.menu,name:menu_sale_configuration"
+msgid "Configuration"
+msgstr ""
+
+msgctxt "model:ir.ui.menu,name:menu_sale_form"
+msgid "Sales"
+msgstr ""
+
+msgctxt "model:product.configuration.default_lead_time,name:"
+msgid "Product Default Lead Time"
+msgstr ""
+
+msgctxt "model:product.sale.context,name:"
+msgid "Product Sale Context"
+msgstr ""
+
+msgctxt "model:res.group,name:group_sale"
+msgid "Sales"
+msgstr ""
+
+msgctxt "model:res.group,name:group_sale_admin"
+msgid "Sales Administrator"
+msgstr ""
+
+msgctxt "model:sale.configuration,name:"
+msgid "Sale Configuration"
+msgstr ""
+
+msgctxt "model:sale.configuration.sale_method,name:"
+msgid "Sale Configuration Sale Method"
+msgstr ""
+
+msgctxt "model:sale.configuration.sequence,name:"
+msgid "Sale Configuration Sequence"
+msgstr ""
+
+msgctxt "model:sale.handle.invoice.exception.ask,name:"
+msgid "Handle Invoice Exception"
+msgstr ""
+
+msgctxt "model:sale.handle.shipment.exception.ask,name:"
+msgid "Handle Shipment Exception"
+msgstr ""
+
+msgctxt "model:sale.line,name:"
+msgid "Sale Line"
+msgstr ""
+
+msgctxt "model:sale.line-account.tax,name:"
+msgid "Sale Line - Tax"
+msgstr ""
+
+msgctxt "model:sale.line-ignored-stock.move,name:"
+msgid "Sale Line - Ignored Move"
+msgstr ""
+
+msgctxt "model:sale.line-recreated-stock.move,name:"
+msgid "Sale Line - Recreated Move"
+msgstr ""
+
+msgctxt "model:sale.reporting.category,name:"
+msgid "Sale Reporting per Category"
+msgstr ""
+
+msgctxt "model:sale.reporting.category.time_series,name:"
+msgid "Sale Reporting per Category"
+msgstr ""
+
+msgctxt "model:sale.reporting.category.tree,name:"
+msgid "Sale Reporting per Category"
+msgstr ""
+
+msgctxt "model:sale.reporting.context,name:"
+msgid "Sale Reporting Context"
+msgstr ""
+
+msgctxt "model:sale.reporting.country,name:"
+msgid "Sale Reporting per Country"
+msgstr ""
+
+msgctxt "model:sale.reporting.country.subdivision,name:"
+msgid "Sale Reporting per Subdivision"
+msgstr ""
+
+msgctxt "model:sale.reporting.country.subdivision.time_series,name:"
+msgid "Sale Reporting per Subdivision"
+msgstr ""
+
+msgctxt "model:sale.reporting.country.time_series,name:"
+msgid "Sale Reporting per Country"
+msgstr ""
+
+msgctxt "model:sale.reporting.customer,name:"
+msgid "Sale Reporting per Customer"
+msgstr ""
+
+msgctxt "model:sale.reporting.customer.time_series,name:"
+msgid "Sale Reporting per Customer"
+msgstr ""
+
+msgctxt "model:sale.reporting.product,name:"
+msgid "Sale Reporting per Product"
+msgstr ""
+
+msgctxt "model:sale.reporting.product.time_series,name:"
+msgid "Sale Reporting per Product"
+msgstr ""
+
+msgctxt "model:sale.reporting.region,name:"
+msgid "Sale Reporting per Region"
+msgstr ""
+
+msgctxt "model:sale.return_sale.start,name:"
+msgid "Return Sale"
+msgstr "Crear devolución de venta"
+
+msgctxt "model:sale.sale,name:"
+msgid "Sale"
+msgstr ""
+
+msgctxt "model:sale.sale-ignored-account.invoice,name:"
+msgid "Sale - Ignored Invoice"
+msgstr ""
+
+msgctxt "model:sale.sale-recreated-account.invoice,name:"
+msgid "Sale - Recreated Invoice"
+msgstr ""
+
+msgctxt "report:sale.sale:"
+msgid ":"
+msgstr ""
+
+msgctxt "report:sale.sale:"
+msgid "Amount"
+msgstr ""
+
+msgctxt "report:sale.sale:"
+msgid "Date:"
+msgstr ""
+
+msgctxt "report:sale.sale:"
+msgid "Description"
+msgstr ""
+
+msgctxt "report:sale.sale:"
+msgid "Description:"
+msgstr ""
+
+msgctxt "report:sale.sale:"
+msgid "Draft Sale Order"
+msgstr "Pedido de venta en borrador"
+
+msgctxt "report:sale.sale:"
+msgid "Quantity"
+msgstr ""
+
+msgctxt "report:sale.sale:"
+msgid "Quotation N°:"
+msgstr "Cotización Nº:"
+
+msgctxt "report:sale.sale:"
+msgid "Reference:"
+msgstr ""
+
+msgctxt "report:sale.sale:"
+msgid "Sale Order N°:"
+msgstr "Pedido Nº:"
+
+msgctxt "report:sale.sale:"
+msgid "Taxes"
+msgstr ""
+
+msgctxt "report:sale.sale:"
+msgid "Taxes:"
+msgstr ""
+
+msgctxt "report:sale.sale:"
+msgid "Total (excl. taxes):"
+msgstr "Total (sin impuestos):"
+
+msgctxt "report:sale.sale:"
+msgid "Total:"
+msgstr ""
+
+msgctxt "report:sale.sale:"
+msgid "Unit Price"
+msgstr "Precio unitario"
+
+msgctxt "selection:account.invoice,sale_exception_state:"
+msgid "Ignored"
+msgstr ""
+
+msgctxt "selection:account.invoice,sale_exception_state:"
+msgid "Recreated"
+msgstr ""
+
+msgctxt "selection:sale.line,type:"
+msgid "Comment"
+msgstr ""
+
+msgctxt "selection:sale.line,type:"
+msgid "Line"
+msgstr ""
+
+msgctxt "selection:sale.line,type:"
+msgid "Subtotal"
+msgstr ""
+
+msgctxt "selection:sale.line,type:"
+msgid "Title"
+msgstr ""
+
+msgctxt "selection:sale.reporting.context,period:"
+msgid "Day"
+msgstr ""
+
+msgctxt "selection:sale.reporting.context,period:"
+msgid "Month"
+msgstr ""
+
+msgctxt "selection:sale.reporting.context,period:"
+msgid "Year"
+msgstr ""
+
+msgctxt "selection:sale.sale,invoice_method:"
+msgid "Manual"
+msgstr ""
+
+msgctxt "selection:sale.sale,invoice_method:"
+msgid "On Order Processed"
+msgstr ""
+
+msgctxt "selection:sale.sale,invoice_method:"
+msgid "On Shipment Sent"
+msgstr ""
+
+msgctxt "selection:sale.sale,invoice_state:"
+msgid "Exception"
+msgstr ""
+
+msgctxt "selection:sale.sale,invoice_state:"
+msgid "None"
+msgstr ""
+
+msgctxt "selection:sale.sale,invoice_state:"
+msgid "Paid"
+msgstr ""
+
+msgctxt "selection:sale.sale,invoice_state:"
+msgid "Waiting"
+msgstr ""
+
+msgctxt "selection:sale.sale,shipment_method:"
+msgid "Manual"
+msgstr ""
+
+msgctxt "selection:sale.sale,shipment_method:"
+msgid "On Invoice Paid"
+msgstr ""
+
+msgctxt "selection:sale.sale,shipment_method:"
+msgid "On Order Processed"
+msgstr ""
+
+msgctxt "selection:sale.sale,shipment_state:"
+msgid "Exception"
+msgstr ""
+
+msgctxt "selection:sale.sale,shipment_state:"
+msgid "None"
+msgstr ""
+
+msgctxt "selection:sale.sale,shipment_state:"
+msgid "Sent"
+msgstr ""
+
+msgctxt "selection:sale.sale,shipment_state:"
+msgid "Waiting"
+msgstr ""
+
+msgctxt "selection:sale.sale,state:"
+msgid "Cancelled"
+msgstr ""
+
+msgctxt "selection:sale.sale,state:"
+msgid "Confirmed"
+msgstr ""
+
+msgctxt "selection:sale.sale,state:"
+msgid "Done"
+msgstr ""
+
+msgctxt "selection:sale.sale,state:"
+msgid "Draft"
+msgstr ""
+
+msgctxt "selection:sale.sale,state:"
+msgid "Processing"
+msgstr ""
+
+msgctxt "selection:sale.sale,state:"
+msgid "Quotation"
+msgstr "Cotización"
+
+msgctxt "selection:stock.move,sale_exception_state:"
+msgid "Ignored"
+msgstr ""
+
+msgctxt "selection:stock.move,sale_exception_state:"
+msgid "Recreated"
+msgstr ""
+
+msgctxt "view:party.party:"
+msgid "Sale"
+msgstr ""
+
+msgctxt "view:product.template:"
+msgid "Customers"
+msgstr ""
+
+msgctxt "view:sale.handle.invoice.exception.ask:"
+msgid "Choose invoices to recreate:"
+msgstr ""
+
+msgctxt "view:sale.handle.shipment.exception.ask:"
+msgid "Choose move to recreate:"
+msgstr ""
+
+msgctxt "view:sale.line:"
+msgid "General"
+msgstr ""
+
+msgctxt "view:sale.line:"
+msgid "Notes"
+msgstr ""
+
+msgctxt "view:sale.line:"
+msgid "Taxes"
+msgstr ""
+
+#, fuzzy
+msgctxt "view:sale.return_sale.start:"
+msgid "Are you sure to return these/this sale(s)?"
+msgstr "Está seguro que desea devolver esta(s) venta(s)?"
+
+msgctxt "view:sale.sale:"
+msgid "Other Info"
+msgstr ""
+
+msgctxt "view:sale.sale:"
+msgid "Sale"
+msgstr ""
+
+msgctxt "wizard_button:sale.handle.invoice.exception,ask,end:"
+msgid "Cancel"
+msgstr ""
+
+msgctxt "wizard_button:sale.handle.invoice.exception,ask,handle:"
+msgid "OK"
+msgstr ""
+
+msgctxt "wizard_button:sale.handle.shipment.exception,ask,end:"
+msgid "Cancel"
+msgstr ""
+
+msgctxt "wizard_button:sale.handle.shipment.exception,ask,handle:"
+msgid "OK"
+msgstr ""
+
+msgctxt "wizard_button:sale.modify_header,start,end:"
+msgid "Cancel"
+msgstr ""
+
+msgctxt "wizard_button:sale.modify_header,start,modify:"
+msgid "Modify"
+msgstr ""
+
+msgctxt "wizard_button:sale.return_sale,start,end:"
+msgid "Cancel"
+msgstr ""
+
+msgctxt "wizard_button:sale.return_sale,start,return_:"
+msgid "Return"
+msgstr ""
diff --git a/modules/sale/locale/et.po b/modules/sale/locale/et.po
new file mode 100644
index 0000000000..40a10fb86b
--- /dev/null
+++ b/modules/sale/locale/et.po
@@ -0,0 +1,1388 @@
+#
+msgid ""
+msgstr "Content-Type: text/plain; charset=utf-8\n"
+
+msgctxt "field:account.invoice,sale_exception_state:"
+msgid "Exception State"
+msgstr "Erandi staatus"
+
+msgctxt "field:account.invoice,sales:"
+msgid "Sales"
+msgstr "Müük"
+
+#, fuzzy
+msgctxt "field:product.configuration,default_lead_time:"
+msgid "Default Lead Time"
+msgstr "Täitmise aeg"
+
+#, fuzzy
+msgctxt "field:product.configuration.default_lead_time,company:"
+msgid "Company"
+msgstr "Ettevõte"
+
+#, fuzzy
+msgctxt "field:product.configuration.default_lead_time,default_lead_time:"
+msgid "Default Lead Time"
+msgstr "Täitmise aeg"
+
+msgctxt "field:product.product,lead_time:"
+msgid "Lead Time"
+msgstr "Täitmise aeg"
+
+msgctxt "field:product.product,salable:"
+msgid "Salable"
+msgstr "Müüdav"
+
+msgctxt "field:product.product,sale_price_uom:"
+msgid "Sale Price"
+msgstr "Müügihind"
+
+msgctxt "field:product.product,sale_uom:"
+msgid "Sale UOM"
+msgstr "Müügiühik"
+
+#, fuzzy
+msgctxt "field:product.sale.context,company:"
+msgid "Company"
+msgstr "Ettevõte"
+
+#, fuzzy
+msgctxt "field:product.sale.context,currency:"
+msgid "Currency"
+msgstr "Valuuta"
+
+#, fuzzy
+msgctxt "field:product.sale.context,customer:"
+msgid "Customer"
+msgstr "Klient"
+
+#, fuzzy
+msgctxt "field:product.sale.context,locations:"
+msgid "Warehouses"
+msgstr "Ladu"
+
+#, fuzzy
+msgctxt "field:product.sale.context,quantity:"
+msgid "Quantity"
+msgstr "Kogus"
+
+#, fuzzy
+msgctxt "field:product.sale.context,sale_date:"
+msgid "Sale Date"
+msgstr "Müügi kuupäev"
+
+msgctxt "field:product.sale.context,stock_date_end:"
+msgid "Stock End Date"
+msgstr ""
+
+msgctxt "field:product.template,lead_time:"
+msgid "Lead Time"
+msgstr "Täitmise aeg"
+
+msgctxt "field:product.template,salable:"
+msgid "Salable"
+msgstr "Müüdav"
+
+msgctxt "field:product.template,sale_uom:"
+msgid "Sale UOM"
+msgstr "Müügiühik"
+
+msgctxt "field:sale.configuration,sale_invoice_method:"
+msgid "Sale Invoice Method"
+msgstr "Müügiarve meetod"
+
+msgctxt "field:sale.configuration,sale_process_after:"
+msgid "Process Sale after"
+msgstr "Protsessi müüki pärast"
+
+msgctxt "field:sale.configuration,sale_sequence:"
+msgid "Sale Sequence"
+msgstr "Müügijärjestus"
+
+msgctxt "field:sale.configuration,sale_shipment_method:"
+msgid "Sale Shipment Method"
+msgstr "Tarnemeetod"
+
+msgctxt "field:sale.configuration.sale_method,sale_invoice_method:"
+msgid "Sale Invoice Method"
+msgstr "Müügiarve meetod"
+
+msgctxt "field:sale.configuration.sale_method,sale_shipment_method:"
+msgid "Sale Shipment Method"
+msgstr "Tarnemeetod"
+
+msgctxt "field:sale.configuration.sequence,company:"
+msgid "Company"
+msgstr "Ettevõte"
+
+msgctxt "field:sale.configuration.sequence,sale_sequence:"
+msgid "Sale Sequence"
+msgstr "Müügi järjestus"
+
+msgctxt "field:sale.handle.invoice.exception.ask,domain_invoices:"
+msgid "Domain Invoices"
+msgstr "Domeeni arved"
+
+msgctxt "field:sale.handle.invoice.exception.ask,recreate_invoices:"
+msgid "Recreate Invoices"
+msgstr "Taasloo arved"
+
+msgctxt "field:sale.handle.shipment.exception.ask,domain_moves:"
+msgid "Domain Moves"
+msgstr "Domeeni kanded"
+
+msgctxt "field:sale.handle.shipment.exception.ask,recreate_moves:"
+msgid "Recreate Moves"
+msgstr "Taasloo kanded"
+
+#, fuzzy
+msgctxt "field:sale.line,actual_quantity:"
+msgid "Actual Quantity"
+msgstr "Kogus"
+
+msgctxt "field:sale.line,amount:"
+msgid "Amount"
+msgstr "Summa"
+
+#, fuzzy
+msgctxt "field:sale.line,company:"
+msgid "Company"
+msgstr "Ettevõte"
+
+#, fuzzy
+msgctxt "field:sale.line,currency:"
+msgid "Currency"
+msgstr "Valuuta"
+
+msgctxt "field:sale.line,description:"
+msgid "Description"
+msgstr "Kirjeldus"
+
+msgctxt "field:sale.line,from_location:"
+msgid "From Location"
+msgstr "Asukohast"
+
+msgctxt "field:sale.line,invoice_lines:"
+msgid "Invoice Lines"
+msgstr "Arve read"
+
+msgctxt "field:sale.line,move_done:"
+msgid "Moves Done"
+msgstr "Kanded tehtud"
+
+msgctxt "field:sale.line,move_exception:"
+msgid "Moves Exception"
+msgstr "Kannete erand"
+
+msgctxt "field:sale.line,moves:"
+msgid "Moves"
+msgstr "Kanded"
+
+msgctxt "field:sale.line,moves_ignored:"
+msgid "Ignored Moves"
+msgstr "Ignoreeritud kanded"
+
+msgctxt "field:sale.line,moves_recreated:"
+msgid "Recreated Moves"
+msgstr "Taasloodud kanded"
+
+msgctxt "field:sale.line,note:"
+msgid "Note"
+msgstr "Märkus"
+
+msgctxt "field:sale.line,product:"
+msgid "Product"
+msgstr "Toode"
+
+msgctxt "field:sale.line,product_uom_category:"
+msgid "Product Uom Category"
+msgstr "Toote ühiku kategooria"
+
+msgctxt "field:sale.line,quantity:"
+msgid "Quantity"
+msgstr "Kogus"
+
+msgctxt "field:sale.line,sale:"
+msgid "Sale"
+msgstr "Müük"
+
+msgctxt "field:sale.line,sale_state:"
+msgid "Sale State"
+msgstr "Müügi staatus"
+
+msgctxt "field:sale.line,shipping_date:"
+msgid "Shipping Date"
+msgstr "Tarne kuupäev"
+
+msgctxt "field:sale.line,summary:"
+msgid "Summary"
+msgstr ""
+
+msgctxt "field:sale.line,taxes:"
+msgid "Taxes"
+msgstr "Maksud"
+
+msgctxt "field:sale.line,to_location:"
+msgid "To Location"
+msgstr "Asukohta"
+
+msgctxt "field:sale.line,type:"
+msgid "Type"
+msgstr "Tüüp"
+
+msgctxt "field:sale.line,unit:"
+msgid "Unit"
+msgstr "Ühik"
+
+msgctxt "field:sale.line,unit_digits:"
+msgid "Unit Digits"
+msgstr "Ühiku numbriline arv"
+
+msgctxt "field:sale.line,unit_price:"
+msgid "Unit Price"
+msgstr "Ühiku hind"
+
+msgctxt "field:sale.line,warehouse:"
+msgid "Warehouse"
+msgstr "Ladu"
+
+msgctxt "field:sale.line-account.tax,line:"
+msgid "Sale Line"
+msgstr "Müügi rida"
+
+msgctxt "field:sale.line-account.tax,tax:"
+msgid "Tax"
+msgstr "Maks"
+
+msgctxt "field:sale.line-ignored-stock.move,move:"
+msgid "Move"
+msgstr "Kanne"
+
+msgctxt "field:sale.line-ignored-stock.move,sale_line:"
+msgid "Sale Line"
+msgstr "Müügi rida"
+
+msgctxt "field:sale.line-recreated-stock.move,move:"
+msgid "Move"
+msgstr "Kanne"
+
+msgctxt "field:sale.line-recreated-stock.move,sale_line:"
+msgid "Sale Line"
+msgstr "Müügi rida"
+
+msgctxt "field:sale.reporting.category,category:"
+msgid "Category"
+msgstr "Kategooria"
+
+msgctxt "field:sale.reporting.category,time_series:"
+msgid "Time Series"
+msgstr "Aegrida"
+
+msgctxt "field:sale.reporting.category.time_series,category:"
+msgid "Category"
+msgstr "Kategooria"
+
+msgctxt "field:sale.reporting.category.time_series,date:"
+msgid "Date"
+msgstr "Kuupäev"
+
+msgctxt "field:sale.reporting.category.tree,children:"
+msgid "Children"
+msgstr "Alamjaotus"
+
+msgctxt "field:sale.reporting.category.tree,currency_digits:"
+msgid "Currency Digits"
+msgstr "Valuuta numbriline väärtus"
+
+msgctxt "field:sale.reporting.category.tree,name:"
+msgid "Name"
+msgstr "Nimi"
+
+msgctxt "field:sale.reporting.category.tree,parent:"
+msgid "Parent"
+msgstr "Ülemjaotus"
+
+msgctxt "field:sale.reporting.category.tree,revenue:"
+msgid "Revenue"
+msgstr "Müügitulu"
+
+msgctxt "field:sale.reporting.context,company:"
+msgid "Company"
+msgstr "Ettevõte"
+
+msgctxt "field:sale.reporting.context,from_date:"
+msgid "From Date"
+msgstr "Kuupäevast"
+
+msgctxt "field:sale.reporting.context,period:"
+msgid "Period"
+msgstr "Periood"
+
+msgctxt "field:sale.reporting.context,to_date:"
+msgid "To Date"
+msgstr "Kuupäevani"
+
+msgctxt "field:sale.reporting.context,warehouse:"
+msgid "Warehouse"
+msgstr "Ladu"
+
+msgctxt "field:sale.reporting.country,country:"
+msgid "Country"
+msgstr "Riik"
+
+msgctxt "field:sale.reporting.country,time_series:"
+msgid "Time Series"
+msgstr "Aegrida"
+
+msgctxt "field:sale.reporting.country.subdivision,country:"
+msgid "Country"
+msgstr "Riik"
+
+msgctxt "field:sale.reporting.country.subdivision,subdivision:"
+msgid "Subdivision"
+msgstr "Alamjaotus"
+
+msgctxt "field:sale.reporting.country.subdivision,time_series:"
+msgid "Time Series"
+msgstr "Aegrida"
+
+msgctxt "field:sale.reporting.country.subdivision.time_series,country:"
+msgid "Country"
+msgstr "Riik"
+
+msgctxt "field:sale.reporting.country.subdivision.time_series,date:"
+msgid "Date"
+msgstr "Kuupäev"
+
+msgctxt "field:sale.reporting.country.subdivision.time_series,subdivision:"
+msgid "Subdivision"
+msgstr "Alamjaotus"
+
+msgctxt "field:sale.reporting.country.time_series,country:"
+msgid "Country"
+msgstr "Riik"
+
+msgctxt "field:sale.reporting.country.time_series,date:"
+msgid "Date"
+msgstr "Kuupäev"
+
+msgctxt "field:sale.reporting.customer,customer:"
+msgid "Customer"
+msgstr "Klient"
+
+msgctxt "field:sale.reporting.customer,time_series:"
+msgid "Time Series"
+msgstr "Aegrida"
+
+msgctxt "field:sale.reporting.customer.time_series,customer:"
+msgid "Customer"
+msgstr "Klient"
+
+msgctxt "field:sale.reporting.customer.time_series,date:"
+msgid "Date"
+msgstr "Kuupäev"
+
+msgctxt "field:sale.reporting.product,product:"
+msgid "Product"
+msgstr "Toode"
+
+msgctxt "field:sale.reporting.product,time_series:"
+msgid "Time Series"
+msgstr "Aegrida"
+
+msgctxt "field:sale.reporting.product.time_series,date:"
+msgid "Date"
+msgstr "Kuupäev"
+
+msgctxt "field:sale.reporting.product.time_series,product:"
+msgid "Product"
+msgstr "Toode"
+
+msgctxt "field:sale.reporting.region,children:"
+msgid "Children"
+msgstr "Alamjaotus"
+
+msgctxt "field:sale.reporting.region,parent:"
+msgid "Parent"
+msgstr "Ülem"
+
+msgctxt "field:sale.reporting.region,region:"
+msgid "Region"
+msgstr "Regioon"
+
+msgctxt "field:sale.sale,comment:"
+msgid "Comment"
+msgstr "Kommentaar"
+
+msgctxt "field:sale.sale,company:"
+msgid "Company"
+msgstr "Ettevõte"
+
+#, fuzzy
+msgctxt "field:sale.sale,confirmed_by:"
+msgid "Confirmed By"
+msgstr "Kinnitatud"
+
+msgctxt "field:sale.sale,contact:"
+msgid "Contact"
+msgstr ""
+
+msgctxt "field:sale.sale,currency:"
+msgid "Currency"
+msgstr "Valuuta"
+
+msgctxt "field:sale.sale,currency_digits:"
+msgid "Currency Digits"
+msgstr "Valuuta numbriline väärtus"
+
+msgctxt "field:sale.sale,description:"
+msgid "Description"
+msgstr "Kirjeldus"
+
+msgctxt "field:sale.sale,invoice_address:"
+msgid "Invoice Address"
+msgstr "Arve aadress"
+
+msgctxt "field:sale.sale,invoice_method:"
+msgid "Invoice Method"
+msgstr "Arve meetod"
+
+#, fuzzy
+msgctxt "field:sale.sale,invoice_party:"
+msgid "Invoice Party"
+msgstr "Arve staatus"
+
+msgctxt "field:sale.sale,invoice_state:"
+msgid "Invoice State"
+msgstr "Arve staatus"
+
+msgctxt "field:sale.sale,invoices:"
+msgid "Invoices"
+msgstr "Arved"
+
+msgctxt "field:sale.sale,invoices_ignored:"
+msgid "Ignored Invoices"
+msgstr "Ignoreeritud arved"
+
+msgctxt "field:sale.sale,invoices_recreated:"
+msgid "Recreated Invoices"
+msgstr "Taasloodud arved"
+
+msgctxt "field:sale.sale,lines:"
+msgid "Lines"
+msgstr "Read"
+
+msgctxt "field:sale.sale,moves:"
+msgid "Moves"
+msgstr "Kanded"
+
+msgctxt "field:sale.sale,number:"
+msgid "Number"
+msgstr "Number"
+
+msgctxt "field:sale.sale,origin:"
+msgid "Origin"
+msgstr "Päritolu"
+
+msgctxt "field:sale.sale,party:"
+msgid "Party"
+msgstr "Osapool"
+
+msgctxt "field:sale.sale,party_lang:"
+msgid "Party Language"
+msgstr "Osapoole keel"
+
+msgctxt "field:sale.sale,payment_term:"
+msgid "Payment Term"
+msgstr "Maksetingimus"
+
+#, fuzzy
+msgctxt "field:sale.sale,quoted_by:"
+msgid "Quoted By"
+msgstr "Pakkumus"
+
+msgctxt "field:sale.sale,reference:"
+msgid "Reference"
+msgstr "Viide"
+
+msgctxt "field:sale.sale,sale_date:"
+msgid "Sale Date"
+msgstr "Müügi kuupäev"
+
+msgctxt "field:sale.sale,shipment_address:"
+msgid "Shipment Address"
+msgstr "Tarneaadress"
+
+msgctxt "field:sale.sale,shipment_method:"
+msgid "Shipment Method"
+msgstr "Tarnemeetod"
+
+msgctxt "field:sale.sale,shipment_party:"
+msgid "Shipment Party"
+msgstr "Tarne osapool"
+
+msgctxt "field:sale.sale,shipment_returns:"
+msgid "Shipment Returns"
+msgstr "Tarne tagastus"
+
+msgctxt "field:sale.sale,shipment_state:"
+msgid "Shipment State"
+msgstr "Tarne staatus"
+
+msgctxt "field:sale.sale,shipments:"
+msgid "Shipments"
+msgstr "Tarned"
+
+#, fuzzy
+msgctxt "field:sale.sale,shipping_date:"
+msgid "Shipping Date"
+msgstr "Tarne kuupäev"
+
+msgctxt "field:sale.sale,state:"
+msgid "State"
+msgstr "Olek"
+
+msgctxt "field:sale.sale,tax_amount:"
+msgid "Tax"
+msgstr "Maks"
+
+msgctxt "field:sale.sale,tax_amount_cache:"
+msgid "Tax Cache"
+msgstr "Maksu vahemälu"
+
+msgctxt "field:sale.sale,total_amount:"
+msgid "Total"
+msgstr "Kokku"
+
+#, fuzzy
+msgctxt "field:sale.sale,total_amount_cache:"
+msgid "Total Cache"
+msgstr "Maksu vahemälu"
+
+msgctxt "field:sale.sale,untaxed_amount:"
+msgid "Untaxed"
+msgstr "Maksuvaba"
+
+msgctxt "field:sale.sale,untaxed_amount_cache:"
+msgid "Untaxed Cache"
+msgstr "Maksustamata vahemälu"
+
+msgctxt "field:sale.sale,warehouse:"
+msgid "Warehouse"
+msgstr "Ladu"
+
+msgctxt "field:sale.sale-ignored-account.invoice,invoice:"
+msgid "Invoice"
+msgstr "Arve"
+
+msgctxt "field:sale.sale-ignored-account.invoice,sale:"
+msgid "Sale"
+msgstr "Müük"
+
+msgctxt "field:sale.sale-recreated-account.invoice,invoice:"
+msgid "Invoice"
+msgstr "Arve"
+
+msgctxt "field:sale.sale-recreated-account.invoice,sale:"
+msgid "Sale"
+msgstr "Müük"
+
+msgctxt "field:stock.move,sale:"
+msgid "Sale"
+msgstr "Müük"
+
+msgctxt "field:stock.move,sale_exception_state:"
+msgid "Exception State"
+msgstr "Erandi olek"
+
+msgctxt "help:product.configuration,default_lead_time:"
+msgid ""
+"The time from confirming the sales order to sending the products.\n"
+"Used for products without a lead time."
+msgstr ""
+
+msgctxt "help:product.product,lead_time:"
+msgid ""
+"The time from confirming the sales order to sending the products.\n"
+"If empty the default lead time from the configuration is used."
+msgstr ""
+
+msgctxt "help:product.template,lead_time:"
+msgid ""
+"The time from confirming the sales order to sending the products.\n"
+"If empty the default lead time from the configuration is used."
+msgstr ""
+
+msgctxt "help:sale.configuration,sale_process_after:"
+msgid ""
+"The grace period during which confirmed sale can still be reset to draft.\n"
+"Applied if a worker queue is activated."
+msgstr ""
+
+msgctxt "help:sale.handle.invoice.exception.ask,recreate_invoices:"
+msgid ""
+"The selected invoices will be recreated. The other ones will be ignored."
+msgstr "Valitud arved taasluuakse. Teisi ignoreeritakse."
+
+msgctxt "help:sale.sale,shipping_date:"
+msgid "When the shipping of goods should start."
+msgstr ""
+
+msgctxt "model:ir.action,name:act_invoice_form"
+msgid "Invoices"
+msgstr "Arved"
+
+msgctxt "model:ir.action,name:act_open_customer"
+msgid "Parties associated to Sales"
+msgstr "Müügiga seotud osapooled"
+
+#, fuzzy
+msgctxt "model:ir.action,name:act_product"
+msgid "Products"
+msgstr "Toode"
+
+msgctxt "model:ir.action,name:act_reporting_category"
+msgid "Sales per Category"
+msgstr "Müük kategooria lõikes"
+
+msgctxt "model:ir.action,name:act_reporting_category_time_series"
+msgid "Sales per Category"
+msgstr "Müük kategooria lõikes"
+
+msgctxt "model:ir.action,name:act_reporting_category_tree"
+msgid "Sales per Category"
+msgstr "Müük kategooria lõikes"
+
+msgctxt "model:ir.action,name:act_reporting_country_subdivision_time_series"
+msgid "Sales per Subdivision"
+msgstr "Müük alamjaotuse lõikes"
+
+msgctxt "model:ir.action,name:act_reporting_country_time_series"
+msgid "Sales per Country"
+msgstr "Müük riigi lõikes"
+
+msgctxt "model:ir.action,name:act_reporting_customer"
+msgid "Sales per Customer"
+msgstr "Müük kliendi lõikes"
+
+msgctxt "model:ir.action,name:act_reporting_customer_time_series"
+msgid "Sales per Customer"
+msgstr "Müük kliendi lõikes"
+
+msgctxt "model:ir.action,name:act_reporting_product"
+msgid "Sales per Product"
+msgstr "Müük toote lõikes"
+
+msgctxt "model:ir.action,name:act_reporting_product_time_series"
+msgid "Sales per Product"
+msgstr "Müük toote lõikes"
+
+msgctxt "model:ir.action,name:act_reporting_region"
+msgid "Sales per Region"
+msgstr "Müük regiooni lõikes"
+
+msgctxt "model:ir.action,name:act_return_form"
+msgid "Returns"
+msgstr "Tagastused"
+
+#, fuzzy
+msgctxt "model:ir.action,name:act_sale_configuration_form"
+msgid "Configuration"
+msgstr "Seadistus"
+
+msgctxt "model:ir.action,name:act_sale_form"
+msgid "Sales"
+msgstr "Müügid"
+
+msgctxt "model:ir.action,name:act_sale_form2"
+msgid "Sales"
+msgstr "Müügid"
+
+msgctxt "model:ir.action,name:act_sale_invoice_relate"
+msgid "Sales"
+msgstr "Müügid"
+
+#, fuzzy
+msgctxt "model:ir.action,name:act_sale_move_relate"
+msgid "Moves"
+msgstr "Kanded"
+
+msgctxt "model:ir.action,name:act_sale_shipment_returns_relate"
+msgid "Sales"
+msgstr "Müügid"
+
+msgctxt "model:ir.action,name:act_sale_shipments_relate"
+msgid "Sales"
+msgstr "Müügid"
+
+msgctxt "model:ir.action,name:act_shipment_form"
+msgid "Shipments"
+msgstr "Lähetused"
+
+msgctxt "model:ir.action,name:report_sale"
+msgid "Sale"
+msgstr "Müük"
+
+msgctxt "model:ir.action,name:wizard_invoice_handle_exception"
+msgid "Handle Invoice Exception"
+msgstr "Käitle arve erisust"
+
+msgctxt "model:ir.action,name:wizard_modify_header"
+msgid "Modify Header"
+msgstr "Muuda päist"
+
+msgctxt "model:ir.action,name:wizard_reporting_region_open"
+msgid "Open Region"
+msgstr "Avatud regioon"
+
+msgctxt "model:ir.action,name:wizard_return_sale"
+msgid "Return Sale"
+msgstr "Kreeditmüük"
+
+msgctxt "model:ir.action,name:wizard_shipment_handle_exception"
+msgid "Handle Shipment Exception"
+msgstr "Käitle lähetuse erisust"
+
+msgctxt "model:ir.action.act_window.domain,name:act_sale_form_domain_all"
+msgid "All"
+msgstr "Kõik"
+
+msgctxt ""
+"model:ir.action.act_window.domain,name:act_sale_form_domain_confirmed"
+msgid "Confirmed"
+msgstr "Kinnitatud"
+
+msgctxt "model:ir.action.act_window.domain,name:act_sale_form_domain_draft"
+msgid "Draft"
+msgstr "Mustand"
+
+#, fuzzy
+msgctxt ""
+"model:ir.action.act_window.domain,name:act_sale_form_domain_exception"
+msgid "Exception"
+msgstr "Erand"
+
+msgctxt ""
+"model:ir.action.act_window.domain,name:act_sale_form_domain_processing"
+msgid "Processing"
+msgstr "Töötluses"
+
+msgctxt ""
+"model:ir.action.act_window.domain,name:act_sale_form_domain_quotation"
+msgid "Quotation"
+msgstr "Pakkumus"
+
+msgctxt "model:ir.message,text:msg_erase_party_pending_sale"
+msgid ""
+"You cannot erase party \"%(party)s\" while they have pending sales with "
+"company \"%(company)s\"."
+msgstr ""
+"Osapoolt \"%(osapooli)\" ei saa kustutada, kuniks neil on ettevõttega "
+"\"%(ettevõtetega)\" avatud müügid."
+
+msgctxt "model:ir.message,text:msg_sale_customer_location_required"
+msgid ""
+"To process sale \"%(sale)s\" you must set a customer location on party "
+"\"%(party)s\"."
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_sale_delete_cancel"
+msgid "To delete sale \"%(sale)s\" you must cancel it."
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_sale_invalid_method"
+msgid ""
+"You cannot use together invoice \"%(invoice_method)s\" and shipment "
+"\"%(shipment_method)s\" on sale \"%(sale)s\"."
+msgstr ""
+
+msgctxt ""
+"model:ir.message,text:msg_sale_invoice_address_required_for_quotation"
+msgid "To get a quote for sale \"%(sale)s\" you must enter an invoice address."
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_sale_invoice_reset_draft"
+msgid ""
+"You cannot reset invoice \"%(invoice)s\" to draft because it was generated "
+"by a sale."
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_sale_line_delete_cancel_draft"
+msgid ""
+"To delete line \"%(line)s\" you must cancel or reset to draft sale "
+"\"%(sale)s\"."
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_sale_missing_account_revenue"
+msgid "To invoice sale \"%(sale)s\" you must configure a default account revenue."
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_sale_modify_header_draft"
+msgid "To modify the header of sale \"%(sale)s\", it must be in \"draft\" state."
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_sale_move_reset_draft"
+msgid ""
+"You cannot reset move \"%(move)s\" to draft because it was generated by a "
+"sale."
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_sale_product_missing_account_revenue"
+msgid ""
+"To invoice sale \"%(sale)s\" you must define an account revenue for product "
+"\"%(product)s\"."
+msgstr ""
+
+#, fuzzy
+msgctxt "model:ir.message,text:msg_sale_reporting_company"
+msgid "Company"
+msgstr "Ettevõte"
+
+#, fuzzy
+msgctxt "model:ir.message,text:msg_sale_reporting_currency"
+msgid "Currency"
+msgstr "Valuuta"
+
+#, fuzzy
+msgctxt "model:ir.message,text:msg_sale_reporting_currency_digits"
+msgid "Currency Digits"
+msgstr "Valuuta numbriline arv"
+
+#, fuzzy
+msgctxt "model:ir.message,text:msg_sale_reporting_number"
+msgid "#"
+msgstr "#"
+
+#, fuzzy
+msgctxt "model:ir.message,text:msg_sale_reporting_number_help"
+msgid "Number of sales"
+msgstr "Müükide arv"
+
+#, fuzzy
+msgctxt "model:ir.message,text:msg_sale_reporting_revenue"
+msgid "Revenue"
+msgstr "Müügitulu"
+
+#, fuzzy
+msgctxt "model:ir.message,text:msg_sale_reporting_revenue_trend"
+msgid "Revenue Trend"
+msgstr "Müügitulu trend"
+
+msgctxt ""
+"model:ir.message,text:msg_sale_shipment_address_required_for_quotation"
+msgid "To get a quote for sale \"%(sale)s\" you must enter a shipment address."
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_sale_warehouse_required_for_quotation"
+msgid "To get a quote for sale \"%(sale)s\" you must enter a warehouse."
+msgstr ""
+
+msgctxt "model:ir.model.button,string:sale_cancel_button"
+msgid "Cancel"
+msgstr "Tühista"
+
+msgctxt "model:ir.model.button,string:sale_confirm_button"
+msgid "Confirm"
+msgstr "Kinnita"
+
+msgctxt "model:ir.model.button,string:sale_draft_button"
+msgid "Draft"
+msgstr "Mustand"
+
+msgctxt "model:ir.model.button,string:sale_handle_invoice_exception_button"
+msgid "Handle Invoice Exception"
+msgstr "Käitle arve erisust"
+
+msgctxt "model:ir.model.button,string:sale_handle_shipment_exception_button"
+msgid "Handle Shipment Exception"
+msgstr "Käitle lähetuse erisust"
+
+msgctxt "model:ir.model.button,string:sale_modify_header_button"
+msgid "Modify Header"
+msgstr "Muuda päist"
+
+msgctxt "model:ir.model.button,string:sale_process_button"
+msgid "Process"
+msgstr "Töötle"
+
+msgctxt "model:ir.model.button,string:sale_quote_button"
+msgid "Quote"
+msgstr "Pakkumus"
+
+#, fuzzy
+msgctxt "model:ir.rule.group,name:rule_group_reporting_category_companies"
+msgid "User in companies"
+msgstr "Kasutaja ettevõttes"
+
+#, fuzzy
+msgctxt ""
+"model:ir.rule.group,name:rule_group_reporting_category_time_series_companies"
+msgid "User in companies"
+msgstr "Kasutaja ettevõttes"
+
+#, fuzzy
+msgctxt ""
+"model:ir.rule.group,name:rule_group_reporting_country_subdivision_time_series_companies"
+msgid "User in companies"
+msgstr "Kasutaja ettevõttes"
+
+#, fuzzy
+msgctxt ""
+"model:ir.rule.group,name:rule_group_reporting_country_time_series_companies"
+msgid "User in companies"
+msgstr "Kasutaja ettevõttes"
+
+#, fuzzy
+msgctxt "model:ir.rule.group,name:rule_group_reporting_customer_companies"
+msgid "User in companies"
+msgstr "Kasutaja ettevõttes"
+
+#, fuzzy
+msgctxt ""
+"model:ir.rule.group,name:rule_group_reporting_customer_time_series_companies"
+msgid "User in companies"
+msgstr "Kasutaja ettevõttes"
+
+#, fuzzy
+msgctxt "model:ir.rule.group,name:rule_group_reporting_product_companies"
+msgid "User in companies"
+msgstr "Kasutaja ettevõttes"
+
+#, fuzzy
+msgctxt ""
+"model:ir.rule.group,name:rule_group_reporting_product_time_series_companies"
+msgid "User in companies"
+msgstr "Kasutaja ettevõttes"
+
+#, fuzzy
+msgctxt "model:ir.rule.group,name:rule_group_reporting_region_companies"
+msgid "User in companies"
+msgstr "Kasutaja ettevõttes"
+
+#, fuzzy
+msgctxt "model:ir.rule.group,name:rule_group_sale_companies"
+msgid "User in companies"
+msgstr "Kasutaja ettevõttes"
+
+msgctxt "model:ir.sequence,name:sequence_sale"
+msgid "Sale"
+msgstr "Müük"
+
+msgctxt "model:ir.sequence.type,name:sequence_type_sale"
+msgid "Sale"
+msgstr "Müük"
+
+msgctxt "model:ir.ui.menu,name:menu_configuration"
+msgid "Configuration"
+msgstr "Seadistus"
+
+#, fuzzy
+msgctxt "model:ir.ui.menu,name:menu_customer"
+msgid "Associated to Sales"
+msgstr "Müügiga seotud osapooled"
+
+#, fuzzy
+msgctxt "model:ir.ui.menu,name:menu_product"
+msgid "Products"
+msgstr "Toode"
+
+msgctxt "model:ir.ui.menu,name:menu_reporting"
+msgid "Reporting"
+msgstr "Aruandlus"
+
+msgctxt "model:ir.ui.menu,name:menu_reporting_sale"
+msgid "Sales"
+msgstr "Müügid"
+
+msgctxt "model:ir.ui.menu,name:menu_sale"
+msgid "Sales"
+msgstr "Müügid"
+
+#, fuzzy
+msgctxt "model:ir.ui.menu,name:menu_sale_configuration"
+msgid "Configuration"
+msgstr "Seadistus"
+
+msgctxt "model:ir.ui.menu,name:menu_sale_form"
+msgid "Sales"
+msgstr "Müügid"
+
+msgctxt "model:product.configuration.default_lead_time,name:"
+msgid "Product Default Lead Time"
+msgstr ""
+
+#, fuzzy
+msgctxt "model:product.sale.context,name:"
+msgid "Product Sale Context"
+msgstr "Protsessi müüki pärast"
+
+msgctxt "model:res.group,name:group_sale"
+msgid "Sales"
+msgstr "Müük"
+
+msgctxt "model:res.group,name:group_sale_admin"
+msgid "Sales Administrator"
+msgstr "Müügijuht"
+
+msgctxt "model:sale.configuration,name:"
+msgid "Sale Configuration"
+msgstr "Müügi seadistus"
+
+msgctxt "model:sale.configuration.sale_method,name:"
+msgid "Sale Configuration Sale Method"
+msgstr "Müügi seadistus - müügi meetod"
+
+msgctxt "model:sale.configuration.sequence,name:"
+msgid "Sale Configuration Sequence"
+msgstr "Müügi seadistuse järjestus"
+
+msgctxt "model:sale.handle.invoice.exception.ask,name:"
+msgid "Handle Invoice Exception"
+msgstr "Käitle arve erisust"
+
+msgctxt "model:sale.handle.shipment.exception.ask,name:"
+msgid "Handle Shipment Exception"
+msgstr "Käitle lähetuse erisust"
+
+msgctxt "model:sale.line,name:"
+msgid "Sale Line"
+msgstr "Müügi rida"
+
+msgctxt "model:sale.line-account.tax,name:"
+msgid "Sale Line - Tax"
+msgstr "Müügi rida - maks"
+
+msgctxt "model:sale.line-ignored-stock.move,name:"
+msgid "Sale Line - Ignored Move"
+msgstr "Müügi rida - ignoreeritud kanne"
+
+msgctxt "model:sale.line-recreated-stock.move,name:"
+msgid "Sale Line - Recreated Move"
+msgstr "Müügi rida - taasloodud kanne"
+
+msgctxt "model:sale.reporting.category,name:"
+msgid "Sale Reporting per Category"
+msgstr "Müügi aruandlus kategooria lõikes"
+
+msgctxt "model:sale.reporting.category.time_series,name:"
+msgid "Sale Reporting per Category"
+msgstr "Müügi aruandlus kategooria lõikes"
+
+msgctxt "model:sale.reporting.category.tree,name:"
+msgid "Sale Reporting per Category"
+msgstr "Müügi aruandlus kategooria lõikes"
+
+msgctxt "model:sale.reporting.context,name:"
+msgid "Sale Reporting Context"
+msgstr "Müügi aruandluse sisu"
+
+msgctxt "model:sale.reporting.country,name:"
+msgid "Sale Reporting per Country"
+msgstr "Müügiaruandlus toote lõikes"
+
+msgctxt "model:sale.reporting.country.subdivision,name:"
+msgid "Sale Reporting per Subdivision"
+msgstr "Müügi aruandlus alamjaotuse lõikes"
+
+msgctxt "model:sale.reporting.country.subdivision.time_series,name:"
+msgid "Sale Reporting per Subdivision"
+msgstr "Müügi aruandlus alamjaotuse lõikes"
+
+msgctxt "model:sale.reporting.country.time_series,name:"
+msgid "Sale Reporting per Country"
+msgstr "Müügiaruandlus riikide lõikes"
+
+msgctxt "model:sale.reporting.customer,name:"
+msgid "Sale Reporting per Customer"
+msgstr "Müügi aruandlus kliendi lõikes"
+
+msgctxt "model:sale.reporting.customer.time_series,name:"
+msgid "Sale Reporting per Customer"
+msgstr "Müügi aruandlus kliendi lõikes"
+
+msgctxt "model:sale.reporting.product,name:"
+msgid "Sale Reporting per Product"
+msgstr "Müügiaruandlus toote lõikes"
+
+msgctxt "model:sale.reporting.product.time_series,name:"
+msgid "Sale Reporting per Product"
+msgstr "Müügiaruandlus toote lõikes"
+
+msgctxt "model:sale.reporting.region,name:"
+msgid "Sale Reporting per Region"
+msgstr "Müügi aruandlus regiooni lõikes"
+
+msgctxt "model:sale.return_sale.start,name:"
+msgid "Return Sale"
+msgstr "Müügi tagastus"
+
+msgctxt "model:sale.sale,name:"
+msgid "Sale"
+msgstr "Müük"
+
+msgctxt "model:sale.sale-ignored-account.invoice,name:"
+msgid "Sale - Ignored Invoice"
+msgstr "Müük - ignoreeritud arve"
+
+msgctxt "model:sale.sale-recreated-account.invoice,name:"
+msgid "Sale - Recreated Invoice"
+msgstr "Müük - taasloodud arve"
+
+msgctxt "report:sale.sale:"
+msgid ":"
+msgstr ":"
+
+msgctxt "report:sale.sale:"
+msgid "Amount"
+msgstr "Summa"
+
+msgctxt "report:sale.sale:"
+msgid "Date:"
+msgstr "Kuupäev:"
+
+msgctxt "report:sale.sale:"
+msgid "Description"
+msgstr "Kirjeldus"
+
+msgctxt "report:sale.sale:"
+msgid "Description:"
+msgstr "Kirjeldus:"
+
+msgctxt "report:sale.sale:"
+msgid "Draft Sale Order"
+msgstr "Müügitellimuse mustand"
+
+msgctxt "report:sale.sale:"
+msgid "Quantity"
+msgstr "Kogus"
+
+msgctxt "report:sale.sale:"
+msgid "Quotation N°:"
+msgstr "Pakkumuse nr:"
+
+msgctxt "report:sale.sale:"
+msgid "Reference:"
+msgstr "Viide:"
+
+msgctxt "report:sale.sale:"
+msgid "Sale Order N°:"
+msgstr "Müügitellimuse nr:"
+
+msgctxt "report:sale.sale:"
+msgid "Taxes"
+msgstr "Maksud"
+
+msgctxt "report:sale.sale:"
+msgid "Taxes:"
+msgstr "Maksud:"
+
+msgctxt "report:sale.sale:"
+msgid "Total (excl. taxes):"
+msgstr "Kokku (ilma maksuta):"
+
+msgctxt "report:sale.sale:"
+msgid "Total:"
+msgstr "Kokku:"
+
+msgctxt "report:sale.sale:"
+msgid "Unit Price"
+msgstr "Ühiku hind"
+
+msgctxt "selection:account.invoice,sale_exception_state:"
+msgid "Ignored"
+msgstr "Ignoreeritud"
+
+msgctxt "selection:account.invoice,sale_exception_state:"
+msgid "Recreated"
+msgstr "Taasloodud"
+
+msgctxt "selection:sale.line,type:"
+msgid "Comment"
+msgstr "Kommentaar"
+
+msgctxt "selection:sale.line,type:"
+msgid "Line"
+msgstr "Rida"
+
+msgctxt "selection:sale.line,type:"
+msgid "Subtotal"
+msgstr "Vahesumma"
+
+msgctxt "selection:sale.line,type:"
+msgid "Title"
+msgstr "Pealkiri"
+
+msgctxt "selection:sale.reporting.context,period:"
+msgid "Day"
+msgstr "Päev"
+
+msgctxt "selection:sale.reporting.context,period:"
+msgid "Month"
+msgstr "Kuu"
+
+msgctxt "selection:sale.reporting.context,period:"
+msgid "Year"
+msgstr "Aasta"
+
+msgctxt "selection:sale.sale,invoice_method:"
+msgid "Manual"
+msgstr "Käsitsi"
+
+msgctxt "selection:sale.sale,invoice_method:"
+msgid "On Order Processed"
+msgstr "Protsessitakse tellimusel"
+
+msgctxt "selection:sale.sale,invoice_method:"
+msgid "On Shipment Sent"
+msgstr "Tarnel saadetud"
+
+msgctxt "selection:sale.sale,invoice_state:"
+msgid "Exception"
+msgstr "Erand"
+
+msgctxt "selection:sale.sale,invoice_state:"
+msgid "None"
+msgstr "Mitte"
+
+msgctxt "selection:sale.sale,invoice_state:"
+msgid "Paid"
+msgstr "Makstud"
+
+msgctxt "selection:sale.sale,invoice_state:"
+msgid "Waiting"
+msgstr "Ootel"
+
+msgctxt "selection:sale.sale,shipment_method:"
+msgid "Manual"
+msgstr "Käsitsi"
+
+msgctxt "selection:sale.sale,shipment_method:"
+msgid "On Invoice Paid"
+msgstr "Arvel tasutud"
+
+msgctxt "selection:sale.sale,shipment_method:"
+msgid "On Order Processed"
+msgstr "Tellimusel protsessitud"
+
+msgctxt "selection:sale.sale,shipment_state:"
+msgid "Exception"
+msgstr "Erand"
+
+msgctxt "selection:sale.sale,shipment_state:"
+msgid "None"
+msgstr "Mitte"
+
+msgctxt "selection:sale.sale,shipment_state:"
+msgid "Sent"
+msgstr "Saadetud"
+
+msgctxt "selection:sale.sale,shipment_state:"
+msgid "Waiting"
+msgstr "Ootel"
+
+#, fuzzy
+msgctxt "selection:sale.sale,state:"
+msgid "Cancelled"
+msgstr "Tühistatud"
+
+msgctxt "selection:sale.sale,state:"
+msgid "Confirmed"
+msgstr "Kinnitatud"
+
+msgctxt "selection:sale.sale,state:"
+msgid "Done"
+msgstr "Tehtud"
+
+msgctxt "selection:sale.sale,state:"
+msgid "Draft"
+msgstr "Mustand"
+
+msgctxt "selection:sale.sale,state:"
+msgid "Processing"
+msgstr "Töötluses"
+
+msgctxt "selection:sale.sale,state:"
+msgid "Quotation"
+msgstr "Pakkumus"
+
+msgctxt "selection:stock.move,sale_exception_state:"
+msgid "Ignored"
+msgstr "Ignoreeritud"
+
+msgctxt "selection:stock.move,sale_exception_state:"
+msgid "Recreated"
+msgstr "Taasloodud"
+
+msgctxt "view:party.party:"
+msgid "Sale"
+msgstr "Müük"
+
+msgctxt "view:product.template:"
+msgid "Customers"
+msgstr "Kliendid"
+
+#, fuzzy
+msgctxt "view:sale.handle.invoice.exception.ask:"
+msgid "Choose invoices to recreate:"
+msgstr "Vali arved taasloomiseks"
+
+#, fuzzy
+msgctxt "view:sale.handle.shipment.exception.ask:"
+msgid "Choose move to recreate:"
+msgstr "Vali kanne taasloomiseks"
+
+msgctxt "view:sale.line:"
+msgid "General"
+msgstr "Üldine"
+
+msgctxt "view:sale.line:"
+msgid "Notes"
+msgstr "Märkused"
+
+msgctxt "view:sale.line:"
+msgid "Taxes"
+msgstr "Maksud"
+
+msgctxt "view:sale.return_sale.start:"
+msgid "Are you sure to return these/this sale(s)?"
+msgstr ""
+
+msgctxt "view:sale.sale:"
+msgid "Other Info"
+msgstr "Muu info"
+
+msgctxt "view:sale.sale:"
+msgid "Sale"
+msgstr "Müük"
+
+msgctxt "wizard_button:sale.handle.invoice.exception,ask,end:"
+msgid "Cancel"
+msgstr "Tühista"
+
+msgctxt "wizard_button:sale.handle.invoice.exception,ask,handle:"
+msgid "OK"
+msgstr "OK"
+
+msgctxt "wizard_button:sale.handle.shipment.exception,ask,end:"
+msgid "Cancel"
+msgstr "Tühista"
+
+msgctxt "wizard_button:sale.handle.shipment.exception,ask,handle:"
+msgid "OK"
+msgstr "OK"
+
+msgctxt "wizard_button:sale.modify_header,start,end:"
+msgid "Cancel"
+msgstr "Tühista"
+
+msgctxt "wizard_button:sale.modify_header,start,modify:"
+msgid "Modify"
+msgstr "Muuda"
+
+msgctxt "wizard_button:sale.return_sale,start,end:"
+msgid "Cancel"
+msgstr "Tühista"
+
+msgctxt "wizard_button:sale.return_sale,start,return_:"
+msgid "Return"
+msgstr "Tagastus"
diff --git a/modules/sale/locale/fa.po b/modules/sale/locale/fa.po
new file mode 100644
index 0000000000..7bc554097d
--- /dev/null
+++ b/modules/sale/locale/fa.po
@@ -0,0 +1,1404 @@
+#
+msgid ""
+msgstr "Content-Type: text/plain; charset=utf-8\n"
+
+msgctxt "field:account.invoice,sale_exception_state:"
+msgid "Exception State"
+msgstr "حالت اعتراضی"
+
+msgctxt "field:account.invoice,sales:"
+msgid "Sales"
+msgstr "فروش ها"
+
+#, fuzzy
+msgctxt "field:product.configuration,default_lead_time:"
+msgid "Default Lead Time"
+msgstr "زمان پیشبرد"
+
+#, fuzzy
+msgctxt "field:product.configuration.default_lead_time,company:"
+msgid "Company"
+msgstr "شرکت"
+
+#, fuzzy
+msgctxt "field:product.configuration.default_lead_time,default_lead_time:"
+msgid "Default Lead Time"
+msgstr "زمان پیشبرد"
+
+msgctxt "field:product.product,lead_time:"
+msgid "Lead Time"
+msgstr "زمان پیشبرد"
+
+msgctxt "field:product.product,salable:"
+msgid "Salable"
+msgstr "قابل فروش"
+
+msgctxt "field:product.product,sale_price_uom:"
+msgid "Sale Price"
+msgstr "قیمت فروش"
+
+msgctxt "field:product.product,sale_uom:"
+msgid "Sale UOM"
+msgstr "واحد اندازی گیری فروش"
+
+#, fuzzy
+msgctxt "field:product.sale.context,company:"
+msgid "Company"
+msgstr "شرکت"
+
+#, fuzzy
+msgctxt "field:product.sale.context,currency:"
+msgid "Currency"
+msgstr "واحد پول"
+
+#, fuzzy
+msgctxt "field:product.sale.context,customer:"
+msgid "Customer"
+msgstr "مشتری"
+
+#, fuzzy
+msgctxt "field:product.sale.context,locations:"
+msgid "Warehouses"
+msgstr "انبار"
+
+#, fuzzy
+msgctxt "field:product.sale.context,quantity:"
+msgid "Quantity"
+msgstr "مقدار/تعداد"
+
+#, fuzzy
+msgctxt "field:product.sale.context,sale_date:"
+msgid "Sale Date"
+msgstr "تاریخ فروش"
+
+msgctxt "field:product.sale.context,stock_date_end:"
+msgid "Stock End Date"
+msgstr ""
+
+msgctxt "field:product.template,lead_time:"
+msgid "Lead Time"
+msgstr "زمان پیشبرد"
+
+msgctxt "field:product.template,salable:"
+msgid "Salable"
+msgstr "قابل فروش"
+
+msgctxt "field:product.template,sale_uom:"
+msgid "Sale UOM"
+msgstr "واحد اندازی گیری فروش"
+
+msgctxt "field:sale.configuration,sale_invoice_method:"
+msgid "Sale Invoice Method"
+msgstr "متد صورتحساب فروش"
+
+msgctxt "field:sale.configuration,sale_process_after:"
+msgid "Process Sale after"
+msgstr "پس از فرایند فروش"
+
+msgctxt "field:sale.configuration,sale_sequence:"
+msgid "Sale Sequence"
+msgstr "ادامه فروش"
+
+msgctxt "field:sale.configuration,sale_shipment_method:"
+msgid "Sale Shipment Method"
+msgstr "متد حمل ونقل فروش"
+
+msgctxt "field:sale.configuration.sale_method,sale_invoice_method:"
+msgid "Sale Invoice Method"
+msgstr "متد صورتحساب فروش"
+
+msgctxt "field:sale.configuration.sale_method,sale_shipment_method:"
+msgid "Sale Shipment Method"
+msgstr "متد حمل ونقل فروش"
+
+msgctxt "field:sale.configuration.sequence,company:"
+msgid "Company"
+msgstr "شرکت"
+
+msgctxt "field:sale.configuration.sequence,sale_sequence:"
+msgid "Sale Sequence"
+msgstr "ادامه فروش"
+
+msgctxt "field:sale.handle.invoice.exception.ask,domain_invoices:"
+msgid "Domain Invoices"
+msgstr "دامنه صورتحساب ها"
+
+msgctxt "field:sale.handle.invoice.exception.ask,recreate_invoices:"
+msgid "Recreate Invoices"
+msgstr "ایجاد دوباره صورتحساب ها"
+
+msgctxt "field:sale.handle.shipment.exception.ask,domain_moves:"
+msgid "Domain Moves"
+msgstr "دامنه جابجایی ها"
+
+msgctxt "field:sale.handle.shipment.exception.ask,recreate_moves:"
+msgid "Recreate Moves"
+msgstr "ایجاد دوباره جابجایی ها"
+
+#, fuzzy
+msgctxt "field:sale.line,actual_quantity:"
+msgid "Actual Quantity"
+msgstr "مقدار/تعداد"
+
+msgctxt "field:sale.line,amount:"
+msgid "Amount"
+msgstr "مقدار"
+
+#, fuzzy
+msgctxt "field:sale.line,company:"
+msgid "Company"
+msgstr "شرکت"
+
+#, fuzzy
+msgctxt "field:sale.line,currency:"
+msgid "Currency"
+msgstr "واحد پول"
+
+msgctxt "field:sale.line,description:"
+msgid "Description"
+msgstr "شرح"
+
+msgctxt "field:sale.line,from_location:"
+msgid "From Location"
+msgstr "از مکان"
+
+msgctxt "field:sale.line,invoice_lines:"
+msgid "Invoice Lines"
+msgstr "خطوط صورتحساب"
+
+msgctxt "field:sale.line,move_done:"
+msgid "Moves Done"
+msgstr "جابجایی ها انجام شد"
+
+msgctxt "field:sale.line,move_exception:"
+msgid "Moves Exception"
+msgstr "جابجایی های اعتراضی"
+
+msgctxt "field:sale.line,moves:"
+msgid "Moves"
+msgstr "جابجایی ها"
+
+msgctxt "field:sale.line,moves_ignored:"
+msgid "Ignored Moves"
+msgstr "جابجایی های نادیده گرفته شده"
+
+msgctxt "field:sale.line,moves_recreated:"
+msgid "Recreated Moves"
+msgstr "جابجایی های دوباره انجام شده"
+
+msgctxt "field:sale.line,note:"
+msgid "Note"
+msgstr "توجه"
+
+msgctxt "field:sale.line,product:"
+msgid "Product"
+msgstr "محصول"
+
+msgctxt "field:sale.line,product_uom_category:"
+msgid "Product Uom Category"
+msgstr "دسته بندی واحد اندازه گیری محصول"
+
+msgctxt "field:sale.line,quantity:"
+msgid "Quantity"
+msgstr "مقدار/تعداد"
+
+msgctxt "field:sale.line,sale:"
+msgid "Sale"
+msgstr "فروش"
+
+msgctxt "field:sale.line,sale_state:"
+msgid "Sale State"
+msgstr "وضعیت فروش"
+
+msgctxt "field:sale.line,shipping_date:"
+msgid "Shipping Date"
+msgstr "تاریخ ارسال"
+
+msgctxt "field:sale.line,summary:"
+msgid "Summary"
+msgstr ""
+
+msgctxt "field:sale.line,taxes:"
+msgid "Taxes"
+msgstr "مالیات ها"
+
+msgctxt "field:sale.line,to_location:"
+msgid "To Location"
+msgstr "به مکان"
+
+msgctxt "field:sale.line,type:"
+msgid "Type"
+msgstr "نوع"
+
+msgctxt "field:sale.line,unit:"
+msgid "Unit"
+msgstr "واحد"
+
+msgctxt "field:sale.line,unit_digits:"
+msgid "Unit Digits"
+msgstr "ارقام واحد"
+
+msgctxt "field:sale.line,unit_price:"
+msgid "Unit Price"
+msgstr "قیمت واحد"
+
+msgctxt "field:sale.line,warehouse:"
+msgid "Warehouse"
+msgstr "انبار"
+
+msgctxt "field:sale.line-account.tax,line:"
+msgid "Sale Line"
+msgstr "سطر فروش"
+
+msgctxt "field:sale.line-account.tax,tax:"
+msgid "Tax"
+msgstr "مالیات"
+
+msgctxt "field:sale.line-ignored-stock.move,move:"
+msgid "Move"
+msgstr "جابجایی"
+
+msgctxt "field:sale.line-ignored-stock.move,sale_line:"
+msgid "Sale Line"
+msgstr "سطر فروش"
+
+msgctxt "field:sale.line-recreated-stock.move,move:"
+msgid "Move"
+msgstr "جابجایی"
+
+msgctxt "field:sale.line-recreated-stock.move,sale_line:"
+msgid "Sale Line"
+msgstr "سطر فروش"
+
+msgctxt "field:sale.reporting.category,category:"
+msgid "Category"
+msgstr "دستهبندی"
+
+msgctxt "field:sale.reporting.category,time_series:"
+msgid "Time Series"
+msgstr "سری زمانی"
+
+msgctxt "field:sale.reporting.category.time_series,category:"
+msgid "Category"
+msgstr "دستهبندی"
+
+msgctxt "field:sale.reporting.category.time_series,date:"
+msgid "Date"
+msgstr "تاریخ"
+
+msgctxt "field:sale.reporting.category.tree,children:"
+msgid "Children"
+msgstr "زیر مجموعه"
+
+msgctxt "field:sale.reporting.category.tree,currency_digits:"
+msgid "Currency Digits"
+msgstr "رقم های واحد پول"
+
+msgctxt "field:sale.reporting.category.tree,name:"
+msgid "Name"
+msgstr "نام"
+
+msgctxt "field:sale.reporting.category.tree,parent:"
+msgid "Parent"
+msgstr "منبع"
+
+msgctxt "field:sale.reporting.category.tree,revenue:"
+msgid "Revenue"
+msgstr "درآمد"
+
+msgctxt "field:sale.reporting.context,company:"
+msgid "Company"
+msgstr "شرکت"
+
+msgctxt "field:sale.reporting.context,from_date:"
+msgid "From Date"
+msgstr "از تاریخ"
+
+msgctxt "field:sale.reporting.context,period:"
+msgid "Period"
+msgstr "دوره زمانی"
+
+msgctxt "field:sale.reporting.context,to_date:"
+msgid "To Date"
+msgstr "تا تاریخ"
+
+msgctxt "field:sale.reporting.context,warehouse:"
+msgid "Warehouse"
+msgstr "انبار"
+
+msgctxt "field:sale.reporting.country,country:"
+msgid "Country"
+msgstr "کشور"
+
+msgctxt "field:sale.reporting.country,time_series:"
+msgid "Time Series"
+msgstr "سری زمانی"
+
+msgctxt "field:sale.reporting.country.subdivision,country:"
+msgid "Country"
+msgstr "کشور"
+
+msgctxt "field:sale.reporting.country.subdivision,subdivision:"
+msgid "Subdivision"
+msgstr "زیرتقسیمات"
+
+msgctxt "field:sale.reporting.country.subdivision,time_series:"
+msgid "Time Series"
+msgstr "سری زمانی"
+
+msgctxt "field:sale.reporting.country.subdivision.time_series,country:"
+msgid "Country"
+msgstr "کشور"
+
+msgctxt "field:sale.reporting.country.subdivision.time_series,date:"
+msgid "Date"
+msgstr "تاریخ"
+
+msgctxt "field:sale.reporting.country.subdivision.time_series,subdivision:"
+msgid "Subdivision"
+msgstr "زیرتقسیمات"
+
+msgctxt "field:sale.reporting.country.time_series,country:"
+msgid "Country"
+msgstr "کشور"
+
+msgctxt "field:sale.reporting.country.time_series,date:"
+msgid "Date"
+msgstr "تاریخ"
+
+msgctxt "field:sale.reporting.customer,customer:"
+msgid "Customer"
+msgstr "مشتری"
+
+msgctxt "field:sale.reporting.customer,time_series:"
+msgid "Time Series"
+msgstr "سری زمانی"
+
+msgctxt "field:sale.reporting.customer.time_series,customer:"
+msgid "Customer"
+msgstr "مشتری"
+
+msgctxt "field:sale.reporting.customer.time_series,date:"
+msgid "Date"
+msgstr "تاریخ"
+
+msgctxt "field:sale.reporting.product,product:"
+msgid "Product"
+msgstr "محصول"
+
+msgctxt "field:sale.reporting.product,time_series:"
+msgid "Time Series"
+msgstr "سری زمانی"
+
+msgctxt "field:sale.reporting.product.time_series,date:"
+msgid "Date"
+msgstr "تاریخ"
+
+msgctxt "field:sale.reporting.product.time_series,product:"
+msgid "Product"
+msgstr "محصول"
+
+msgctxt "field:sale.reporting.region,children:"
+msgid "Children"
+msgstr "زیر مجموعه"
+
+msgctxt "field:sale.reporting.region,parent:"
+msgid "Parent"
+msgstr "منبع"
+
+msgctxt "field:sale.reporting.region,region:"
+msgid "Region"
+msgstr "منطقه"
+
+msgctxt "field:sale.sale,comment:"
+msgid "Comment"
+msgstr "اظهار نظر"
+
+msgctxt "field:sale.sale,company:"
+msgid "Company"
+msgstr "شرکت"
+
+#, fuzzy
+msgctxt "field:sale.sale,confirmed_by:"
+msgid "Confirmed By"
+msgstr "تایید شده"
+
+msgctxt "field:sale.sale,contact:"
+msgid "Contact"
+msgstr ""
+
+msgctxt "field:sale.sale,currency:"
+msgid "Currency"
+msgstr "واحد پول"
+
+msgctxt "field:sale.sale,currency_digits:"
+msgid "Currency Digits"
+msgstr "رقم های واحد پول"
+
+msgctxt "field:sale.sale,description:"
+msgid "Description"
+msgstr "شرح"
+
+msgctxt "field:sale.sale,invoice_address:"
+msgid "Invoice Address"
+msgstr "آدرس صورتحساب"
+
+msgctxt "field:sale.sale,invoice_method:"
+msgid "Invoice Method"
+msgstr "متد صورتحساب"
+
+#, fuzzy
+msgctxt "field:sale.sale,invoice_party:"
+msgid "Invoice Party"
+msgstr "وضعیت صورت حساب"
+
+msgctxt "field:sale.sale,invoice_state:"
+msgid "Invoice State"
+msgstr "وضعیت صورت حساب"
+
+msgctxt "field:sale.sale,invoices:"
+msgid "Invoices"
+msgstr "صورتحساب ها"
+
+msgctxt "field:sale.sale,invoices_ignored:"
+msgid "Ignored Invoices"
+msgstr "صورتحساب های نادیده گرفته شده"
+
+msgctxt "field:sale.sale,invoices_recreated:"
+msgid "Recreated Invoices"
+msgstr "صورتحساب های دوباره ایجاد شده"
+
+msgctxt "field:sale.sale,lines:"
+msgid "Lines"
+msgstr "خطوط"
+
+msgctxt "field:sale.sale,moves:"
+msgid "Moves"
+msgstr "جابجایی ها"
+
+msgctxt "field:sale.sale,number:"
+msgid "Number"
+msgstr "شماره"
+
+msgctxt "field:sale.sale,origin:"
+msgid "Origin"
+msgstr "مبداء"
+
+msgctxt "field:sale.sale,party:"
+msgid "Party"
+msgstr "نهاد/سازمان"
+
+msgctxt "field:sale.sale,party_lang:"
+msgid "Party Language"
+msgstr "زبان نهاد/سازمان"
+
+msgctxt "field:sale.sale,payment_term:"
+msgid "Payment Term"
+msgstr "شرایط پرداخت"
+
+#, fuzzy
+msgctxt "field:sale.sale,quoted_by:"
+msgid "Quoted By"
+msgstr "Quote"
+
+msgctxt "field:sale.sale,reference:"
+msgid "Reference"
+msgstr "مرجع"
+
+msgctxt "field:sale.sale,sale_date:"
+msgid "Sale Date"
+msgstr "تاریخ فروش"
+
+msgctxt "field:sale.sale,shipment_address:"
+msgid "Shipment Address"
+msgstr "آدرس حمل و نقل"
+
+msgctxt "field:sale.sale,shipment_method:"
+msgid "Shipment Method"
+msgstr "متد حمل ونقل"
+
+msgctxt "field:sale.sale,shipment_party:"
+msgid "Shipment Party"
+msgstr "نهاد/سازمان حمل و نقل"
+
+msgctxt "field:sale.sale,shipment_returns:"
+msgid "Shipment Returns"
+msgstr "محموله های برگشتی"
+
+msgctxt "field:sale.sale,shipment_state:"
+msgid "Shipment State"
+msgstr "وضعیت حمل و نقل محموله"
+
+msgctxt "field:sale.sale,shipments:"
+msgid "Shipments"
+msgstr "محموله ها"
+
+#, fuzzy
+msgctxt "field:sale.sale,shipping_date:"
+msgid "Shipping Date"
+msgstr "تاریخ ارسال"
+
+msgctxt "field:sale.sale,state:"
+msgid "State"
+msgstr "وضعیت"
+
+msgctxt "field:sale.sale,tax_amount:"
+msgid "Tax"
+msgstr "مالیات"
+
+msgctxt "field:sale.sale,tax_amount_cache:"
+msgid "Tax Cache"
+msgstr "مالیات نقدی"
+
+msgctxt "field:sale.sale,total_amount:"
+msgid "Total"
+msgstr "مجموع"
+
+#, fuzzy
+msgctxt "field:sale.sale,total_amount_cache:"
+msgid "Total Cache"
+msgstr "مالیات نقدی"
+
+msgctxt "field:sale.sale,untaxed_amount:"
+msgid "Untaxed"
+msgstr "بدون اعمال مالیات"
+
+msgctxt "field:sale.sale,untaxed_amount_cache:"
+msgid "Untaxed Cache"
+msgstr "نقدی بدون اعمال مالیات"
+
+msgctxt "field:sale.sale,warehouse:"
+msgid "Warehouse"
+msgstr "انبار"
+
+msgctxt "field:sale.sale-ignored-account.invoice,invoice:"
+msgid "Invoice"
+msgstr "صورت حساب"
+
+msgctxt "field:sale.sale-ignored-account.invoice,sale:"
+msgid "Sale"
+msgstr "فروش"
+
+msgctxt "field:sale.sale-recreated-account.invoice,invoice:"
+msgid "Invoice"
+msgstr "صورت حساب"
+
+msgctxt "field:sale.sale-recreated-account.invoice,sale:"
+msgid "Sale"
+msgstr "فروش"
+
+msgctxt "field:stock.move,sale:"
+msgid "Sale"
+msgstr "فروش"
+
+msgctxt "field:stock.move,sale_exception_state:"
+msgid "Exception State"
+msgstr "حالت اعتراضی"
+
+msgctxt "help:product.configuration,default_lead_time:"
+msgid ""
+"The time from confirming the sales order to sending the products.\n"
+"Used for products without a lead time."
+msgstr ""
+
+msgctxt "help:product.product,lead_time:"
+msgid ""
+"The time from confirming the sales order to sending the products.\n"
+"If empty the default lead time from the configuration is used."
+msgstr ""
+
+msgctxt "help:product.template,lead_time:"
+msgid ""
+"The time from confirming the sales order to sending the products.\n"
+"If empty the default lead time from the configuration is used."
+msgstr ""
+
+msgctxt "help:sale.configuration,sale_process_after:"
+msgid ""
+"The grace period during which confirmed sale can still be reset to draft.\n"
+"Applied if a worker queue is activated."
+msgstr ""
+"دوره فصلی که در آن فروش تایید شده می تواند دوباره به پیش نویس بازگردد.اگر یک"
+" صف کارگر فعال شود، اعمال می شود."
+
+msgctxt "help:sale.handle.invoice.exception.ask,recreate_invoices:"
+msgid ""
+"The selected invoices will be recreated. The other ones will be ignored."
+msgstr ""
+"صورتحساب های انتخاب شده دوباره ایجاد خواهند شد، مابقی نادیده گرفته میشوند."
+
+msgctxt "help:sale.sale,shipping_date:"
+msgid "When the shipping of goods should start."
+msgstr ""
+
+msgctxt "model:ir.action,name:act_invoice_form"
+msgid "Invoices"
+msgstr "صورتحساب ها"
+
+msgctxt "model:ir.action,name:act_open_customer"
+msgid "Parties associated to Sales"
+msgstr "نهادها/سازمان های مرتبط با فروش ها"
+
+#, fuzzy
+msgctxt "model:ir.action,name:act_product"
+msgid "Products"
+msgstr "محصول"
+
+msgctxt "model:ir.action,name:act_reporting_category"
+msgid "Sales per Category"
+msgstr "Sales per Category"
+
+msgctxt "model:ir.action,name:act_reporting_category_time_series"
+msgid "Sales per Category"
+msgstr "Sales per Category"
+
+msgctxt "model:ir.action,name:act_reporting_category_tree"
+msgid "Sales per Category"
+msgstr "Sales per Category"
+
+msgctxt "model:ir.action,name:act_reporting_country_subdivision_time_series"
+msgid "Sales per Subdivision"
+msgstr "Sales per Subdivision"
+
+msgctxt "model:ir.action,name:act_reporting_country_time_series"
+msgid "Sales per Country"
+msgstr "Sales per Country"
+
+msgctxt "model:ir.action,name:act_reporting_customer"
+msgid "Sales per Customer"
+msgstr "Sales per Customer"
+
+msgctxt "model:ir.action,name:act_reporting_customer_time_series"
+msgid "Sales per Customer"
+msgstr "Sales per Customer"
+
+msgctxt "model:ir.action,name:act_reporting_product"
+msgid "Sales per Product"
+msgstr "Sales per Product"
+
+msgctxt "model:ir.action,name:act_reporting_product_time_series"
+msgid "Sales per Product"
+msgstr "Sales per Product"
+
+msgctxt "model:ir.action,name:act_reporting_region"
+msgid "Sales per Region"
+msgstr "Sales per Region"
+
+msgctxt "model:ir.action,name:act_return_form"
+msgid "Returns"
+msgstr "برگشتی ها"
+
+#, fuzzy
+msgctxt "model:ir.action,name:act_sale_configuration_form"
+msgid "Configuration"
+msgstr "پیکربندی"
+
+msgctxt "model:ir.action,name:act_sale_form"
+msgid "Sales"
+msgstr "فروش ها"
+
+msgctxt "model:ir.action,name:act_sale_form2"
+msgid "Sales"
+msgstr "فروش ها"
+
+msgctxt "model:ir.action,name:act_sale_invoice_relate"
+msgid "Sales"
+msgstr "فروش ها"
+
+#, fuzzy
+msgctxt "model:ir.action,name:act_sale_move_relate"
+msgid "Moves"
+msgstr "جابجایی ها"
+
+msgctxt "model:ir.action,name:act_sale_shipment_returns_relate"
+msgid "Sales"
+msgstr "Sales"
+
+msgctxt "model:ir.action,name:act_sale_shipments_relate"
+msgid "Sales"
+msgstr "فروش ها"
+
+msgctxt "model:ir.action,name:act_shipment_form"
+msgid "Shipments"
+msgstr "محموله ها"
+
+msgctxt "model:ir.action,name:report_sale"
+msgid "Sale"
+msgstr "فروش"
+
+msgctxt "model:ir.action,name:wizard_invoice_handle_exception"
+msgid "Handle Invoice Exception"
+msgstr "رسیدگی به صورتحساب های اعتراضی"
+
+msgctxt "model:ir.action,name:wizard_modify_header"
+msgid "Modify Header"
+msgstr "Modify Header"
+
+msgctxt "model:ir.action,name:wizard_reporting_region_open"
+msgid "Open Region"
+msgstr "Open Region"
+
+msgctxt "model:ir.action,name:wizard_return_sale"
+msgid "Return Sale"
+msgstr "برگشتی فروش"
+
+msgctxt "model:ir.action,name:wizard_shipment_handle_exception"
+msgid "Handle Shipment Exception"
+msgstr "رسیدگی به محموله های اعتراضی"
+
+msgctxt "model:ir.action.act_window.domain,name:act_sale_form_domain_all"
+msgid "All"
+msgstr "همه"
+
+msgctxt ""
+"model:ir.action.act_window.domain,name:act_sale_form_domain_confirmed"
+msgid "Confirmed"
+msgstr "تایید شده"
+
+msgctxt "model:ir.action.act_window.domain,name:act_sale_form_domain_draft"
+msgid "Draft"
+msgstr "پیشنویس"
+
+#, fuzzy
+msgctxt ""
+"model:ir.action.act_window.domain,name:act_sale_form_domain_exception"
+msgid "Exception"
+msgstr "اعتراض"
+
+msgctxt ""
+"model:ir.action.act_window.domain,name:act_sale_form_domain_processing"
+msgid "Processing"
+msgstr "در حال پردازش"
+
+msgctxt ""
+"model:ir.action.act_window.domain,name:act_sale_form_domain_quotation"
+msgid "Quotation"
+msgstr "نقل قول"
+
+msgctxt "model:ir.message,text:msg_erase_party_pending_sale"
+msgid ""
+"You cannot erase party \"%(party)s\" while they have pending sales with "
+"company \"%(company)s\"."
+msgstr ""
+"شما نمیتوانید نهاد/سازمان: \"%(party)s\"را هنگامی که فروش هایی معوق با شرکت:"
+" \"%(company)s\"دارد را حذف کنید."
+
+msgctxt "model:ir.message,text:msg_sale_customer_location_required"
+msgid ""
+"To process sale \"%(sale)s\" you must set a customer location on party "
+"\"%(party)s\"."
+msgstr ""
+"برای پردازش فروش: \"%(sale)s\" شما باید مکان مشتری را در نهاد/سازمان : "
+"\"%(party)s\" تنظیم کنید."
+
+msgctxt "model:ir.message,text:msg_sale_delete_cancel"
+msgid "To delete sale \"%(sale)s\" you must cancel it."
+msgstr "برای حذف فروش : \"%(sale)s\" شما باید ابتدا آنرا لغو کنید."
+
+msgctxt "model:ir.message,text:msg_sale_invalid_method"
+msgid ""
+"You cannot use together invoice \"%(invoice_method)s\" and shipment "
+"\"%(shipment_method)s\" on sale \"%(sale)s\"."
+msgstr ""
+"شما نمیتوانید در فروش : \"%(sale)s\" صورتحساب :\"%(invoice_method)s\"و حمل و"
+" نقل :\"%(shipment_method)s\" را با هم استفاده کنید."
+
+msgctxt ""
+"model:ir.message,text:msg_sale_invoice_address_required_for_quotation"
+msgid "To get a quote for sale \"%(sale)s\" you must enter an invoice address."
+msgstr ""
+"برای دریافت یک نقل قول برای فروش : \"%(sale)s\"شما باید آدرس صورتحساب را "
+"وارد کنید."
+
+msgctxt "model:ir.message,text:msg_sale_invoice_reset_draft"
+msgid ""
+"You cannot reset invoice \"%(invoice)s\" to draft because it was generated "
+"by a sale."
+msgstr ""
+"شما نمیتوانید صورتحساب :\"%(invoice)s\"را به حالت پیش نویس بازنشانی کنید "
+"چراکه توسط یک فروش ایجاد شده است."
+
+msgctxt "model:ir.message,text:msg_sale_line_delete_cancel_draft"
+msgid ""
+"To delete line \"%(line)s\" you must cancel or reset to draft sale "
+"\"%(sale)s\"."
+msgstr ""
+"برای حذف سطر:\"%(line)s\" شما باید فروش :\"%(sale)s\"را لغو یا به حالت پیش "
+"نویس بازنشانی کنید."
+
+#, fuzzy
+msgctxt "model:ir.message,text:msg_sale_missing_account_revenue"
+msgid "To invoice sale \"%(sale)s\" you must configure a default account revenue."
+msgstr ""
+"برای صورتحساب فروش :\"%(sale)s\" شما باید یک حساب درآمد پیش فرض پیکربندی "
+"کنید."
+
+msgctxt "model:ir.message,text:msg_sale_modify_header_draft"
+msgid "To modify the header of sale \"%(sale)s\", it must be in \"draft\" state."
+msgstr "برای تغیر عنوان فروش :\"%(sale)s\" حالت آن باید به پیش نویس بازنشانی شود."
+
+msgctxt "model:ir.message,text:msg_sale_move_reset_draft"
+msgid ""
+"You cannot reset move \"%(move)s\" to draft because it was generated by a "
+"sale."
+msgstr ""
+"شما نمیتوانید جابجایی:\"%(move)s\"را به حالت پیش نویس بازنشانی کنید چراکه "
+"توسط یک فروش ایجاد شده است."
+
+#, fuzzy
+msgctxt "model:ir.message,text:msg_sale_product_missing_account_revenue"
+msgid ""
+"To invoice sale \"%(sale)s\" you must define an account revenue for product "
+"\"%(product)s\"."
+msgstr ""
+"برای صورتحساب فروش :\"%(sale)s\" شما باید یک حساب درآمد برای محصول : "
+"\"%(product)s\" تعریف کنید."
+
+#, fuzzy
+msgctxt "model:ir.message,text:msg_sale_reporting_company"
+msgid "Company"
+msgstr "شرکت"
+
+#, fuzzy
+msgctxt "model:ir.message,text:msg_sale_reporting_currency"
+msgid "Currency"
+msgstr "واحد پول"
+
+#, fuzzy
+msgctxt "model:ir.message,text:msg_sale_reporting_currency_digits"
+msgid "Currency Digits"
+msgstr "رقم های واحد پول"
+
+#, fuzzy
+msgctxt "model:ir.message,text:msg_sale_reporting_number"
+msgid "#"
+msgstr "#"
+
+#, fuzzy
+msgctxt "model:ir.message,text:msg_sale_reporting_number_help"
+msgid "Number of sales"
+msgstr "تعداد فروش ها"
+
+#, fuzzy
+msgctxt "model:ir.message,text:msg_sale_reporting_revenue"
+msgid "Revenue"
+msgstr "درآمد"
+
+#, fuzzy
+msgctxt "model:ir.message,text:msg_sale_reporting_revenue_trend"
+msgid "Revenue Trend"
+msgstr "روند درآمد"
+
+msgctxt ""
+"model:ir.message,text:msg_sale_shipment_address_required_for_quotation"
+msgid "To get a quote for sale \"%(sale)s\" you must enter a shipment address."
+msgstr ""
+"برای دریافت یک نقل قول برای فروش : \"%(sale)s\"شما باید یک آدرس حمل ونقل را "
+"وارد کنید."
+
+msgctxt "model:ir.message,text:msg_sale_warehouse_required_for_quotation"
+msgid "To get a quote for sale \"%(sale)s\" you must enter a warehouse."
+msgstr ""
+"برای دریافت یک نقل قول برای فروش : \"%(sale)s\"شما باید یک انبار را وارد "
+"کنید."
+
+msgctxt "model:ir.model.button,string:sale_cancel_button"
+msgid "Cancel"
+msgstr "Cancel"
+
+msgctxt "model:ir.model.button,string:sale_confirm_button"
+msgid "Confirm"
+msgstr "Confirm"
+
+msgctxt "model:ir.model.button,string:sale_draft_button"
+msgid "Draft"
+msgstr "Draft"
+
+msgctxt "model:ir.model.button,string:sale_handle_invoice_exception_button"
+msgid "Handle Invoice Exception"
+msgstr "Handle Invoice Exception"
+
+msgctxt "model:ir.model.button,string:sale_handle_shipment_exception_button"
+msgid "Handle Shipment Exception"
+msgstr "Handle Shipment Exception"
+
+msgctxt "model:ir.model.button,string:sale_modify_header_button"
+msgid "Modify Header"
+msgstr "Modify Header"
+
+msgctxt "model:ir.model.button,string:sale_process_button"
+msgid "Process"
+msgstr "Process"
+
+msgctxt "model:ir.model.button,string:sale_quote_button"
+msgid "Quote"
+msgstr "Quote"
+
+msgctxt "model:ir.rule.group,name:rule_group_reporting_category_companies"
+msgid "User in companies"
+msgstr ""
+
+msgctxt ""
+"model:ir.rule.group,name:rule_group_reporting_category_time_series_companies"
+msgid "User in companies"
+msgstr ""
+
+msgctxt ""
+"model:ir.rule.group,name:rule_group_reporting_country_subdivision_time_series_companies"
+msgid "User in companies"
+msgstr ""
+
+msgctxt ""
+"model:ir.rule.group,name:rule_group_reporting_country_time_series_companies"
+msgid "User in companies"
+msgstr ""
+
+msgctxt "model:ir.rule.group,name:rule_group_reporting_customer_companies"
+msgid "User in companies"
+msgstr ""
+
+msgctxt ""
+"model:ir.rule.group,name:rule_group_reporting_customer_time_series_companies"
+msgid "User in companies"
+msgstr ""
+
+msgctxt "model:ir.rule.group,name:rule_group_reporting_product_companies"
+msgid "User in companies"
+msgstr ""
+
+msgctxt ""
+"model:ir.rule.group,name:rule_group_reporting_product_time_series_companies"
+msgid "User in companies"
+msgstr ""
+
+msgctxt "model:ir.rule.group,name:rule_group_reporting_region_companies"
+msgid "User in companies"
+msgstr ""
+
+msgctxt "model:ir.rule.group,name:rule_group_sale_companies"
+msgid "User in companies"
+msgstr ""
+
+msgctxt "model:ir.sequence,name:sequence_sale"
+msgid "Sale"
+msgstr "فروش"
+
+msgctxt "model:ir.sequence.type,name:sequence_type_sale"
+msgid "Sale"
+msgstr "فروش"
+
+msgctxt "model:ir.ui.menu,name:menu_configuration"
+msgid "Configuration"
+msgstr "پیکربندی"
+
+#, fuzzy
+msgctxt "model:ir.ui.menu,name:menu_customer"
+msgid "Associated to Sales"
+msgstr "نهادها/سازمان های مرتبط با فروش ها"
+
+#, fuzzy
+msgctxt "model:ir.ui.menu,name:menu_product"
+msgid "Products"
+msgstr "محصول"
+
+msgctxt "model:ir.ui.menu,name:menu_reporting"
+msgid "Reporting"
+msgstr "Reporting"
+
+msgctxt "model:ir.ui.menu,name:menu_reporting_sale"
+msgid "Sales"
+msgstr "Sales"
+
+msgctxt "model:ir.ui.menu,name:menu_sale"
+msgid "Sales"
+msgstr "فروش ها"
+
+#, fuzzy
+msgctxt "model:ir.ui.menu,name:menu_sale_configuration"
+msgid "Configuration"
+msgstr "پیکربندی"
+
+msgctxt "model:ir.ui.menu,name:menu_sale_form"
+msgid "Sales"
+msgstr "فروش ها"
+
+msgctxt "model:product.configuration.default_lead_time,name:"
+msgid "Product Default Lead Time"
+msgstr ""
+
+#, fuzzy
+msgctxt "model:product.sale.context,name:"
+msgid "Product Sale Context"
+msgstr "پس از فرایند فروش"
+
+msgctxt "model:res.group,name:group_sale"
+msgid "Sales"
+msgstr "فروش ها"
+
+msgctxt "model:res.group,name:group_sale_admin"
+msgid "Sales Administrator"
+msgstr "مدیریت فروش ها"
+
+msgctxt "model:sale.configuration,name:"
+msgid "Sale Configuration"
+msgstr "پیکربندی فروش"
+
+msgctxt "model:sale.configuration.sale_method,name:"
+msgid "Sale Configuration Sale Method"
+msgstr "پیکربندی فروش ؛ متد فروش"
+
+msgctxt "model:sale.configuration.sequence,name:"
+msgid "Sale Configuration Sequence"
+msgstr "ادامه پیکربندی فروش"
+
+msgctxt "model:sale.handle.invoice.exception.ask,name:"
+msgid "Handle Invoice Exception"
+msgstr "رسیدگی به صورتحساب های اعتراضی"
+
+msgctxt "model:sale.handle.shipment.exception.ask,name:"
+msgid "Handle Shipment Exception"
+msgstr "رسیدگی به محموله های اعتراضی"
+
+msgctxt "model:sale.line,name:"
+msgid "Sale Line"
+msgstr "سطر فروش"
+
+msgctxt "model:sale.line-account.tax,name:"
+msgid "Sale Line - Tax"
+msgstr "سطر فروش - مالیات"
+
+msgctxt "model:sale.line-ignored-stock.move,name:"
+msgid "Sale Line - Ignored Move"
+msgstr "سطر فروش - جابجایی نادیده گرفته شده"
+
+msgctxt "model:sale.line-recreated-stock.move,name:"
+msgid "Sale Line - Recreated Move"
+msgstr "جابجایی دوباره انجام شده - سطر فروش"
+
+msgctxt "model:sale.reporting.category,name:"
+msgid "Sale Reporting per Category"
+msgstr "گزارش فروش در هر زیرمجموعه"
+
+msgctxt "model:sale.reporting.category.time_series,name:"
+msgid "Sale Reporting per Category"
+msgstr "گزارش فروش در هر زیرمجموعه"
+
+msgctxt "model:sale.reporting.category.tree,name:"
+msgid "Sale Reporting per Category"
+msgstr "گزارش فروش در هر زیرمجموعه"
+
+msgctxt "model:sale.reporting.context,name:"
+msgid "Sale Reporting Context"
+msgstr "مفاد گزارش فروش"
+
+msgctxt "model:sale.reporting.country,name:"
+msgid "Sale Reporting per Country"
+msgstr "گزارش فروش در هر کشور"
+
+msgctxt "model:sale.reporting.country.subdivision,name:"
+msgid "Sale Reporting per Subdivision"
+msgstr "گزارش فروش در هر استان"
+
+msgctxt "model:sale.reporting.country.subdivision.time_series,name:"
+msgid "Sale Reporting per Subdivision"
+msgstr "گزارش فروش در هر استان"
+
+msgctxt "model:sale.reporting.country.time_series,name:"
+msgid "Sale Reporting per Country"
+msgstr "گزارش فروش در هر کشور"
+
+msgctxt "model:sale.reporting.customer,name:"
+msgid "Sale Reporting per Customer"
+msgstr "گزارش فروش برای هر مشتری"
+
+msgctxt "model:sale.reporting.customer.time_series,name:"
+msgid "Sale Reporting per Customer"
+msgstr "گزارش فروش برای هر مشتری"
+
+msgctxt "model:sale.reporting.product,name:"
+msgid "Sale Reporting per Product"
+msgstr "گزارش فروش در هر محصول"
+
+msgctxt "model:sale.reporting.product.time_series,name:"
+msgid "Sale Reporting per Product"
+msgstr "گزارش فروش در هر محصول"
+
+msgctxt "model:sale.reporting.region,name:"
+msgid "Sale Reporting per Region"
+msgstr "گزارش فروش در هر منطقه"
+
+msgctxt "model:sale.return_sale.start,name:"
+msgid "Return Sale"
+msgstr "برگشتی فروش"
+
+msgctxt "model:sale.sale,name:"
+msgid "Sale"
+msgstr "فروش"
+
+msgctxt "model:sale.sale-ignored-account.invoice,name:"
+msgid "Sale - Ignored Invoice"
+msgstr "فروش - فاکتور نادیده گرفته شده"
+
+msgctxt "model:sale.sale-recreated-account.invoice,name:"
+msgid "Sale - Recreated Invoice"
+msgstr "صورتحساب دوباره ایجاد شده - فروش"
+
+msgctxt "report:sale.sale:"
+msgid ":"
+msgstr ":"
+
+msgctxt "report:sale.sale:"
+msgid "Amount"
+msgstr "مقدار"
+
+msgctxt "report:sale.sale:"
+msgid "Date:"
+msgstr "تاریخ :"
+
+msgctxt "report:sale.sale:"
+msgid "Description"
+msgstr "شرح"
+
+msgctxt "report:sale.sale:"
+msgid "Description:"
+msgstr "توضیحات :"
+
+msgctxt "report:sale.sale:"
+msgid "Draft Sale Order"
+msgstr "پیش نویس دستور فروش"
+
+msgctxt "report:sale.sale:"
+msgid "Quantity"
+msgstr "مقدار/تعداد"
+
+msgctxt "report:sale.sale:"
+msgid "Quotation N°:"
+msgstr "نقل قول N°:"
+
+msgctxt "report:sale.sale:"
+msgid "Reference:"
+msgstr "ارجاع :"
+
+msgctxt "report:sale.sale:"
+msgid "Sale Order N°:"
+msgstr "دستور فروش N° :"
+
+msgctxt "report:sale.sale:"
+msgid "Taxes"
+msgstr "مالیات ها"
+
+msgctxt "report:sale.sale:"
+msgid "Taxes:"
+msgstr "مالیات ها :"
+
+msgctxt "report:sale.sale:"
+msgid "Total (excl. taxes):"
+msgstr "مجموع (بدون احتساب مالیات) :"
+
+msgctxt "report:sale.sale:"
+msgid "Total:"
+msgstr "مجموع :"
+
+msgctxt "report:sale.sale:"
+msgid "Unit Price"
+msgstr "قیمت واحد"
+
+msgctxt "selection:account.invoice,sale_exception_state:"
+msgid "Ignored"
+msgstr "نادیده گرفته شده"
+
+msgctxt "selection:account.invoice,sale_exception_state:"
+msgid "Recreated"
+msgstr "دوباره ایجاد شده"
+
+msgctxt "selection:sale.line,type:"
+msgid "Comment"
+msgstr "اظهار نظر"
+
+msgctxt "selection:sale.line,type:"
+msgid "Line"
+msgstr "سطر"
+
+msgctxt "selection:sale.line,type:"
+msgid "Subtotal"
+msgstr "زیرمجموع"
+
+msgctxt "selection:sale.line,type:"
+msgid "Title"
+msgstr "عنوان"
+
+msgctxt "selection:sale.reporting.context,period:"
+msgid "Day"
+msgstr "روز"
+
+msgctxt "selection:sale.reporting.context,period:"
+msgid "Month"
+msgstr "ماه"
+
+msgctxt "selection:sale.reporting.context,period:"
+msgid "Year"
+msgstr "سال"
+
+msgctxt "selection:sale.sale,invoice_method:"
+msgid "Manual"
+msgstr "دستی"
+
+msgctxt "selection:sale.sale,invoice_method:"
+msgid "On Order Processed"
+msgstr "در دستور پردازش شده"
+
+msgctxt "selection:sale.sale,invoice_method:"
+msgid "On Shipment Sent"
+msgstr "در ارسال حمل و نقل"
+
+msgctxt "selection:sale.sale,invoice_state:"
+msgid "Exception"
+msgstr "اعتراض"
+
+msgctxt "selection:sale.sale,invoice_state:"
+msgid "None"
+msgstr "هیجکدام"
+
+msgctxt "selection:sale.sale,invoice_state:"
+msgid "Paid"
+msgstr "پرداخت شده"
+
+msgctxt "selection:sale.sale,invoice_state:"
+msgid "Waiting"
+msgstr "در انتظار"
+
+msgctxt "selection:sale.sale,shipment_method:"
+msgid "Manual"
+msgstr "دستی"
+
+msgctxt "selection:sale.sale,shipment_method:"
+msgid "On Invoice Paid"
+msgstr "در فاکتور پرداخت شده"
+
+msgctxt "selection:sale.sale,shipment_method:"
+msgid "On Order Processed"
+msgstr "در دستور پردازش شده"
+
+msgctxt "selection:sale.sale,shipment_state:"
+msgid "Exception"
+msgstr "اعتراض"
+
+msgctxt "selection:sale.sale,shipment_state:"
+msgid "None"
+msgstr "هیجکدام"
+
+msgctxt "selection:sale.sale,shipment_state:"
+msgid "Sent"
+msgstr "ارسال"
+
+msgctxt "selection:sale.sale,shipment_state:"
+msgid "Waiting"
+msgstr "در انتظار"
+
+#, fuzzy
+msgctxt "selection:sale.sale,state:"
+msgid "Cancelled"
+msgstr "لغو شده"
+
+msgctxt "selection:sale.sale,state:"
+msgid "Confirmed"
+msgstr "تایید شده"
+
+msgctxt "selection:sale.sale,state:"
+msgid "Done"
+msgstr "انجام شد"
+
+msgctxt "selection:sale.sale,state:"
+msgid "Draft"
+msgstr "پیشنویس"
+
+msgctxt "selection:sale.sale,state:"
+msgid "Processing"
+msgstr "در حال پردازش"
+
+msgctxt "selection:sale.sale,state:"
+msgid "Quotation"
+msgstr "نقل قول"
+
+msgctxt "selection:stock.move,sale_exception_state:"
+msgid "Ignored"
+msgstr "نادیده گرفته شده"
+
+msgctxt "selection:stock.move,sale_exception_state:"
+msgid "Recreated"
+msgstr "دوباره ایجاد شده"
+
+msgctxt "view:party.party:"
+msgid "Sale"
+msgstr "فروش"
+
+msgctxt "view:product.template:"
+msgid "Customers"
+msgstr "مشتریان"
+
+#, fuzzy
+msgctxt "view:sale.handle.invoice.exception.ask:"
+msgid "Choose invoices to recreate:"
+msgstr "انتخاب صورتحساب ها برای ایجاد دوباره"
+
+#, fuzzy
+msgctxt "view:sale.handle.shipment.exception.ask:"
+msgid "Choose move to recreate:"
+msgstr "انتخاب جابجایی برای ایجاد دوباره"
+
+msgctxt "view:sale.line:"
+msgid "General"
+msgstr "عمومی"
+
+msgctxt "view:sale.line:"
+msgid "Notes"
+msgstr "یادداشت ها"
+
+msgctxt "view:sale.line:"
+msgid "Taxes"
+msgstr "مالیات ها"
+
+#, fuzzy
+msgctxt "view:sale.return_sale.start:"
+msgid "Are you sure to return these/this sale(s)?"
+msgstr "آیا شما برای برگشت این فروش(ها) اطمینان دارید؟"
+
+msgctxt "view:sale.sale:"
+msgid "Other Info"
+msgstr "سایر اطلاعات"
+
+msgctxt "view:sale.sale:"
+msgid "Sale"
+msgstr "فروش"
+
+msgctxt "wizard_button:sale.handle.invoice.exception,ask,end:"
+msgid "Cancel"
+msgstr "انصراف"
+
+msgctxt "wizard_button:sale.handle.invoice.exception,ask,handle:"
+msgid "OK"
+msgstr "قبول"
+
+msgctxt "wizard_button:sale.handle.shipment.exception,ask,end:"
+msgid "Cancel"
+msgstr "انصراف"
+
+msgctxt "wizard_button:sale.handle.shipment.exception,ask,handle:"
+msgid "OK"
+msgstr "قبول"
+
+msgctxt "wizard_button:sale.modify_header,start,end:"
+msgid "Cancel"
+msgstr "انصراف"
+
+msgctxt "wizard_button:sale.modify_header,start,modify:"
+msgid "Modify"
+msgstr "تغییر"
+
+msgctxt "wizard_button:sale.return_sale,start,end:"
+msgid "Cancel"
+msgstr "انصراف"
+
+msgctxt "wizard_button:sale.return_sale,start,return_:"
+msgid "Return"
+msgstr "بازگشت"
diff --git a/modules/sale/locale/fi.po b/modules/sale/locale/fi.po
new file mode 100644
index 0000000000..24a9c4bb45
--- /dev/null
+++ b/modules/sale/locale/fi.po
@@ -0,0 +1,1383 @@
+#
+msgid ""
+msgstr "Content-Type: text/plain; charset=utf-8\n"
+
+msgctxt "field:account.invoice,sale_exception_state:"
+msgid "Exception State"
+msgstr ""
+
+#, fuzzy
+msgctxt "field:account.invoice,sales:"
+msgid "Sales"
+msgstr "Sales"
+
+msgctxt "field:product.configuration,default_lead_time:"
+msgid "Default Lead Time"
+msgstr ""
+
+msgctxt "field:product.configuration.default_lead_time,company:"
+msgid "Company"
+msgstr ""
+
+msgctxt "field:product.configuration.default_lead_time,default_lead_time:"
+msgid "Default Lead Time"
+msgstr ""
+
+msgctxt "field:product.product,lead_time:"
+msgid "Lead Time"
+msgstr ""
+
+msgctxt "field:product.product,salable:"
+msgid "Salable"
+msgstr ""
+
+msgctxt "field:product.product,sale_price_uom:"
+msgid "Sale Price"
+msgstr ""
+
+msgctxt "field:product.product,sale_uom:"
+msgid "Sale UOM"
+msgstr ""
+
+msgctxt "field:product.sale.context,company:"
+msgid "Company"
+msgstr ""
+
+msgctxt "field:product.sale.context,currency:"
+msgid "Currency"
+msgstr ""
+
+#, fuzzy
+msgctxt "field:product.sale.context,customer:"
+msgid "Customer"
+msgstr "Sales per Customer"
+
+msgctxt "field:product.sale.context,locations:"
+msgid "Warehouses"
+msgstr ""
+
+msgctxt "field:product.sale.context,quantity:"
+msgid "Quantity"
+msgstr ""
+
+#, fuzzy
+msgctxt "field:product.sale.context,sale_date:"
+msgid "Sale Date"
+msgstr "Sales"
+
+msgctxt "field:product.sale.context,stock_date_end:"
+msgid "Stock End Date"
+msgstr ""
+
+msgctxt "field:product.template,lead_time:"
+msgid "Lead Time"
+msgstr ""
+
+msgctxt "field:product.template,salable:"
+msgid "Salable"
+msgstr ""
+
+msgctxt "field:product.template,sale_uom:"
+msgid "Sale UOM"
+msgstr ""
+
+msgctxt "field:sale.configuration,sale_invoice_method:"
+msgid "Sale Invoice Method"
+msgstr ""
+
+msgctxt "field:sale.configuration,sale_process_after:"
+msgid "Process Sale after"
+msgstr ""
+
+msgctxt "field:sale.configuration,sale_sequence:"
+msgid "Sale Sequence"
+msgstr ""
+
+msgctxt "field:sale.configuration,sale_shipment_method:"
+msgid "Sale Shipment Method"
+msgstr ""
+
+msgctxt "field:sale.configuration.sale_method,sale_invoice_method:"
+msgid "Sale Invoice Method"
+msgstr ""
+
+msgctxt "field:sale.configuration.sale_method,sale_shipment_method:"
+msgid "Sale Shipment Method"
+msgstr ""
+
+msgctxt "field:sale.configuration.sequence,company:"
+msgid "Company"
+msgstr ""
+
+msgctxt "field:sale.configuration.sequence,sale_sequence:"
+msgid "Sale Sequence"
+msgstr ""
+
+msgctxt "field:sale.handle.invoice.exception.ask,domain_invoices:"
+msgid "Domain Invoices"
+msgstr ""
+
+msgctxt "field:sale.handle.invoice.exception.ask,recreate_invoices:"
+msgid "Recreate Invoices"
+msgstr ""
+
+msgctxt "field:sale.handle.shipment.exception.ask,domain_moves:"
+msgid "Domain Moves"
+msgstr ""
+
+msgctxt "field:sale.handle.shipment.exception.ask,recreate_moves:"
+msgid "Recreate Moves"
+msgstr ""
+
+msgctxt "field:sale.line,actual_quantity:"
+msgid "Actual Quantity"
+msgstr ""
+
+msgctxt "field:sale.line,amount:"
+msgid "Amount"
+msgstr ""
+
+msgctxt "field:sale.line,company:"
+msgid "Company"
+msgstr ""
+
+msgctxt "field:sale.line,currency:"
+msgid "Currency"
+msgstr ""
+
+msgctxt "field:sale.line,description:"
+msgid "Description"
+msgstr ""
+
+msgctxt "field:sale.line,from_location:"
+msgid "From Location"
+msgstr ""
+
+msgctxt "field:sale.line,invoice_lines:"
+msgid "Invoice Lines"
+msgstr ""
+
+msgctxt "field:sale.line,move_done:"
+msgid "Moves Done"
+msgstr ""
+
+msgctxt "field:sale.line,move_exception:"
+msgid "Moves Exception"
+msgstr ""
+
+msgctxt "field:sale.line,moves:"
+msgid "Moves"
+msgstr ""
+
+msgctxt "field:sale.line,moves_ignored:"
+msgid "Ignored Moves"
+msgstr ""
+
+msgctxt "field:sale.line,moves_recreated:"
+msgid "Recreated Moves"
+msgstr ""
+
+msgctxt "field:sale.line,note:"
+msgid "Note"
+msgstr ""
+
+msgctxt "field:sale.line,product:"
+msgid "Product"
+msgstr ""
+
+msgctxt "field:sale.line,product_uom_category:"
+msgid "Product Uom Category"
+msgstr ""
+
+msgctxt "field:sale.line,quantity:"
+msgid "Quantity"
+msgstr ""
+
+#, fuzzy
+msgctxt "field:sale.line,sale:"
+msgid "Sale"
+msgstr "Sales"
+
+msgctxt "field:sale.line,sale_state:"
+msgid "Sale State"
+msgstr ""
+
+msgctxt "field:sale.line,shipping_date:"
+msgid "Shipping Date"
+msgstr ""
+
+msgctxt "field:sale.line,summary:"
+msgid "Summary"
+msgstr ""
+
+msgctxt "field:sale.line,taxes:"
+msgid "Taxes"
+msgstr ""
+
+msgctxt "field:sale.line,to_location:"
+msgid "To Location"
+msgstr ""
+
+msgctxt "field:sale.line,type:"
+msgid "Type"
+msgstr ""
+
+msgctxt "field:sale.line,unit:"
+msgid "Unit"
+msgstr ""
+
+msgctxt "field:sale.line,unit_digits:"
+msgid "Unit Digits"
+msgstr ""
+
+msgctxt "field:sale.line,unit_price:"
+msgid "Unit Price"
+msgstr ""
+
+msgctxt "field:sale.line,warehouse:"
+msgid "Warehouse"
+msgstr ""
+
+msgctxt "field:sale.line-account.tax,line:"
+msgid "Sale Line"
+msgstr ""
+
+msgctxt "field:sale.line-account.tax,tax:"
+msgid "Tax"
+msgstr ""
+
+msgctxt "field:sale.line-ignored-stock.move,move:"
+msgid "Move"
+msgstr ""
+
+msgctxt "field:sale.line-ignored-stock.move,sale_line:"
+msgid "Sale Line"
+msgstr ""
+
+msgctxt "field:sale.line-recreated-stock.move,move:"
+msgid "Move"
+msgstr ""
+
+msgctxt "field:sale.line-recreated-stock.move,sale_line:"
+msgid "Sale Line"
+msgstr ""
+
+msgctxt "field:sale.reporting.category,category:"
+msgid "Category"
+msgstr ""
+
+msgctxt "field:sale.reporting.category,time_series:"
+msgid "Time Series"
+msgstr ""
+
+msgctxt "field:sale.reporting.category.time_series,category:"
+msgid "Category"
+msgstr ""
+
+msgctxt "field:sale.reporting.category.time_series,date:"
+msgid "Date"
+msgstr ""
+
+msgctxt "field:sale.reporting.category.tree,children:"
+msgid "Children"
+msgstr ""
+
+msgctxt "field:sale.reporting.category.tree,currency_digits:"
+msgid "Currency Digits"
+msgstr ""
+
+msgctxt "field:sale.reporting.category.tree,name:"
+msgid "Name"
+msgstr ""
+
+msgctxt "field:sale.reporting.category.tree,parent:"
+msgid "Parent"
+msgstr ""
+
+msgctxt "field:sale.reporting.category.tree,revenue:"
+msgid "Revenue"
+msgstr ""
+
+msgctxt "field:sale.reporting.context,company:"
+msgid "Company"
+msgstr ""
+
+msgctxt "field:sale.reporting.context,from_date:"
+msgid "From Date"
+msgstr ""
+
+msgctxt "field:sale.reporting.context,period:"
+msgid "Period"
+msgstr ""
+
+msgctxt "field:sale.reporting.context,to_date:"
+msgid "To Date"
+msgstr ""
+
+msgctxt "field:sale.reporting.context,warehouse:"
+msgid "Warehouse"
+msgstr ""
+
+msgctxt "field:sale.reporting.country,country:"
+msgid "Country"
+msgstr ""
+
+msgctxt "field:sale.reporting.country,time_series:"
+msgid "Time Series"
+msgstr ""
+
+msgctxt "field:sale.reporting.country.subdivision,country:"
+msgid "Country"
+msgstr ""
+
+msgctxt "field:sale.reporting.country.subdivision,subdivision:"
+msgid "Subdivision"
+msgstr ""
+
+msgctxt "field:sale.reporting.country.subdivision,time_series:"
+msgid "Time Series"
+msgstr ""
+
+msgctxt "field:sale.reporting.country.subdivision.time_series,country:"
+msgid "Country"
+msgstr ""
+
+msgctxt "field:sale.reporting.country.subdivision.time_series,date:"
+msgid "Date"
+msgstr ""
+
+msgctxt "field:sale.reporting.country.subdivision.time_series,subdivision:"
+msgid "Subdivision"
+msgstr ""
+
+msgctxt "field:sale.reporting.country.time_series,country:"
+msgid "Country"
+msgstr ""
+
+msgctxt "field:sale.reporting.country.time_series,date:"
+msgid "Date"
+msgstr ""
+
+msgctxt "field:sale.reporting.customer,customer:"
+msgid "Customer"
+msgstr ""
+
+msgctxt "field:sale.reporting.customer,time_series:"
+msgid "Time Series"
+msgstr ""
+
+msgctxt "field:sale.reporting.customer.time_series,customer:"
+msgid "Customer"
+msgstr ""
+
+msgctxt "field:sale.reporting.customer.time_series,date:"
+msgid "Date"
+msgstr ""
+
+msgctxt "field:sale.reporting.product,product:"
+msgid "Product"
+msgstr ""
+
+msgctxt "field:sale.reporting.product,time_series:"
+msgid "Time Series"
+msgstr ""
+
+msgctxt "field:sale.reporting.product.time_series,date:"
+msgid "Date"
+msgstr ""
+
+msgctxt "field:sale.reporting.product.time_series,product:"
+msgid "Product"
+msgstr ""
+
+msgctxt "field:sale.reporting.region,children:"
+msgid "Children"
+msgstr ""
+
+msgctxt "field:sale.reporting.region,parent:"
+msgid "Parent"
+msgstr ""
+
+msgctxt "field:sale.reporting.region,region:"
+msgid "Region"
+msgstr ""
+
+msgctxt "field:sale.sale,comment:"
+msgid "Comment"
+msgstr ""
+
+msgctxt "field:sale.sale,company:"
+msgid "Company"
+msgstr ""
+
+#, fuzzy
+msgctxt "field:sale.sale,confirmed_by:"
+msgid "Confirmed By"
+msgstr "Confirmed"
+
+msgctxt "field:sale.sale,contact:"
+msgid "Contact"
+msgstr ""
+
+msgctxt "field:sale.sale,currency:"
+msgid "Currency"
+msgstr ""
+
+msgctxt "field:sale.sale,currency_digits:"
+msgid "Currency Digits"
+msgstr ""
+
+msgctxt "field:sale.sale,description:"
+msgid "Description"
+msgstr ""
+
+msgctxt "field:sale.sale,invoice_address:"
+msgid "Invoice Address"
+msgstr ""
+
+msgctxt "field:sale.sale,invoice_method:"
+msgid "Invoice Method"
+msgstr ""
+
+#, fuzzy
+msgctxt "field:sale.sale,invoice_party:"
+msgid "Invoice Party"
+msgstr "Invoices"
+
+msgctxt "field:sale.sale,invoice_state:"
+msgid "Invoice State"
+msgstr ""
+
+#, fuzzy
+msgctxt "field:sale.sale,invoices:"
+msgid "Invoices"
+msgstr "Invoices"
+
+msgctxt "field:sale.sale,invoices_ignored:"
+msgid "Ignored Invoices"
+msgstr ""
+
+msgctxt "field:sale.sale,invoices_recreated:"
+msgid "Recreated Invoices"
+msgstr ""
+
+msgctxt "field:sale.sale,lines:"
+msgid "Lines"
+msgstr ""
+
+msgctxt "field:sale.sale,moves:"
+msgid "Moves"
+msgstr ""
+
+msgctxt "field:sale.sale,number:"
+msgid "Number"
+msgstr ""
+
+msgctxt "field:sale.sale,origin:"
+msgid "Origin"
+msgstr ""
+
+msgctxt "field:sale.sale,party:"
+msgid "Party"
+msgstr ""
+
+msgctxt "field:sale.sale,party_lang:"
+msgid "Party Language"
+msgstr ""
+
+msgctxt "field:sale.sale,payment_term:"
+msgid "Payment Term"
+msgstr ""
+
+#, fuzzy
+msgctxt "field:sale.sale,quoted_by:"
+msgid "Quoted By"
+msgstr "Quote"
+
+msgctxt "field:sale.sale,reference:"
+msgid "Reference"
+msgstr ""
+
+msgctxt "field:sale.sale,sale_date:"
+msgid "Sale Date"
+msgstr ""
+
+msgctxt "field:sale.sale,shipment_address:"
+msgid "Shipment Address"
+msgstr ""
+
+msgctxt "field:sale.sale,shipment_method:"
+msgid "Shipment Method"
+msgstr ""
+
+msgctxt "field:sale.sale,shipment_party:"
+msgid "Shipment Party"
+msgstr ""
+
+msgctxt "field:sale.sale,shipment_returns:"
+msgid "Shipment Returns"
+msgstr ""
+
+msgctxt "field:sale.sale,shipment_state:"
+msgid "Shipment State"
+msgstr ""
+
+#, fuzzy
+msgctxt "field:sale.sale,shipments:"
+msgid "Shipments"
+msgstr "Shipments"
+
+msgctxt "field:sale.sale,shipping_date:"
+msgid "Shipping Date"
+msgstr ""
+
+msgctxt "field:sale.sale,state:"
+msgid "State"
+msgstr ""
+
+msgctxt "field:sale.sale,tax_amount:"
+msgid "Tax"
+msgstr ""
+
+msgctxt "field:sale.sale,tax_amount_cache:"
+msgid "Tax Cache"
+msgstr ""
+
+msgctxt "field:sale.sale,total_amount:"
+msgid "Total"
+msgstr ""
+
+msgctxt "field:sale.sale,total_amount_cache:"
+msgid "Total Cache"
+msgstr ""
+
+msgctxt "field:sale.sale,untaxed_amount:"
+msgid "Untaxed"
+msgstr ""
+
+msgctxt "field:sale.sale,untaxed_amount_cache:"
+msgid "Untaxed Cache"
+msgstr ""
+
+msgctxt "field:sale.sale,warehouse:"
+msgid "Warehouse"
+msgstr ""
+
+#, fuzzy
+msgctxt "field:sale.sale-ignored-account.invoice,invoice:"
+msgid "Invoice"
+msgstr "Invoices"
+
+#, fuzzy
+msgctxt "field:sale.sale-ignored-account.invoice,sale:"
+msgid "Sale"
+msgstr "Sales"
+
+#, fuzzy
+msgctxt "field:sale.sale-recreated-account.invoice,invoice:"
+msgid "Invoice"
+msgstr "Invoices"
+
+#, fuzzy
+msgctxt "field:sale.sale-recreated-account.invoice,sale:"
+msgid "Sale"
+msgstr "Sales"
+
+#, fuzzy
+msgctxt "field:stock.move,sale:"
+msgid "Sale"
+msgstr "Sales"
+
+msgctxt "field:stock.move,sale_exception_state:"
+msgid "Exception State"
+msgstr ""
+
+msgctxt "help:product.configuration,default_lead_time:"
+msgid ""
+"The time from confirming the sales order to sending the products.\n"
+"Used for products without a lead time."
+msgstr ""
+
+msgctxt "help:product.product,lead_time:"
+msgid ""
+"The time from confirming the sales order to sending the products.\n"
+"If empty the default lead time from the configuration is used."
+msgstr ""
+
+msgctxt "help:product.template,lead_time:"
+msgid ""
+"The time from confirming the sales order to sending the products.\n"
+"If empty the default lead time from the configuration is used."
+msgstr ""
+
+msgctxt "help:sale.configuration,sale_process_after:"
+msgid ""
+"The grace period during which confirmed sale can still be reset to draft.\n"
+"Applied if a worker queue is activated."
+msgstr ""
+
+msgctxt "help:sale.handle.invoice.exception.ask,recreate_invoices:"
+msgid ""
+"The selected invoices will be recreated. The other ones will be ignored."
+msgstr ""
+
+msgctxt "help:sale.sale,shipping_date:"
+msgid "When the shipping of goods should start."
+msgstr ""
+
+msgctxt "model:ir.action,name:act_invoice_form"
+msgid "Invoices"
+msgstr "Invoices"
+
+msgctxt "model:ir.action,name:act_open_customer"
+msgid "Parties associated to Sales"
+msgstr "Parties associated to Sales"
+
+#, fuzzy
+msgctxt "model:ir.action,name:act_product"
+msgid "Products"
+msgstr "Sales per Product"
+
+msgctxt "model:ir.action,name:act_reporting_category"
+msgid "Sales per Category"
+msgstr "Sales per Category"
+
+msgctxt "model:ir.action,name:act_reporting_category_time_series"
+msgid "Sales per Category"
+msgstr "Sales per Category"
+
+msgctxt "model:ir.action,name:act_reporting_category_tree"
+msgid "Sales per Category"
+msgstr "Sales per Category"
+
+msgctxt "model:ir.action,name:act_reporting_country_subdivision_time_series"
+msgid "Sales per Subdivision"
+msgstr "Sales per Subdivision"
+
+msgctxt "model:ir.action,name:act_reporting_country_time_series"
+msgid "Sales per Country"
+msgstr "Sales per Country"
+
+msgctxt "model:ir.action,name:act_reporting_customer"
+msgid "Sales per Customer"
+msgstr "Sales per Customer"
+
+msgctxt "model:ir.action,name:act_reporting_customer_time_series"
+msgid "Sales per Customer"
+msgstr "Sales per Customer"
+
+msgctxt "model:ir.action,name:act_reporting_product"
+msgid "Sales per Product"
+msgstr "Sales per Product"
+
+msgctxt "model:ir.action,name:act_reporting_product_time_series"
+msgid "Sales per Product"
+msgstr "Sales per Product"
+
+msgctxt "model:ir.action,name:act_reporting_region"
+msgid "Sales per Region"
+msgstr "Sales per Region"
+
+msgctxt "model:ir.action,name:act_return_form"
+msgid "Returns"
+msgstr "Returns"
+
+#, fuzzy
+msgctxt "model:ir.action,name:act_sale_configuration_form"
+msgid "Configuration"
+msgstr "Configuration"
+
+msgctxt "model:ir.action,name:act_sale_form"
+msgid "Sales"
+msgstr "Sales"
+
+msgctxt "model:ir.action,name:act_sale_form2"
+msgid "Sales"
+msgstr "Sales"
+
+msgctxt "model:ir.action,name:act_sale_invoice_relate"
+msgid "Sales"
+msgstr "Sales"
+
+msgctxt "model:ir.action,name:act_sale_move_relate"
+msgid "Moves"
+msgstr ""
+
+msgctxt "model:ir.action,name:act_sale_shipment_returns_relate"
+msgid "Sales"
+msgstr "Sales"
+
+msgctxt "model:ir.action,name:act_sale_shipments_relate"
+msgid "Sales"
+msgstr "Sales"
+
+msgctxt "model:ir.action,name:act_shipment_form"
+msgid "Shipments"
+msgstr "Shipments"
+
+#, fuzzy
+msgctxt "model:ir.action,name:report_sale"
+msgid "Sale"
+msgstr "Sale"
+
+msgctxt "model:ir.action,name:wizard_invoice_handle_exception"
+msgid "Handle Invoice Exception"
+msgstr "Handle Invoice Exception"
+
+msgctxt "model:ir.action,name:wizard_modify_header"
+msgid "Modify Header"
+msgstr "Modify Header"
+
+msgctxt "model:ir.action,name:wizard_reporting_region_open"
+msgid "Open Region"
+msgstr "Open Region"
+
+msgctxt "model:ir.action,name:wizard_return_sale"
+msgid "Return Sale"
+msgstr "Return Sale"
+
+msgctxt "model:ir.action,name:wizard_shipment_handle_exception"
+msgid "Handle Shipment Exception"
+msgstr "Handle Shipment Exception"
+
+msgctxt "model:ir.action.act_window.domain,name:act_sale_form_domain_all"
+msgid "All"
+msgstr "All"
+
+#, fuzzy
+msgctxt ""
+"model:ir.action.act_window.domain,name:act_sale_form_domain_confirmed"
+msgid "Confirmed"
+msgstr "Confirmed"
+
+msgctxt "model:ir.action.act_window.domain,name:act_sale_form_domain_draft"
+msgid "Draft"
+msgstr "Draft"
+
+msgctxt ""
+"model:ir.action.act_window.domain,name:act_sale_form_domain_exception"
+msgid "Exception"
+msgstr ""
+
+msgctxt ""
+"model:ir.action.act_window.domain,name:act_sale_form_domain_processing"
+msgid "Processing"
+msgstr "Processing"
+
+msgctxt ""
+"model:ir.action.act_window.domain,name:act_sale_form_domain_quotation"
+msgid "Quotation"
+msgstr "Quotation"
+
+msgctxt "model:ir.message,text:msg_erase_party_pending_sale"
+msgid ""
+"You cannot erase party \"%(party)s\" while they have pending sales with "
+"company \"%(company)s\"."
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_sale_customer_location_required"
+msgid ""
+"To process sale \"%(sale)s\" you must set a customer location on party "
+"\"%(party)s\"."
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_sale_delete_cancel"
+msgid "To delete sale \"%(sale)s\" you must cancel it."
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_sale_invalid_method"
+msgid ""
+"You cannot use together invoice \"%(invoice_method)s\" and shipment "
+"\"%(shipment_method)s\" on sale \"%(sale)s\"."
+msgstr ""
+
+msgctxt ""
+"model:ir.message,text:msg_sale_invoice_address_required_for_quotation"
+msgid "To get a quote for sale \"%(sale)s\" you must enter an invoice address."
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_sale_invoice_reset_draft"
+msgid ""
+"You cannot reset invoice \"%(invoice)s\" to draft because it was generated "
+"by a sale."
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_sale_line_delete_cancel_draft"
+msgid ""
+"To delete line \"%(line)s\" you must cancel or reset to draft sale "
+"\"%(sale)s\"."
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_sale_missing_account_revenue"
+msgid "To invoice sale \"%(sale)s\" you must configure a default account revenue."
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_sale_modify_header_draft"
+msgid "To modify the header of sale \"%(sale)s\", it must be in \"draft\" state."
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_sale_move_reset_draft"
+msgid ""
+"You cannot reset move \"%(move)s\" to draft because it was generated by a "
+"sale."
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_sale_product_missing_account_revenue"
+msgid ""
+"To invoice sale \"%(sale)s\" you must define an account revenue for product "
+"\"%(product)s\"."
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_sale_reporting_company"
+msgid "Company"
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_sale_reporting_currency"
+msgid "Currency"
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_sale_reporting_currency_digits"
+msgid "Currency Digits"
+msgstr ""
+
+#, fuzzy
+msgctxt "model:ir.message,text:msg_sale_reporting_number"
+msgid "#"
+msgstr "#"
+
+msgctxt "model:ir.message,text:msg_sale_reporting_number_help"
+msgid "Number of sales"
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_sale_reporting_revenue"
+msgid "Revenue"
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_sale_reporting_revenue_trend"
+msgid "Revenue Trend"
+msgstr ""
+
+msgctxt ""
+"model:ir.message,text:msg_sale_shipment_address_required_for_quotation"
+msgid "To get a quote for sale \"%(sale)s\" you must enter a shipment address."
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_sale_warehouse_required_for_quotation"
+msgid "To get a quote for sale \"%(sale)s\" you must enter a warehouse."
+msgstr ""
+
+msgctxt "model:ir.model.button,string:sale_cancel_button"
+msgid "Cancel"
+msgstr "Cancel"
+
+msgctxt "model:ir.model.button,string:sale_confirm_button"
+msgid "Confirm"
+msgstr "Confirm"
+
+msgctxt "model:ir.model.button,string:sale_draft_button"
+msgid "Draft"
+msgstr "Draft"
+
+msgctxt "model:ir.model.button,string:sale_handle_invoice_exception_button"
+msgid "Handle Invoice Exception"
+msgstr "Handle Invoice Exception"
+
+msgctxt "model:ir.model.button,string:sale_handle_shipment_exception_button"
+msgid "Handle Shipment Exception"
+msgstr "Handle Shipment Exception"
+
+msgctxt "model:ir.model.button,string:sale_modify_header_button"
+msgid "Modify Header"
+msgstr "Modify Header"
+
+msgctxt "model:ir.model.button,string:sale_process_button"
+msgid "Process"
+msgstr "Process"
+
+msgctxt "model:ir.model.button,string:sale_quote_button"
+msgid "Quote"
+msgstr "Quote"
+
+msgctxt "model:ir.rule.group,name:rule_group_reporting_category_companies"
+msgid "User in companies"
+msgstr ""
+
+msgctxt ""
+"model:ir.rule.group,name:rule_group_reporting_category_time_series_companies"
+msgid "User in companies"
+msgstr ""
+
+msgctxt ""
+"model:ir.rule.group,name:rule_group_reporting_country_subdivision_time_series_companies"
+msgid "User in companies"
+msgstr ""
+
+msgctxt ""
+"model:ir.rule.group,name:rule_group_reporting_country_time_series_companies"
+msgid "User in companies"
+msgstr ""
+
+msgctxt "model:ir.rule.group,name:rule_group_reporting_customer_companies"
+msgid "User in companies"
+msgstr ""
+
+msgctxt ""
+"model:ir.rule.group,name:rule_group_reporting_customer_time_series_companies"
+msgid "User in companies"
+msgstr ""
+
+msgctxt "model:ir.rule.group,name:rule_group_reporting_product_companies"
+msgid "User in companies"
+msgstr ""
+
+msgctxt ""
+"model:ir.rule.group,name:rule_group_reporting_product_time_series_companies"
+msgid "User in companies"
+msgstr ""
+
+msgctxt "model:ir.rule.group,name:rule_group_reporting_region_companies"
+msgid "User in companies"
+msgstr ""
+
+msgctxt "model:ir.rule.group,name:rule_group_sale_companies"
+msgid "User in companies"
+msgstr ""
+
+#, fuzzy
+msgctxt "model:ir.sequence,name:sequence_sale"
+msgid "Sale"
+msgstr "Sale"
+
+#, fuzzy
+msgctxt "model:ir.sequence.type,name:sequence_type_sale"
+msgid "Sale"
+msgstr "Sale"
+
+msgctxt "model:ir.ui.menu,name:menu_configuration"
+msgid "Configuration"
+msgstr "Configuration"
+
+#, fuzzy
+msgctxt "model:ir.ui.menu,name:menu_customer"
+msgid "Associated to Sales"
+msgstr "Parties associated to Sales"
+
+#, fuzzy
+msgctxt "model:ir.ui.menu,name:menu_product"
+msgid "Products"
+msgstr "Sales per Product"
+
+msgctxt "model:ir.ui.menu,name:menu_reporting"
+msgid "Reporting"
+msgstr "Reporting"
+
+msgctxt "model:ir.ui.menu,name:menu_reporting_sale"
+msgid "Sales"
+msgstr "Sales"
+
+msgctxt "model:ir.ui.menu,name:menu_sale"
+msgid "Sales"
+msgstr "Sales"
+
+#, fuzzy
+msgctxt "model:ir.ui.menu,name:menu_sale_configuration"
+msgid "Configuration"
+msgstr "Configuration"
+
+msgctxt "model:ir.ui.menu,name:menu_sale_form"
+msgid "Sales"
+msgstr "Sales"
+
+msgctxt "model:product.configuration.default_lead_time,name:"
+msgid "Product Default Lead Time"
+msgstr ""
+
+msgctxt "model:product.sale.context,name:"
+msgid "Product Sale Context"
+msgstr ""
+
+msgctxt "model:res.group,name:group_sale"
+msgid "Sales"
+msgstr "Sales"
+
+msgctxt "model:res.group,name:group_sale_admin"
+msgid "Sales Administrator"
+msgstr "Sales Administrator"
+
+#, fuzzy
+msgctxt "model:sale.configuration,name:"
+msgid "Sale Configuration"
+msgstr "Sales Configuration"
+
+msgctxt "model:sale.configuration.sale_method,name:"
+msgid "Sale Configuration Sale Method"
+msgstr ""
+
+msgctxt "model:sale.configuration.sequence,name:"
+msgid "Sale Configuration Sequence"
+msgstr ""
+
+#, fuzzy
+msgctxt "model:sale.handle.invoice.exception.ask,name:"
+msgid "Handle Invoice Exception"
+msgstr "Handle Invoice Exception"
+
+#, fuzzy
+msgctxt "model:sale.handle.shipment.exception.ask,name:"
+msgid "Handle Shipment Exception"
+msgstr "Handle Shipment Exception"
+
+msgctxt "model:sale.line,name:"
+msgid "Sale Line"
+msgstr ""
+
+msgctxt "model:sale.line-account.tax,name:"
+msgid "Sale Line - Tax"
+msgstr ""
+
+msgctxt "model:sale.line-ignored-stock.move,name:"
+msgid "Sale Line - Ignored Move"
+msgstr ""
+
+msgctxt "model:sale.line-recreated-stock.move,name:"
+msgid "Sale Line - Recreated Move"
+msgstr ""
+
+msgctxt "model:sale.reporting.category,name:"
+msgid "Sale Reporting per Category"
+msgstr ""
+
+msgctxt "model:sale.reporting.category.time_series,name:"
+msgid "Sale Reporting per Category"
+msgstr ""
+
+msgctxt "model:sale.reporting.category.tree,name:"
+msgid "Sale Reporting per Category"
+msgstr ""
+
+msgctxt "model:sale.reporting.context,name:"
+msgid "Sale Reporting Context"
+msgstr ""
+
+msgctxt "model:sale.reporting.country,name:"
+msgid "Sale Reporting per Country"
+msgstr ""
+
+msgctxt "model:sale.reporting.country.subdivision,name:"
+msgid "Sale Reporting per Subdivision"
+msgstr ""
+
+msgctxt "model:sale.reporting.country.subdivision.time_series,name:"
+msgid "Sale Reporting per Subdivision"
+msgstr ""
+
+msgctxt "model:sale.reporting.country.time_series,name:"
+msgid "Sale Reporting per Country"
+msgstr ""
+
+msgctxt "model:sale.reporting.customer,name:"
+msgid "Sale Reporting per Customer"
+msgstr ""
+
+msgctxt "model:sale.reporting.customer.time_series,name:"
+msgid "Sale Reporting per Customer"
+msgstr ""
+
+msgctxt "model:sale.reporting.product,name:"
+msgid "Sale Reporting per Product"
+msgstr ""
+
+msgctxt "model:sale.reporting.product.time_series,name:"
+msgid "Sale Reporting per Product"
+msgstr ""
+
+msgctxt "model:sale.reporting.region,name:"
+msgid "Sale Reporting per Region"
+msgstr ""
+
+#, fuzzy
+msgctxt "model:sale.return_sale.start,name:"
+msgid "Return Sale"
+msgstr "Return Sale"
+
+#, fuzzy
+msgctxt "model:sale.sale,name:"
+msgid "Sale"
+msgstr "Sales"
+
+msgctxt "model:sale.sale-ignored-account.invoice,name:"
+msgid "Sale - Ignored Invoice"
+msgstr ""
+
+msgctxt "model:sale.sale-recreated-account.invoice,name:"
+msgid "Sale - Recreated Invoice"
+msgstr ""
+
+#, fuzzy
+msgctxt "report:sale.sale:"
+msgid ":"
+msgstr ":"
+
+msgctxt "report:sale.sale:"
+msgid "Amount"
+msgstr ""
+
+msgctxt "report:sale.sale:"
+msgid "Date:"
+msgstr ""
+
+msgctxt "report:sale.sale:"
+msgid "Description"
+msgstr ""
+
+msgctxt "report:sale.sale:"
+msgid "Description:"
+msgstr ""
+
+msgctxt "report:sale.sale:"
+msgid "Draft Sale Order"
+msgstr ""
+
+msgctxt "report:sale.sale:"
+msgid "Quantity"
+msgstr ""
+
+msgctxt "report:sale.sale:"
+msgid "Quotation N°:"
+msgstr ""
+
+msgctxt "report:sale.sale:"
+msgid "Reference:"
+msgstr ""
+
+msgctxt "report:sale.sale:"
+msgid "Sale Order N°:"
+msgstr ""
+
+msgctxt "report:sale.sale:"
+msgid "Taxes"
+msgstr ""
+
+msgctxt "report:sale.sale:"
+msgid "Taxes:"
+msgstr ""
+
+msgctxt "report:sale.sale:"
+msgid "Total (excl. taxes):"
+msgstr ""
+
+msgctxt "report:sale.sale:"
+msgid "Total:"
+msgstr ""
+
+msgctxt "report:sale.sale:"
+msgid "Unit Price"
+msgstr ""
+
+msgctxt "selection:account.invoice,sale_exception_state:"
+msgid "Ignored"
+msgstr ""
+
+msgctxt "selection:account.invoice,sale_exception_state:"
+msgid "Recreated"
+msgstr ""
+
+msgctxt "selection:sale.line,type:"
+msgid "Comment"
+msgstr ""
+
+msgctxt "selection:sale.line,type:"
+msgid "Line"
+msgstr ""
+
+msgctxt "selection:sale.line,type:"
+msgid "Subtotal"
+msgstr ""
+
+msgctxt "selection:sale.line,type:"
+msgid "Title"
+msgstr ""
+
+msgctxt "selection:sale.reporting.context,period:"
+msgid "Day"
+msgstr ""
+
+msgctxt "selection:sale.reporting.context,period:"
+msgid "Month"
+msgstr ""
+
+msgctxt "selection:sale.reporting.context,period:"
+msgid "Year"
+msgstr ""
+
+msgctxt "selection:sale.sale,invoice_method:"
+msgid "Manual"
+msgstr ""
+
+msgctxt "selection:sale.sale,invoice_method:"
+msgid "On Order Processed"
+msgstr ""
+
+msgctxt "selection:sale.sale,invoice_method:"
+msgid "On Shipment Sent"
+msgstr ""
+
+msgctxt "selection:sale.sale,invoice_state:"
+msgid "Exception"
+msgstr ""
+
+msgctxt "selection:sale.sale,invoice_state:"
+msgid "None"
+msgstr ""
+
+msgctxt "selection:sale.sale,invoice_state:"
+msgid "Paid"
+msgstr ""
+
+msgctxt "selection:sale.sale,invoice_state:"
+msgid "Waiting"
+msgstr ""
+
+msgctxt "selection:sale.sale,shipment_method:"
+msgid "Manual"
+msgstr ""
+
+msgctxt "selection:sale.sale,shipment_method:"
+msgid "On Invoice Paid"
+msgstr ""
+
+msgctxt "selection:sale.sale,shipment_method:"
+msgid "On Order Processed"
+msgstr ""
+
+msgctxt "selection:sale.sale,shipment_state:"
+msgid "Exception"
+msgstr ""
+
+msgctxt "selection:sale.sale,shipment_state:"
+msgid "None"
+msgstr ""
+
+msgctxt "selection:sale.sale,shipment_state:"
+msgid "Sent"
+msgstr ""
+
+msgctxt "selection:sale.sale,shipment_state:"
+msgid "Waiting"
+msgstr ""
+
+#, fuzzy
+msgctxt "selection:sale.sale,state:"
+msgid "Cancelled"
+msgstr "Cancel"
+
+#, fuzzy
+msgctxt "selection:sale.sale,state:"
+msgid "Confirmed"
+msgstr "Confirm"
+
+msgctxt "selection:sale.sale,state:"
+msgid "Done"
+msgstr ""
+
+#, fuzzy
+msgctxt "selection:sale.sale,state:"
+msgid "Draft"
+msgstr "Draft"
+
+#, fuzzy
+msgctxt "selection:sale.sale,state:"
+msgid "Processing"
+msgstr "Processing"
+
+#, fuzzy
+msgctxt "selection:sale.sale,state:"
+msgid "Quotation"
+msgstr "Quotation"
+
+msgctxt "selection:stock.move,sale_exception_state:"
+msgid "Ignored"
+msgstr ""
+
+msgctxt "selection:stock.move,sale_exception_state:"
+msgid "Recreated"
+msgstr ""
+
+#, fuzzy
+msgctxt "view:party.party:"
+msgid "Sale"
+msgstr "Sales"
+
+msgctxt "view:product.template:"
+msgid "Customers"
+msgstr ""
+
+msgctxt "view:sale.handle.invoice.exception.ask:"
+msgid "Choose invoices to recreate:"
+msgstr ""
+
+msgctxt "view:sale.handle.shipment.exception.ask:"
+msgid "Choose move to recreate:"
+msgstr ""
+
+msgctxt "view:sale.line:"
+msgid "General"
+msgstr ""
+
+msgctxt "view:sale.line:"
+msgid "Notes"
+msgstr ""
+
+msgctxt "view:sale.line:"
+msgid "Taxes"
+msgstr ""
+
+msgctxt "view:sale.return_sale.start:"
+msgid "Are you sure to return these/this sale(s)?"
+msgstr ""
+
+msgctxt "view:sale.sale:"
+msgid "Other Info"
+msgstr ""
+
+#, fuzzy
+msgctxt "view:sale.sale:"
+msgid "Sale"
+msgstr "Sales"
+
+#, fuzzy
+msgctxt "wizard_button:sale.handle.invoice.exception,ask,end:"
+msgid "Cancel"
+msgstr "Cancel"
+
+msgctxt "wizard_button:sale.handle.invoice.exception,ask,handle:"
+msgid "OK"
+msgstr ""
+
+#, fuzzy
+msgctxt "wizard_button:sale.handle.shipment.exception,ask,end:"
+msgid "Cancel"
+msgstr "Cancel"
+
+msgctxt "wizard_button:sale.handle.shipment.exception,ask,handle:"
+msgid "OK"
+msgstr ""
+
+#, fuzzy
+msgctxt "wizard_button:sale.modify_header,start,end:"
+msgid "Cancel"
+msgstr "Cancel"
+
+msgctxt "wizard_button:sale.modify_header,start,modify:"
+msgid "Modify"
+msgstr ""
+
+#, fuzzy
+msgctxt "wizard_button:sale.return_sale,start,end:"
+msgid "Cancel"
+msgstr "Cancel"
+
+#, fuzzy
+msgctxt "wizard_button:sale.return_sale,start,return_:"
+msgid "Return"
+msgstr "Returns"
diff --git a/modules/sale/locale/fr.po b/modules/sale/locale/fr.po
new file mode 100644
index 0000000000..ec42291fea
--- /dev/null
+++ b/modules/sale/locale/fr.po
@@ -0,0 +1,1375 @@
+#
+msgid ""
+msgstr "Content-Type: text/plain; charset=utf-8\n"
+
+msgctxt "field:account.invoice,sale_exception_state:"
+msgid "Exception State"
+msgstr "État d'exception"
+
+msgctxt "field:account.invoice,sales:"
+msgid "Sales"
+msgstr "Ventes"
+
+msgctxt "field:product.configuration,default_lead_time:"
+msgid "Default Lead Time"
+msgstr "Délai d'éxécution par défaut"
+
+msgctxt "field:product.configuration.default_lead_time,company:"
+msgid "Company"
+msgstr "Société"
+
+msgctxt "field:product.configuration.default_lead_time,default_lead_time:"
+msgid "Default Lead Time"
+msgstr "Délai d'éxécution par défaut"
+
+msgctxt "field:product.product,lead_time:"
+msgid "Lead Time"
+msgstr "Délai d'exécution"
+
+msgctxt "field:product.product,salable:"
+msgid "Salable"
+msgstr "Vendable"
+
+msgctxt "field:product.product,sale_price_uom:"
+msgid "Sale Price"
+msgstr "Prix de vente"
+
+msgctxt "field:product.product,sale_uom:"
+msgid "Sale UOM"
+msgstr "UDM de vente"
+
+msgctxt "field:product.sale.context,company:"
+msgid "Company"
+msgstr "Société"
+
+msgctxt "field:product.sale.context,currency:"
+msgid "Currency"
+msgstr "Devise"
+
+msgctxt "field:product.sale.context,customer:"
+msgid "Customer"
+msgstr "Client"
+
+msgctxt "field:product.sale.context,locations:"
+msgid "Warehouses"
+msgstr "Entrepôts"
+
+msgctxt "field:product.sale.context,quantity:"
+msgid "Quantity"
+msgstr "Quantité"
+
+msgctxt "field:product.sale.context,sale_date:"
+msgid "Sale Date"
+msgstr "Date de la vente"
+
+msgctxt "field:product.sale.context,stock_date_end:"
+msgid "Stock End Date"
+msgstr "Date de fin de stock"
+
+msgctxt "field:product.template,lead_time:"
+msgid "Lead Time"
+msgstr "Délai d'exécution"
+
+msgctxt "field:product.template,salable:"
+msgid "Salable"
+msgstr "Vendable"
+
+msgctxt "field:product.template,sale_uom:"
+msgid "Sale UOM"
+msgstr "UDM de vente"
+
+msgctxt "field:sale.configuration,sale_invoice_method:"
+msgid "Sale Invoice Method"
+msgstr "Méthode de facturation"
+
+msgctxt "field:sale.configuration,sale_process_after:"
+msgid "Process Sale after"
+msgstr "Traiter les ventes après"
+
+msgctxt "field:sale.configuration,sale_sequence:"
+msgid "Sale Sequence"
+msgstr "Séquence de vente"
+
+msgctxt "field:sale.configuration,sale_shipment_method:"
+msgid "Sale Shipment Method"
+msgstr "Méthode d'expédition"
+
+msgctxt "field:sale.configuration.sale_method,sale_invoice_method:"
+msgid "Sale Invoice Method"
+msgstr "Méthode de facturation de vente"
+
+msgctxt "field:sale.configuration.sale_method,sale_shipment_method:"
+msgid "Sale Shipment Method"
+msgstr "Méthode d'expédition de vente"
+
+msgctxt "field:sale.configuration.sequence,company:"
+msgid "Company"
+msgstr "Société"
+
+msgctxt "field:sale.configuration.sequence,sale_sequence:"
+msgid "Sale Sequence"
+msgstr "Séquence de vente"
+
+msgctxt "field:sale.handle.invoice.exception.ask,domain_invoices:"
+msgid "Domain Invoices"
+msgstr "Domaine des factures"
+
+msgctxt "field:sale.handle.invoice.exception.ask,recreate_invoices:"
+msgid "Recreate Invoices"
+msgstr "Recréer les factures"
+
+msgctxt "field:sale.handle.shipment.exception.ask,domain_moves:"
+msgid "Domain Moves"
+msgstr "Domaine des mouvements"
+
+msgctxt "field:sale.handle.shipment.exception.ask,recreate_moves:"
+msgid "Recreate Moves"
+msgstr "Recréer des mouvements"
+
+msgctxt "field:sale.line,actual_quantity:"
+msgid "Actual Quantity"
+msgstr "Quantité réelle"
+
+msgctxt "field:sale.line,amount:"
+msgid "Amount"
+msgstr "Montant"
+
+msgctxt "field:sale.line,company:"
+msgid "Company"
+msgstr "Société"
+
+msgctxt "field:sale.line,currency:"
+msgid "Currency"
+msgstr "Devise"
+
+msgctxt "field:sale.line,description:"
+msgid "Description"
+msgstr "Description"
+
+msgctxt "field:sale.line,from_location:"
+msgid "From Location"
+msgstr "Emplacement d'origine"
+
+msgctxt "field:sale.line,invoice_lines:"
+msgid "Invoice Lines"
+msgstr "Lignes de facture"
+
+msgctxt "field:sale.line,move_done:"
+msgid "Moves Done"
+msgstr "Mouvements effectués"
+
+msgctxt "field:sale.line,move_exception:"
+msgid "Moves Exception"
+msgstr "Mouvements en exception"
+
+msgctxt "field:sale.line,moves:"
+msgid "Moves"
+msgstr "Mouvements"
+
+msgctxt "field:sale.line,moves_ignored:"
+msgid "Ignored Moves"
+msgstr "Mouvements ignorés"
+
+msgctxt "field:sale.line,moves_recreated:"
+msgid "Recreated Moves"
+msgstr "Mouvements recréés"
+
+msgctxt "field:sale.line,note:"
+msgid "Note"
+msgstr "Note"
+
+msgctxt "field:sale.line,product:"
+msgid "Product"
+msgstr "Produit"
+
+msgctxt "field:sale.line,product_uom_category:"
+msgid "Product Uom Category"
+msgstr "Catégorie d'unité de mesure"
+
+msgctxt "field:sale.line,quantity:"
+msgid "Quantity"
+msgstr "Quantité"
+
+msgctxt "field:sale.line,sale:"
+msgid "Sale"
+msgstr "Vente"
+
+msgctxt "field:sale.line,sale_state:"
+msgid "Sale State"
+msgstr "État de la vente"
+
+msgctxt "field:sale.line,shipping_date:"
+msgid "Shipping Date"
+msgstr "Date de livraison"
+
+msgctxt "field:sale.line,summary:"
+msgid "Summary"
+msgstr "Résumé"
+
+msgctxt "field:sale.line,taxes:"
+msgid "Taxes"
+msgstr "Taxes"
+
+msgctxt "field:sale.line,to_location:"
+msgid "To Location"
+msgstr "Emplacement de destination"
+
+msgctxt "field:sale.line,type:"
+msgid "Type"
+msgstr "Type"
+
+msgctxt "field:sale.line,unit:"
+msgid "Unit"
+msgstr "Unité"
+
+msgctxt "field:sale.line,unit_digits:"
+msgid "Unit Digits"
+msgstr "Décimales de l'unité"
+
+msgctxt "field:sale.line,unit_price:"
+msgid "Unit Price"
+msgstr "Prix unitaire"
+
+msgctxt "field:sale.line,warehouse:"
+msgid "Warehouse"
+msgstr "Entrepôt"
+
+msgctxt "field:sale.line-account.tax,line:"
+msgid "Sale Line"
+msgstr "Ligne de vente"
+
+msgctxt "field:sale.line-account.tax,tax:"
+msgid "Tax"
+msgstr "Taxe"
+
+msgctxt "field:sale.line-ignored-stock.move,move:"
+msgid "Move"
+msgstr "Mouvement"
+
+msgctxt "field:sale.line-ignored-stock.move,sale_line:"
+msgid "Sale Line"
+msgstr "Ligne de vente"
+
+msgctxt "field:sale.line-recreated-stock.move,move:"
+msgid "Move"
+msgstr "Mouvement"
+
+msgctxt "field:sale.line-recreated-stock.move,sale_line:"
+msgid "Sale Line"
+msgstr "Ligne de vente"
+
+msgctxt "field:sale.reporting.category,category:"
+msgid "Category"
+msgstr "Catégorie"
+
+msgctxt "field:sale.reporting.category,time_series:"
+msgid "Time Series"
+msgstr "Séries temporelles"
+
+msgctxt "field:sale.reporting.category.time_series,category:"
+msgid "Category"
+msgstr "Catégorie"
+
+msgctxt "field:sale.reporting.category.time_series,date:"
+msgid "Date"
+msgstr "Date"
+
+msgctxt "field:sale.reporting.category.tree,children:"
+msgid "Children"
+msgstr "Enfants"
+
+msgctxt "field:sale.reporting.category.tree,currency_digits:"
+msgid "Currency Digits"
+msgstr "Décimales de la devise"
+
+msgctxt "field:sale.reporting.category.tree,name:"
+msgid "Name"
+msgstr "Nom"
+
+msgctxt "field:sale.reporting.category.tree,parent:"
+msgid "Parent"
+msgstr "Parent"
+
+msgctxt "field:sale.reporting.category.tree,revenue:"
+msgid "Revenue"
+msgstr "Revenu"
+
+msgctxt "field:sale.reporting.context,company:"
+msgid "Company"
+msgstr "Société"
+
+msgctxt "field:sale.reporting.context,from_date:"
+msgid "From Date"
+msgstr "Date de début"
+
+msgctxt "field:sale.reporting.context,period:"
+msgid "Period"
+msgstr "Période"
+
+msgctxt "field:sale.reporting.context,to_date:"
+msgid "To Date"
+msgstr "Date de fin"
+
+msgctxt "field:sale.reporting.context,warehouse:"
+msgid "Warehouse"
+msgstr "Entrepôt"
+
+msgctxt "field:sale.reporting.country,country:"
+msgid "Country"
+msgstr "Pays"
+
+msgctxt "field:sale.reporting.country,time_series:"
+msgid "Time Series"
+msgstr "Séries temporelles"
+
+msgctxt "field:sale.reporting.country.subdivision,country:"
+msgid "Country"
+msgstr "Pays"
+
+msgctxt "field:sale.reporting.country.subdivision,subdivision:"
+msgid "Subdivision"
+msgstr "Subdivision"
+
+msgctxt "field:sale.reporting.country.subdivision,time_series:"
+msgid "Time Series"
+msgstr "Séries temporelles"
+
+msgctxt "field:sale.reporting.country.subdivision.time_series,country:"
+msgid "Country"
+msgstr "Pays"
+
+msgctxt "field:sale.reporting.country.subdivision.time_series,date:"
+msgid "Date"
+msgstr "Date"
+
+msgctxt "field:sale.reporting.country.subdivision.time_series,subdivision:"
+msgid "Subdivision"
+msgstr "Subdivision"
+
+msgctxt "field:sale.reporting.country.time_series,country:"
+msgid "Country"
+msgstr "Pays"
+
+msgctxt "field:sale.reporting.country.time_series,date:"
+msgid "Date"
+msgstr "Date"
+
+msgctxt "field:sale.reporting.customer,customer:"
+msgid "Customer"
+msgstr "Client"
+
+msgctxt "field:sale.reporting.customer,time_series:"
+msgid "Time Series"
+msgstr "Séries temporelles"
+
+msgctxt "field:sale.reporting.customer.time_series,customer:"
+msgid "Customer"
+msgstr "Client"
+
+msgctxt "field:sale.reporting.customer.time_series,date:"
+msgid "Date"
+msgstr "Date"
+
+msgctxt "field:sale.reporting.product,product:"
+msgid "Product"
+msgstr "Produit"
+
+msgctxt "field:sale.reporting.product,time_series:"
+msgid "Time Series"
+msgstr "Séries temporelles"
+
+msgctxt "field:sale.reporting.product.time_series,date:"
+msgid "Date"
+msgstr "Date"
+
+msgctxt "field:sale.reporting.product.time_series,product:"
+msgid "Product"
+msgstr "Produit"
+
+msgctxt "field:sale.reporting.region,children:"
+msgid "Children"
+msgstr "Enfants"
+
+msgctxt "field:sale.reporting.region,parent:"
+msgid "Parent"
+msgstr "Parent"
+
+msgctxt "field:sale.reporting.region,region:"
+msgid "Region"
+msgstr "Région"
+
+msgctxt "field:sale.sale,comment:"
+msgid "Comment"
+msgstr "Commentaire"
+
+msgctxt "field:sale.sale,company:"
+msgid "Company"
+msgstr "Société"
+
+msgctxt "field:sale.sale,confirmed_by:"
+msgid "Confirmed By"
+msgstr "Confirmée par"
+
+msgctxt "field:sale.sale,contact:"
+msgid "Contact"
+msgstr "Contact"
+
+msgctxt "field:sale.sale,currency:"
+msgid "Currency"
+msgstr "Devise"
+
+msgctxt "field:sale.sale,currency_digits:"
+msgid "Currency Digits"
+msgstr "Décimales de la devise"
+
+msgctxt "field:sale.sale,description:"
+msgid "Description"
+msgstr "Description"
+
+msgctxt "field:sale.sale,invoice_address:"
+msgid "Invoice Address"
+msgstr "Adresse de facturation"
+
+msgctxt "field:sale.sale,invoice_method:"
+msgid "Invoice Method"
+msgstr "Méthode de facturation"
+
+msgctxt "field:sale.sale,invoice_party:"
+msgid "Invoice Party"
+msgstr "Tiers de facturation"
+
+msgctxt "field:sale.sale,invoice_state:"
+msgid "Invoice State"
+msgstr "État de la facture"
+
+msgctxt "field:sale.sale,invoices:"
+msgid "Invoices"
+msgstr "Factures"
+
+msgctxt "field:sale.sale,invoices_ignored:"
+msgid "Ignored Invoices"
+msgstr "Factures ignorées"
+
+msgctxt "field:sale.sale,invoices_recreated:"
+msgid "Recreated Invoices"
+msgstr "Factures recréées"
+
+msgctxt "field:sale.sale,lines:"
+msgid "Lines"
+msgstr "Lignes"
+
+msgctxt "field:sale.sale,moves:"
+msgid "Moves"
+msgstr "Mouvements"
+
+msgctxt "field:sale.sale,number:"
+msgid "Number"
+msgstr "Numéro"
+
+msgctxt "field:sale.sale,origin:"
+msgid "Origin"
+msgstr "Origine"
+
+msgctxt "field:sale.sale,party:"
+msgid "Party"
+msgstr "Tiers"
+
+msgctxt "field:sale.sale,party_lang:"
+msgid "Party Language"
+msgstr "Langue du tiers"
+
+msgctxt "field:sale.sale,payment_term:"
+msgid "Payment Term"
+msgstr "Conditions de paiement"
+
+msgctxt "field:sale.sale,quoted_by:"
+msgid "Quoted By"
+msgstr "Devis fait par"
+
+msgctxt "field:sale.sale,reference:"
+msgid "Reference"
+msgstr "Référence"
+
+msgctxt "field:sale.sale,sale_date:"
+msgid "Sale Date"
+msgstr "Date de la vente"
+
+msgctxt "field:sale.sale,shipment_address:"
+msgid "Shipment Address"
+msgstr "Adresse d'expédition"
+
+msgctxt "field:sale.sale,shipment_method:"
+msgid "Shipment Method"
+msgstr "Méthode d'expédition"
+
+msgctxt "field:sale.sale,shipment_party:"
+msgid "Shipment Party"
+msgstr "Tiers d'expédition"
+
+msgctxt "field:sale.sale,shipment_returns:"
+msgid "Shipment Returns"
+msgstr "Retours d'expédition"
+
+msgctxt "field:sale.sale,shipment_state:"
+msgid "Shipment State"
+msgstr "État de l'expédition"
+
+msgctxt "field:sale.sale,shipments:"
+msgid "Shipments"
+msgstr "Expéditions"
+
+msgctxt "field:sale.sale,shipping_date:"
+msgid "Shipping Date"
+msgstr "Date de livraison"
+
+msgctxt "field:sale.sale,state:"
+msgid "State"
+msgstr "État"
+
+msgctxt "field:sale.sale,tax_amount:"
+msgid "Tax"
+msgstr "Taxe"
+
+msgctxt "field:sale.sale,tax_amount_cache:"
+msgid "Tax Cache"
+msgstr "Cache des taxes"
+
+msgctxt "field:sale.sale,total_amount:"
+msgid "Total"
+msgstr "Total"
+
+msgctxt "field:sale.sale,total_amount_cache:"
+msgid "Total Cache"
+msgstr "Cache du total"
+
+msgctxt "field:sale.sale,untaxed_amount:"
+msgid "Untaxed"
+msgstr "Hors taxe"
+
+msgctxt "field:sale.sale,untaxed_amount_cache:"
+msgid "Untaxed Cache"
+msgstr "Cache hors taxe"
+
+msgctxt "field:sale.sale,warehouse:"
+msgid "Warehouse"
+msgstr "Entrepôt"
+
+msgctxt "field:sale.sale-ignored-account.invoice,invoice:"
+msgid "Invoice"
+msgstr "Facture"
+
+msgctxt "field:sale.sale-ignored-account.invoice,sale:"
+msgid "Sale"
+msgstr "Vente"
+
+msgctxt "field:sale.sale-recreated-account.invoice,invoice:"
+msgid "Invoice"
+msgstr "Facture"
+
+msgctxt "field:sale.sale-recreated-account.invoice,sale:"
+msgid "Sale"
+msgstr "Vente"
+
+msgctxt "field:stock.move,sale:"
+msgid "Sale"
+msgstr "Vente"
+
+msgctxt "field:stock.move,sale_exception_state:"
+msgid "Exception State"
+msgstr "État d'exception"
+
+msgctxt "help:product.configuration,default_lead_time:"
+msgid ""
+"The time from confirming the sales order to sending the products.\n"
+"Used for products without a lead time."
+msgstr ""
+"Le délai entre la confirmation de la vente et l'envoi des produits.\n"
+"Utilisé pour les produits sans délai d'éxécution."
+
+msgctxt "help:product.product,lead_time:"
+msgid ""
+"The time from confirming the sales order to sending the products.\n"
+"If empty the default lead time from the configuration is used."
+msgstr ""
+"Le délai entre la confirmation de la vente et l'envoi des produits.\n"
+"Si vide, le délai d'éxécution par défaut de la configuration est utilisé."
+
+msgctxt "help:product.template,lead_time:"
+msgid ""
+"The time from confirming the sales order to sending the products.\n"
+"If empty the default lead time from the configuration is used."
+msgstr ""
+"Le délai entre la confirmation de la vente et l'envoi des produits.\n"
+"Si vide, le délai d'éxécution par défaut de la configuration est utilisé."
+
+msgctxt "help:sale.configuration,sale_process_after:"
+msgid ""
+"The grace period during which confirmed sale can still be reset to draft.\n"
+"Applied if a worker queue is activated."
+msgstr ""
+"La période de grâce pendant laquelle une vente confirmée peut toujours être réinitialiser à l'état brouillon.\n"
+"S'applique si une fille d'attente de travailleurs est activée."
+
+msgctxt "help:sale.handle.invoice.exception.ask,recreate_invoices:"
+msgid ""
+"The selected invoices will be recreated. The other ones will be ignored."
+msgstr ""
+"Les factures sélectionnées seront recréés. Les autres seront ignorées."
+
+msgctxt "help:sale.sale,shipping_date:"
+msgid "When the shipping of goods should start."
+msgstr "Quand l'expédition des marchandises doit commencer."
+
+msgctxt "model:ir.action,name:act_invoice_form"
+msgid "Invoices"
+msgstr "Factures"
+
+msgctxt "model:ir.action,name:act_open_customer"
+msgid "Parties associated to Sales"
+msgstr "Tiers associés à des ventes"
+
+msgctxt "model:ir.action,name:act_product"
+msgid "Products"
+msgstr "Produits"
+
+msgctxt "model:ir.action,name:act_reporting_category"
+msgid "Sales per Category"
+msgstr "Ventes par catégorie"
+
+msgctxt "model:ir.action,name:act_reporting_category_time_series"
+msgid "Sales per Category"
+msgstr "Ventes par catégorie"
+
+msgctxt "model:ir.action,name:act_reporting_category_tree"
+msgid "Sales per Category"
+msgstr "Ventes par catégorie"
+
+msgctxt "model:ir.action,name:act_reporting_country_subdivision_time_series"
+msgid "Sales per Subdivision"
+msgstr "Ventes par subdivision"
+
+msgctxt "model:ir.action,name:act_reporting_country_time_series"
+msgid "Sales per Country"
+msgstr "Ventes par pays"
+
+msgctxt "model:ir.action,name:act_reporting_customer"
+msgid "Sales per Customer"
+msgstr "Ventes par client"
+
+msgctxt "model:ir.action,name:act_reporting_customer_time_series"
+msgid "Sales per Customer"
+msgstr "Ventes par client"
+
+msgctxt "model:ir.action,name:act_reporting_product"
+msgid "Sales per Product"
+msgstr "Ventes par produit"
+
+msgctxt "model:ir.action,name:act_reporting_product_time_series"
+msgid "Sales per Product"
+msgstr "Ventes par produit"
+
+msgctxt "model:ir.action,name:act_reporting_region"
+msgid "Sales per Region"
+msgstr "Ventes par région"
+
+msgctxt "model:ir.action,name:act_return_form"
+msgid "Returns"
+msgstr "Retours"
+
+msgctxt "model:ir.action,name:act_sale_configuration_form"
+msgid "Configuration"
+msgstr "Configuration"
+
+msgctxt "model:ir.action,name:act_sale_form"
+msgid "Sales"
+msgstr "Ventes"
+
+msgctxt "model:ir.action,name:act_sale_form2"
+msgid "Sales"
+msgstr "Ventes"
+
+msgctxt "model:ir.action,name:act_sale_invoice_relate"
+msgid "Sales"
+msgstr "Ventes"
+
+msgctxt "model:ir.action,name:act_sale_move_relate"
+msgid "Moves"
+msgstr "Mouvements"
+
+msgctxt "model:ir.action,name:act_sale_shipment_returns_relate"
+msgid "Sales"
+msgstr "Ventes"
+
+msgctxt "model:ir.action,name:act_sale_shipments_relate"
+msgid "Sales"
+msgstr "Ventes"
+
+msgctxt "model:ir.action,name:act_shipment_form"
+msgid "Shipments"
+msgstr "Expéditions"
+
+msgctxt "model:ir.action,name:report_sale"
+msgid "Sale"
+msgstr "Vente"
+
+msgctxt "model:ir.action,name:wizard_invoice_handle_exception"
+msgid "Handle Invoice Exception"
+msgstr "Gérer l'exception de facture"
+
+msgctxt "model:ir.action,name:wizard_modify_header"
+msgid "Modify Header"
+msgstr "Modifier l'entête"
+
+msgctxt "model:ir.action,name:wizard_reporting_region_open"
+msgid "Open Region"
+msgstr "Ouvrir la région"
+
+msgctxt "model:ir.action,name:wizard_return_sale"
+msgid "Return Sale"
+msgstr "Retourner la vente"
+
+msgctxt "model:ir.action,name:wizard_shipment_handle_exception"
+msgid "Handle Shipment Exception"
+msgstr "Gérer l'exception d'expédition"
+
+msgctxt "model:ir.action.act_window.domain,name:act_sale_form_domain_all"
+msgid "All"
+msgstr "Toutes"
+
+msgctxt ""
+"model:ir.action.act_window.domain,name:act_sale_form_domain_confirmed"
+msgid "Confirmed"
+msgstr "Confirmées"
+
+msgctxt "model:ir.action.act_window.domain,name:act_sale_form_domain_draft"
+msgid "Draft"
+msgstr "Brouillons"
+
+msgctxt ""
+"model:ir.action.act_window.domain,name:act_sale_form_domain_exception"
+msgid "Exception"
+msgstr "Exception"
+
+msgctxt ""
+"model:ir.action.act_window.domain,name:act_sale_form_domain_processing"
+msgid "Processing"
+msgstr "En traitements"
+
+msgctxt ""
+"model:ir.action.act_window.domain,name:act_sale_form_domain_quotation"
+msgid "Quotation"
+msgstr "Devis"
+
+msgctxt "model:ir.message,text:msg_erase_party_pending_sale"
+msgid ""
+"You cannot erase party \"%(party)s\" while they have pending sales with "
+"company \"%(company)s\"."
+msgstr ""
+"Vous ne pouvez pas effacer le tiers « %(party)s » tant qu'il a des ventes en"
+" attentes pour la société « %(company)s »."
+
+msgctxt "model:ir.message,text:msg_sale_customer_location_required"
+msgid ""
+"To process sale \"%(sale)s\" you must set a customer location on party "
+"\"%(party)s\"."
+msgstr ""
+"Pour traiter la vente « %(sale)s », vous devez définir un emplacement client"
+" pour le tiers « %(party)s »."
+
+msgctxt "model:ir.message,text:msg_sale_delete_cancel"
+msgid "To delete sale \"%(sale)s\" you must cancel it."
+msgstr "Pour supprimer la vente « %(sale)s », vous devez l'annuler."
+
+msgctxt "model:ir.message,text:msg_sale_invalid_method"
+msgid ""
+"You cannot use together invoice \"%(invoice_method)s\" and shipment "
+"\"%(shipment_method)s\" on sale \"%(sale)s\"."
+msgstr ""
+"Vous ne pouvez pas utiliser conjointement la facturation "
+"« %(invoice_method)s » et l'exédition « %(shipment_method)s » sur la vente "
+"« %(sale)s »."
+
+msgctxt ""
+"model:ir.message,text:msg_sale_invoice_address_required_for_quotation"
+msgid "To get a quote for sale \"%(sale)s\" you must enter an invoice address."
+msgstr ""
+"Pour avoir un devis pour la vente « %(sale)s », vous devez entrer une "
+"adresse de facturation."
+
+msgctxt "model:ir.message,text:msg_sale_invoice_reset_draft"
+msgid ""
+"You cannot reset invoice \"%(invoice)s\" to draft because it was generated "
+"by a sale."
+msgstr ""
+"Vous ne pouvez pas réinitialiser à l'état brouillon la facture "
+"« %(invoice)s » car elle a été générée par une vente."
+
+msgctxt "model:ir.message,text:msg_sale_line_delete_cancel_draft"
+msgid ""
+"To delete line \"%(line)s\" you must cancel or reset to draft sale "
+"\"%(sale)s\"."
+msgstr ""
+"Pour supprimer la ligne « %(line)s », vous devez annuler ou réinitialiser à "
+"l'état brouillon la vente « %(sale)s »."
+
+msgctxt "model:ir.message,text:msg_sale_missing_account_revenue"
+msgid "To invoice sale \"%(sale)s\" you must configure a default account revenue."
+msgstr ""
+"Pour facturer la vente « %(sale)s », vous devez configurer un compte de "
+"produits par défaut."
+
+msgctxt "model:ir.message,text:msg_sale_modify_header_draft"
+msgid "To modify the header of sale \"%(sale)s\", it must be in \"draft\" state."
+msgstr ""
+"Pour modifier l'entête de la vente « %(sale)s », elle doit être dans l'état "
+"« brouillon »."
+
+msgctxt "model:ir.message,text:msg_sale_move_reset_draft"
+msgid ""
+"You cannot reset move \"%(move)s\" to draft because it was generated by a "
+"sale."
+msgstr ""
+"Vous ne pouvez pas réinitialiser à l'état brouillon le mouvement "
+"« %(move)s » car il a été généré par une vente."
+
+msgctxt "model:ir.message,text:msg_sale_product_missing_account_revenue"
+msgid ""
+"To invoice sale \"%(sale)s\" you must define an account revenue for product "
+"\"%(product)s\"."
+msgstr ""
+"Pour facturer la vente « %(sale)s », vous devez définir un compte de "
+"produits pour le produit « %(product)s »."
+
+msgctxt "model:ir.message,text:msg_sale_reporting_company"
+msgid "Company"
+msgstr "Société"
+
+msgctxt "model:ir.message,text:msg_sale_reporting_currency"
+msgid "Currency"
+msgstr "Devise"
+
+msgctxt "model:ir.message,text:msg_sale_reporting_currency_digits"
+msgid "Currency Digits"
+msgstr "Décimales de la devise"
+
+msgctxt "model:ir.message,text:msg_sale_reporting_number"
+msgid "#"
+msgstr "#"
+
+msgctxt "model:ir.message,text:msg_sale_reporting_number_help"
+msgid "Number of sales"
+msgstr "Nombre de ventes"
+
+msgctxt "model:ir.message,text:msg_sale_reporting_revenue"
+msgid "Revenue"
+msgstr "Revenu"
+
+msgctxt "model:ir.message,text:msg_sale_reporting_revenue_trend"
+msgid "Revenue Trend"
+msgstr "Tendance du revenu"
+
+msgctxt ""
+"model:ir.message,text:msg_sale_shipment_address_required_for_quotation"
+msgid "To get a quote for sale \"%(sale)s\" you must enter a shipment address."
+msgstr ""
+"Pour avoir un devis pour la vente « %(sale)s », vous devez entrer une "
+"adresse de livraison."
+
+msgctxt "model:ir.message,text:msg_sale_warehouse_required_for_quotation"
+msgid "To get a quote for sale \"%(sale)s\" you must enter a warehouse."
+msgstr ""
+"Pour avoir un devis pour la vente « %(sale)s », vous devez entrer un "
+"entrepôt."
+
+msgctxt "model:ir.model.button,string:sale_cancel_button"
+msgid "Cancel"
+msgstr "Annuler"
+
+msgctxt "model:ir.model.button,string:sale_confirm_button"
+msgid "Confirm"
+msgstr "Confirmer"
+
+msgctxt "model:ir.model.button,string:sale_draft_button"
+msgid "Draft"
+msgstr "Brouillon"
+
+msgctxt "model:ir.model.button,string:sale_handle_invoice_exception_button"
+msgid "Handle Invoice Exception"
+msgstr "Gérer l'exception de facture"
+
+msgctxt "model:ir.model.button,string:sale_handle_shipment_exception_button"
+msgid "Handle Shipment Exception"
+msgstr "Gérer l'exception d'expédition"
+
+msgctxt "model:ir.model.button,string:sale_modify_header_button"
+msgid "Modify Header"
+msgstr "Modifier l'entête"
+
+msgctxt "model:ir.model.button,string:sale_process_button"
+msgid "Process"
+msgstr "Traiter"
+
+msgctxt "model:ir.model.button,string:sale_quote_button"
+msgid "Quote"
+msgstr "Devis"
+
+msgctxt "model:ir.rule.group,name:rule_group_reporting_category_companies"
+msgid "User in companies"
+msgstr "Utilisateur dans les sociétés"
+
+msgctxt ""
+"model:ir.rule.group,name:rule_group_reporting_category_time_series_companies"
+msgid "User in companies"
+msgstr "Utilisateur dans les sociétés"
+
+msgctxt ""
+"model:ir.rule.group,name:rule_group_reporting_country_subdivision_time_series_companies"
+msgid "User in companies"
+msgstr "Utilisateur dans les sociétés"
+
+msgctxt ""
+"model:ir.rule.group,name:rule_group_reporting_country_time_series_companies"
+msgid "User in companies"
+msgstr "Utilisateur dans les sociétés"
+
+msgctxt "model:ir.rule.group,name:rule_group_reporting_customer_companies"
+msgid "User in companies"
+msgstr "Utilisateur dans les sociétés"
+
+msgctxt ""
+"model:ir.rule.group,name:rule_group_reporting_customer_time_series_companies"
+msgid "User in companies"
+msgstr "Utilisateur dans les sociétés"
+
+msgctxt "model:ir.rule.group,name:rule_group_reporting_product_companies"
+msgid "User in companies"
+msgstr "Utilisateur dans les sociétés"
+
+msgctxt ""
+"model:ir.rule.group,name:rule_group_reporting_product_time_series_companies"
+msgid "User in companies"
+msgstr "Utilisateur dans les sociétés"
+
+msgctxt "model:ir.rule.group,name:rule_group_reporting_region_companies"
+msgid "User in companies"
+msgstr "Utilisateur dans les sociétés"
+
+msgctxt "model:ir.rule.group,name:rule_group_sale_companies"
+msgid "User in companies"
+msgstr "Utilisateur dans les sociétés"
+
+msgctxt "model:ir.sequence,name:sequence_sale"
+msgid "Sale"
+msgstr "Vente"
+
+msgctxt "model:ir.sequence.type,name:sequence_type_sale"
+msgid "Sale"
+msgstr "Vente"
+
+msgctxt "model:ir.ui.menu,name:menu_configuration"
+msgid "Configuration"
+msgstr "Configuration"
+
+msgctxt "model:ir.ui.menu,name:menu_customer"
+msgid "Associated to Sales"
+msgstr "Associés à des ventes"
+
+msgctxt "model:ir.ui.menu,name:menu_product"
+msgid "Products"
+msgstr "Produits"
+
+msgctxt "model:ir.ui.menu,name:menu_reporting"
+msgid "Reporting"
+msgstr "Rapports"
+
+msgctxt "model:ir.ui.menu,name:menu_reporting_sale"
+msgid "Sales"
+msgstr "Ventes"
+
+msgctxt "model:ir.ui.menu,name:menu_sale"
+msgid "Sales"
+msgstr "Ventes"
+
+msgctxt "model:ir.ui.menu,name:menu_sale_configuration"
+msgid "Configuration"
+msgstr "Configuration"
+
+msgctxt "model:ir.ui.menu,name:menu_sale_form"
+msgid "Sales"
+msgstr "Ventes"
+
+msgctxt "model:product.configuration.default_lead_time,name:"
+msgid "Product Default Lead Time"
+msgstr "Délai d'exécution par défaut des produits"
+
+msgctxt "model:product.sale.context,name:"
+msgid "Product Sale Context"
+msgstr "Contexte de produit de vente"
+
+msgctxt "model:res.group,name:group_sale"
+msgid "Sales"
+msgstr "Ventes"
+
+msgctxt "model:res.group,name:group_sale_admin"
+msgid "Sales Administrator"
+msgstr "Administrateur des ventes"
+
+msgctxt "model:sale.configuration,name:"
+msgid "Sale Configuration"
+msgstr "Configuration des ventes"
+
+msgctxt "model:sale.configuration.sale_method,name:"
+msgid "Sale Configuration Sale Method"
+msgstr "Configuration de vente Méthode de vente"
+
+msgctxt "model:sale.configuration.sequence,name:"
+msgid "Sale Configuration Sequence"
+msgstr "Configuration de vente Séquence"
+
+msgctxt "model:sale.handle.invoice.exception.ask,name:"
+msgid "Handle Invoice Exception"
+msgstr "Exception de facture - Demande"
+
+msgctxt "model:sale.handle.shipment.exception.ask,name:"
+msgid "Handle Shipment Exception"
+msgstr "Exception d'expédition - Demande"
+
+msgctxt "model:sale.line,name:"
+msgid "Sale Line"
+msgstr "Ligne de vente"
+
+msgctxt "model:sale.line-account.tax,name:"
+msgid "Sale Line - Tax"
+msgstr "Ligne de vente - Taxe"
+
+msgctxt "model:sale.line-ignored-stock.move,name:"
+msgid "Sale Line - Ignored Move"
+msgstr "Ligne de vente - Mouvement ignoré"
+
+msgctxt "model:sale.line-recreated-stock.move,name:"
+msgid "Sale Line - Recreated Move"
+msgstr "Ligne de vente - Mouvement recréé"
+
+msgctxt "model:sale.reporting.category,name:"
+msgid "Sale Reporting per Category"
+msgstr "Rapports de vente par catégorie"
+
+msgctxt "model:sale.reporting.category.time_series,name:"
+msgid "Sale Reporting per Category"
+msgstr "Rapports de vente par catégorie"
+
+msgctxt "model:sale.reporting.category.tree,name:"
+msgid "Sale Reporting per Category"
+msgstr "Rapports de vente par catégorie"
+
+msgctxt "model:sale.reporting.context,name:"
+msgid "Sale Reporting Context"
+msgstr "Contexte de rapports de vente"
+
+msgctxt "model:sale.reporting.country,name:"
+msgid "Sale Reporting per Country"
+msgstr "Rapports de vente par pays"
+
+msgctxt "model:sale.reporting.country.subdivision,name:"
+msgid "Sale Reporting per Subdivision"
+msgstr "Rapports de vente par subdivision"
+
+msgctxt "model:sale.reporting.country.subdivision.time_series,name:"
+msgid "Sale Reporting per Subdivision"
+msgstr "Rapports de vente par subdivision"
+
+msgctxt "model:sale.reporting.country.time_series,name:"
+msgid "Sale Reporting per Country"
+msgstr "Rapports de vente par pays"
+
+msgctxt "model:sale.reporting.customer,name:"
+msgid "Sale Reporting per Customer"
+msgstr "Rapports de vente par client"
+
+msgctxt "model:sale.reporting.customer.time_series,name:"
+msgid "Sale Reporting per Customer"
+msgstr "Rapports de vente par client"
+
+msgctxt "model:sale.reporting.product,name:"
+msgid "Sale Reporting per Product"
+msgstr "Rapports de vente par produit"
+
+msgctxt "model:sale.reporting.product.time_series,name:"
+msgid "Sale Reporting per Product"
+msgstr "Rapports de vente par produit"
+
+msgctxt "model:sale.reporting.region,name:"
+msgid "Sale Reporting per Region"
+msgstr "Rapports de vente par région"
+
+msgctxt "model:sale.return_sale.start,name:"
+msgid "Return Sale"
+msgstr "Créer le retour de vente"
+
+msgctxt "model:sale.sale,name:"
+msgid "Sale"
+msgstr "Vente"
+
+msgctxt "model:sale.sale-ignored-account.invoice,name:"
+msgid "Sale - Ignored Invoice"
+msgstr "Vente - Facture Ignorée"
+
+msgctxt "model:sale.sale-recreated-account.invoice,name:"
+msgid "Sale - Recreated Invoice"
+msgstr "Vente - Facture recréée"
+
+msgctxt "report:sale.sale:"
+msgid ":"
+msgstr " :"
+
+msgctxt "report:sale.sale:"
+msgid "Amount"
+msgstr "Montant"
+
+msgctxt "report:sale.sale:"
+msgid "Date:"
+msgstr "Date :"
+
+msgctxt "report:sale.sale:"
+msgid "Description"
+msgstr "Description"
+
+msgctxt "report:sale.sale:"
+msgid "Description:"
+msgstr "Description :"
+
+msgctxt "report:sale.sale:"
+msgid "Draft Sale Order"
+msgstr "Bon de commande brouillon"
+
+msgctxt "report:sale.sale:"
+msgid "Quantity"
+msgstr "Quantité"
+
+msgctxt "report:sale.sale:"
+msgid "Quotation N°:"
+msgstr "Devis N° :"
+
+msgctxt "report:sale.sale:"
+msgid "Reference:"
+msgstr "Référence :"
+
+msgctxt "report:sale.sale:"
+msgid "Sale Order N°:"
+msgstr "Bon de commande N° :"
+
+msgctxt "report:sale.sale:"
+msgid "Taxes"
+msgstr "Taxes"
+
+msgctxt "report:sale.sale:"
+msgid "Taxes:"
+msgstr "Taxes :"
+
+msgctxt "report:sale.sale:"
+msgid "Total (excl. taxes):"
+msgstr "Total (hors taxes) :"
+
+msgctxt "report:sale.sale:"
+msgid "Total:"
+msgstr "Total :"
+
+msgctxt "report:sale.sale:"
+msgid "Unit Price"
+msgstr "Prix unitaire"
+
+msgctxt "selection:account.invoice,sale_exception_state:"
+msgid "Ignored"
+msgstr "Ignoré"
+
+msgctxt "selection:account.invoice,sale_exception_state:"
+msgid "Recreated"
+msgstr "Recréé"
+
+msgctxt "selection:sale.line,type:"
+msgid "Comment"
+msgstr "Commentaire"
+
+msgctxt "selection:sale.line,type:"
+msgid "Line"
+msgstr "Ligne"
+
+msgctxt "selection:sale.line,type:"
+msgid "Subtotal"
+msgstr "Sous-total"
+
+msgctxt "selection:sale.line,type:"
+msgid "Title"
+msgstr "Titre"
+
+msgctxt "selection:sale.reporting.context,period:"
+msgid "Day"
+msgstr "Jour"
+
+msgctxt "selection:sale.reporting.context,period:"
+msgid "Month"
+msgstr "Mois"
+
+msgctxt "selection:sale.reporting.context,period:"
+msgid "Year"
+msgstr "Année"
+
+msgctxt "selection:sale.sale,invoice_method:"
+msgid "Manual"
+msgstr "Manuel"
+
+msgctxt "selection:sale.sale,invoice_method:"
+msgid "On Order Processed"
+msgstr "Sur traitement de l'ordre"
+
+msgctxt "selection:sale.sale,invoice_method:"
+msgid "On Shipment Sent"
+msgstr "À l'envoi de l'expédition"
+
+msgctxt "selection:sale.sale,invoice_state:"
+msgid "Exception"
+msgstr "Exception"
+
+msgctxt "selection:sale.sale,invoice_state:"
+msgid "None"
+msgstr "Aucun"
+
+msgctxt "selection:sale.sale,invoice_state:"
+msgid "Paid"
+msgstr "Payé"
+
+msgctxt "selection:sale.sale,invoice_state:"
+msgid "Waiting"
+msgstr "En attente"
+
+msgctxt "selection:sale.sale,shipment_method:"
+msgid "Manual"
+msgstr "Manuel"
+
+msgctxt "selection:sale.sale,shipment_method:"
+msgid "On Invoice Paid"
+msgstr "Au paiement"
+
+msgctxt "selection:sale.sale,shipment_method:"
+msgid "On Order Processed"
+msgstr "Sur traitement de l'ordre"
+
+msgctxt "selection:sale.sale,shipment_state:"
+msgid "Exception"
+msgstr "Exception"
+
+msgctxt "selection:sale.sale,shipment_state:"
+msgid "None"
+msgstr "Aucun"
+
+msgctxt "selection:sale.sale,shipment_state:"
+msgid "Sent"
+msgstr "Envoyé"
+
+msgctxt "selection:sale.sale,shipment_state:"
+msgid "Waiting"
+msgstr "En attente"
+
+msgctxt "selection:sale.sale,state:"
+msgid "Cancelled"
+msgstr "Annulée"
+
+msgctxt "selection:sale.sale,state:"
+msgid "Confirmed"
+msgstr "Confirmé"
+
+msgctxt "selection:sale.sale,state:"
+msgid "Done"
+msgstr "Terminée"
+
+msgctxt "selection:sale.sale,state:"
+msgid "Draft"
+msgstr "Brouillon"
+
+msgctxt "selection:sale.sale,state:"
+msgid "Processing"
+msgstr "En traitement"
+
+msgctxt "selection:sale.sale,state:"
+msgid "Quotation"
+msgstr "Devis"
+
+msgctxt "selection:stock.move,sale_exception_state:"
+msgid "Ignored"
+msgstr "Ignoré"
+
+msgctxt "selection:stock.move,sale_exception_state:"
+msgid "Recreated"
+msgstr "Recréé"
+
+msgctxt "view:party.party:"
+msgid "Sale"
+msgstr "Vente"
+
+msgctxt "view:product.template:"
+msgid "Customers"
+msgstr "Clients"
+
+msgctxt "view:sale.handle.invoice.exception.ask:"
+msgid "Choose invoices to recreate:"
+msgstr "Choisissez les factures à recréer :"
+
+msgctxt "view:sale.handle.shipment.exception.ask:"
+msgid "Choose move to recreate:"
+msgstr "Choisissez les mouvements à recréer :"
+
+msgctxt "view:sale.line:"
+msgid "General"
+msgstr "Général"
+
+msgctxt "view:sale.line:"
+msgid "Notes"
+msgstr "Notes"
+
+msgctxt "view:sale.line:"
+msgid "Taxes"
+msgstr "Taxes"
+
+msgctxt "view:sale.return_sale.start:"
+msgid "Are you sure to return these/this sale(s)?"
+msgstr "Êtes-vous sûr de retourner ces/cette vente(s) ?"
+
+msgctxt "view:sale.sale:"
+msgid "Other Info"
+msgstr "Autre information"
+
+msgctxt "view:sale.sale:"
+msgid "Sale"
+msgstr "Vente"
+
+msgctxt "wizard_button:sale.handle.invoice.exception,ask,end:"
+msgid "Cancel"
+msgstr "Annuler"
+
+msgctxt "wizard_button:sale.handle.invoice.exception,ask,handle:"
+msgid "OK"
+msgstr "OK"
+
+msgctxt "wizard_button:sale.handle.shipment.exception,ask,end:"
+msgid "Cancel"
+msgstr "Annuler"
+
+msgctxt "wizard_button:sale.handle.shipment.exception,ask,handle:"
+msgid "OK"
+msgstr "OK"
+
+msgctxt "wizard_button:sale.modify_header,start,end:"
+msgid "Cancel"
+msgstr "Annuler"
+
+msgctxt "wizard_button:sale.modify_header,start,modify:"
+msgid "Modify"
+msgstr "Modifier"
+
+msgctxt "wizard_button:sale.return_sale,start,end:"
+msgid "Cancel"
+msgstr "Annuler"
+
+msgctxt "wizard_button:sale.return_sale,start,return_:"
+msgid "Return"
+msgstr "Retourner"
diff --git a/modules/sale/locale/hu.po b/modules/sale/locale/hu.po
new file mode 100644
index 0000000000..13b9eaa3d1
--- /dev/null
+++ b/modules/sale/locale/hu.po
@@ -0,0 +1,1354 @@
+#
+msgid ""
+msgstr "Content-Type: text/plain; charset=utf-8\n"
+
+msgctxt "field:account.invoice,sale_exception_state:"
+msgid "Exception State"
+msgstr "Visszautasítás kezelése"
+
+msgctxt "field:account.invoice,sales:"
+msgid "Sales"
+msgstr "Vevői rendelések"
+
+msgctxt "field:product.configuration,default_lead_time:"
+msgid "Default Lead Time"
+msgstr "Alapértelmezett átfutási idő"
+
+msgctxt "field:product.configuration.default_lead_time,company:"
+msgid "Company"
+msgstr "Cég"
+
+msgctxt "field:product.configuration.default_lead_time,default_lead_time:"
+msgid "Default Lead Time"
+msgstr "Alapértelmezett átfutási idő"
+
+msgctxt "field:product.product,lead_time:"
+msgid "Lead Time"
+msgstr "Átfutási idő"
+
+msgctxt "field:product.product,salable:"
+msgid "Salable"
+msgstr "Eladható"
+
+msgctxt "field:product.product,sale_price_uom:"
+msgid "Sale Price"
+msgstr "Listaár"
+
+msgctxt "field:product.product,sale_uom:"
+msgid "Sale UOM"
+msgstr "Értékesítési ME"
+
+msgctxt "field:product.sale.context,company:"
+msgid "Company"
+msgstr "Cég"
+
+msgctxt "field:product.sale.context,currency:"
+msgid "Currency"
+msgstr "Pénznem"
+
+msgctxt "field:product.sale.context,customer:"
+msgid "Customer"
+msgstr "Vevő"
+
+msgctxt "field:product.sale.context,locations:"
+msgid "Warehouses"
+msgstr "Raktárak"
+
+msgctxt "field:product.sale.context,quantity:"
+msgid "Quantity"
+msgstr "Mennyiség"
+
+msgctxt "field:product.sale.context,sale_date:"
+msgid "Sale Date"
+msgstr "Rendelés dátuma"
+
+msgctxt "field:product.sale.context,stock_date_end:"
+msgid "Stock End Date"
+msgstr ""
+
+msgctxt "field:product.template,lead_time:"
+msgid "Lead Time"
+msgstr "Átfutási idő"
+
+msgctxt "field:product.template,salable:"
+msgid "Salable"
+msgstr "Eladható"
+
+msgctxt "field:product.template,sale_uom:"
+msgid "Sale UOM"
+msgstr "Értékesítési ME"
+
+msgctxt "field:sale.configuration,sale_invoice_method:"
+msgid "Sale Invoice Method"
+msgstr "Vevői rendelések számlázási módja"
+
+msgctxt "field:sale.configuration,sale_process_after:"
+msgid "Process Sale after"
+msgstr ""
+
+msgctxt "field:sale.configuration,sale_sequence:"
+msgid "Sale Sequence"
+msgstr "Vevői rendelések sorszámozása"
+
+msgctxt "field:sale.configuration,sale_shipment_method:"
+msgid "Sale Shipment Method"
+msgstr "Vevői rendelések szállítási módja"
+
+msgctxt "field:sale.configuration.sale_method,sale_invoice_method:"
+msgid "Sale Invoice Method"
+msgstr "Vevői rendelések számlázási módja"
+
+msgctxt "field:sale.configuration.sale_method,sale_shipment_method:"
+msgid "Sale Shipment Method"
+msgstr "Vevői rendelések szállítási módja"
+
+msgctxt "field:sale.configuration.sequence,company:"
+msgid "Company"
+msgstr "Cég"
+
+msgctxt "field:sale.configuration.sequence,sale_sequence:"
+msgid "Sale Sequence"
+msgstr "Vevői rendelések sorszámozása"
+
+msgctxt "field:sale.handle.invoice.exception.ask,domain_invoices:"
+msgid "Domain Invoices"
+msgstr ""
+
+msgctxt "field:sale.handle.invoice.exception.ask,recreate_invoices:"
+msgid "Recreate Invoices"
+msgstr ""
+
+msgctxt "field:sale.handle.shipment.exception.ask,domain_moves:"
+msgid "Domain Moves"
+msgstr ""
+
+msgctxt "field:sale.handle.shipment.exception.ask,recreate_moves:"
+msgid "Recreate Moves"
+msgstr ""
+
+#, fuzzy
+msgctxt "field:sale.line,actual_quantity:"
+msgid "Actual Quantity"
+msgstr "Mennyiség"
+
+msgctxt "field:sale.line,amount:"
+msgid "Amount"
+msgstr "Részösszeg"
+
+msgctxt "field:sale.line,company:"
+msgid "Company"
+msgstr "Cég"
+
+msgctxt "field:sale.line,currency:"
+msgid "Currency"
+msgstr "Pénznem"
+
+msgctxt "field:sale.line,description:"
+msgid "Description"
+msgstr "Leírás"
+
+msgctxt "field:sale.line,from_location:"
+msgid "From Location"
+msgstr "Induló tárhely"
+
+msgctxt "field:sale.line,invoice_lines:"
+msgid "Invoice Lines"
+msgstr "Számlasorok"
+
+msgctxt "field:sale.line,move_done:"
+msgid "Moves Done"
+msgstr ""
+
+msgctxt "field:sale.line,move_exception:"
+msgid "Moves Exception"
+msgstr ""
+
+msgctxt "field:sale.line,moves:"
+msgid "Moves"
+msgstr "Mozgások"
+
+msgctxt "field:sale.line,moves_ignored:"
+msgid "Ignored Moves"
+msgstr ""
+
+msgctxt "field:sale.line,moves_recreated:"
+msgid "Recreated Moves"
+msgstr ""
+
+msgctxt "field:sale.line,note:"
+msgid "Note"
+msgstr "Jegyzetek"
+
+msgctxt "field:sale.line,product:"
+msgid "Product"
+msgstr "Termék"
+
+msgctxt "field:sale.line,product_uom_category:"
+msgid "Product Uom Category"
+msgstr "Mértékegység kategória"
+
+msgctxt "field:sale.line,quantity:"
+msgid "Quantity"
+msgstr "Mennyiség"
+
+msgctxt "field:sale.line,sale:"
+msgid "Sale"
+msgstr "Vevői rendelés"
+
+msgctxt "field:sale.line,sale_state:"
+msgid "Sale State"
+msgstr ""
+
+msgctxt "field:sale.line,shipping_date:"
+msgid "Shipping Date"
+msgstr "Kiszállítás dátuma"
+
+msgctxt "field:sale.line,summary:"
+msgid "Summary"
+msgstr "Leírás"
+
+msgctxt "field:sale.line,taxes:"
+msgid "Taxes"
+msgstr "Adók"
+
+msgctxt "field:sale.line,to_location:"
+msgid "To Location"
+msgstr "Cél tárhely"
+
+msgctxt "field:sale.line,type:"
+msgid "Type"
+msgstr "Típus"
+
+msgctxt "field:sale.line,unit:"
+msgid "Unit"
+msgstr "Mértékegység"
+
+msgctxt "field:sale.line,unit_digits:"
+msgid "Unit Digits"
+msgstr "Tizedes vessző utáni számjegy"
+
+msgctxt "field:sale.line,unit_price:"
+msgid "Unit Price"
+msgstr "Egységár"
+
+msgctxt "field:sale.line,warehouse:"
+msgid "Warehouse"
+msgstr "Raktár"
+
+msgctxt "field:sale.line-account.tax,line:"
+msgid "Sale Line"
+msgstr "Vevői rendelés sora"
+
+msgctxt "field:sale.line-account.tax,tax:"
+msgid "Tax"
+msgstr "Adó"
+
+msgctxt "field:sale.line-ignored-stock.move,move:"
+msgid "Move"
+msgstr "Tétel"
+
+msgctxt "field:sale.line-ignored-stock.move,sale_line:"
+msgid "Sale Line"
+msgstr "Vevői rendelés sora"
+
+msgctxt "field:sale.line-recreated-stock.move,move:"
+msgid "Move"
+msgstr "Tétel"
+
+msgctxt "field:sale.line-recreated-stock.move,sale_line:"
+msgid "Sale Line"
+msgstr "Vevői rendelés sora"
+
+msgctxt "field:sale.reporting.category,category:"
+msgid "Category"
+msgstr "Kategória"
+
+msgctxt "field:sale.reporting.category,time_series:"
+msgid "Time Series"
+msgstr ""
+
+msgctxt "field:sale.reporting.category.time_series,category:"
+msgid "Category"
+msgstr "Kategória"
+
+msgctxt "field:sale.reporting.category.time_series,date:"
+msgid "Date"
+msgstr "Dátum"
+
+msgctxt "field:sale.reporting.category.tree,children:"
+msgid "Children"
+msgstr "Alárendelt rekordok"
+
+msgctxt "field:sale.reporting.category.tree,currency_digits:"
+msgid "Currency Digits"
+msgstr ""
+
+msgctxt "field:sale.reporting.category.tree,name:"
+msgid "Name"
+msgstr "Név"
+
+msgctxt "field:sale.reporting.category.tree,parent:"
+msgid "Parent"
+msgstr "Fölérendelt"
+
+msgctxt "field:sale.reporting.category.tree,revenue:"
+msgid "Revenue"
+msgstr "Árbevétel"
+
+msgctxt "field:sale.reporting.context,company:"
+msgid "Company"
+msgstr "Cég"
+
+msgctxt "field:sale.reporting.context,from_date:"
+msgid "From Date"
+msgstr "Ettől"
+
+msgctxt "field:sale.reporting.context,period:"
+msgid "Period"
+msgstr "Periódus"
+
+msgctxt "field:sale.reporting.context,to_date:"
+msgid "To Date"
+msgstr "Eddig"
+
+msgctxt "field:sale.reporting.context,warehouse:"
+msgid "Warehouse"
+msgstr "Raktár"
+
+msgctxt "field:sale.reporting.country,country:"
+msgid "Country"
+msgstr "Ország"
+
+msgctxt "field:sale.reporting.country,time_series:"
+msgid "Time Series"
+msgstr ""
+
+msgctxt "field:sale.reporting.country.subdivision,country:"
+msgid "Country"
+msgstr "Ország"
+
+msgctxt "field:sale.reporting.country.subdivision,subdivision:"
+msgid "Subdivision"
+msgstr "Közigazgatási egység"
+
+msgctxt "field:sale.reporting.country.subdivision,time_series:"
+msgid "Time Series"
+msgstr ""
+
+msgctxt "field:sale.reporting.country.subdivision.time_series,country:"
+msgid "Country"
+msgstr "Ország"
+
+msgctxt "field:sale.reporting.country.subdivision.time_series,date:"
+msgid "Date"
+msgstr "Dátum"
+
+msgctxt "field:sale.reporting.country.subdivision.time_series,subdivision:"
+msgid "Subdivision"
+msgstr "Közigazgatási egység"
+
+msgctxt "field:sale.reporting.country.time_series,country:"
+msgid "Country"
+msgstr "Ország"
+
+msgctxt "field:sale.reporting.country.time_series,date:"
+msgid "Date"
+msgstr "Dátum"
+
+msgctxt "field:sale.reporting.customer,customer:"
+msgid "Customer"
+msgstr "Vevő"
+
+msgctxt "field:sale.reporting.customer,time_series:"
+msgid "Time Series"
+msgstr ""
+
+msgctxt "field:sale.reporting.customer.time_series,customer:"
+msgid "Customer"
+msgstr "Vevő"
+
+msgctxt "field:sale.reporting.customer.time_series,date:"
+msgid "Date"
+msgstr "Dátum"
+
+msgctxt "field:sale.reporting.product,product:"
+msgid "Product"
+msgstr "Termék"
+
+msgctxt "field:sale.reporting.product,time_series:"
+msgid "Time Series"
+msgstr ""
+
+msgctxt "field:sale.reporting.product.time_series,date:"
+msgid "Date"
+msgstr "Dátum"
+
+msgctxt "field:sale.reporting.product.time_series,product:"
+msgid "Product"
+msgstr "Termék"
+
+msgctxt "field:sale.reporting.region,children:"
+msgid "Children"
+msgstr "Alárendelt rekordok"
+
+msgctxt "field:sale.reporting.region,parent:"
+msgid "Parent"
+msgstr "Fölérendelt"
+
+msgctxt "field:sale.reporting.region,region:"
+msgid "Region"
+msgstr "Régió"
+
+msgctxt "field:sale.sale,comment:"
+msgid "Comment"
+msgstr "Megjegyzés"
+
+msgctxt "field:sale.sale,company:"
+msgid "Company"
+msgstr "Cég"
+
+msgctxt "field:sale.sale,confirmed_by:"
+msgid "Confirmed By"
+msgstr "Jóváhagyta"
+
+msgctxt "field:sale.sale,contact:"
+msgid "Contact"
+msgstr "Kapcsolattartó"
+
+msgctxt "field:sale.sale,currency:"
+msgid "Currency"
+msgstr "Pénznem"
+
+msgctxt "field:sale.sale,currency_digits:"
+msgid "Currency Digits"
+msgstr ""
+
+msgctxt "field:sale.sale,description:"
+msgid "Description"
+msgstr "Leírás"
+
+msgctxt "field:sale.sale,invoice_address:"
+msgid "Invoice Address"
+msgstr "Számlázási cím"
+
+msgctxt "field:sale.sale,invoice_method:"
+msgid "Invoice Method"
+msgstr "Számlázás módja"
+
+msgctxt "field:sale.sale,invoice_party:"
+msgid "Invoice Party"
+msgstr "Vevő a számlán"
+
+msgctxt "field:sale.sale,invoice_state:"
+msgid "Invoice State"
+msgstr "Számlázás állapota"
+
+msgctxt "field:sale.sale,invoices:"
+msgid "Invoices"
+msgstr "Számlák"
+
+msgctxt "field:sale.sale,invoices_ignored:"
+msgid "Ignored Invoices"
+msgstr ""
+
+msgctxt "field:sale.sale,invoices_recreated:"
+msgid "Recreated Invoices"
+msgstr ""
+
+msgctxt "field:sale.sale,lines:"
+msgid "Lines"
+msgstr "Sorok"
+
+msgctxt "field:sale.sale,moves:"
+msgid "Moves"
+msgstr "Mozgások"
+
+msgctxt "field:sale.sale,number:"
+msgid "Number"
+msgstr "Szám"
+
+msgctxt "field:sale.sale,origin:"
+msgid "Origin"
+msgstr "Eredet"
+
+msgctxt "field:sale.sale,party:"
+msgid "Party"
+msgstr "Ügyfél"
+
+msgctxt "field:sale.sale,party_lang:"
+msgid "Party Language"
+msgstr "Ügyfél nyelve"
+
+msgctxt "field:sale.sale,payment_term:"
+msgid "Payment Term"
+msgstr "Fizetési feltétel"
+
+msgctxt "field:sale.sale,quoted_by:"
+msgid "Quoted By"
+msgstr "Ajánlatot létrehozta"
+
+msgctxt "field:sale.sale,reference:"
+msgid "Reference"
+msgstr "Hivatkozás"
+
+msgctxt "field:sale.sale,sale_date:"
+msgid "Sale Date"
+msgstr "Rendelés dátuma"
+
+msgctxt "field:sale.sale,shipment_address:"
+msgid "Shipment Address"
+msgstr "Szállítási cím"
+
+msgctxt "field:sale.sale,shipment_method:"
+msgid "Shipment Method"
+msgstr "Kiszállítás módja"
+
+msgctxt "field:sale.sale,shipment_party:"
+msgid "Shipment Party"
+msgstr "Vevő a szállítólevélen"
+
+msgctxt "field:sale.sale,shipment_returns:"
+msgid "Shipment Returns"
+msgstr ""
+
+msgctxt "field:sale.sale,shipment_state:"
+msgid "Shipment State"
+msgstr "Szállítmányok állapota"
+
+msgctxt "field:sale.sale,shipments:"
+msgid "Shipments"
+msgstr "Szállítmányok"
+
+msgctxt "field:sale.sale,shipping_date:"
+msgid "Shipping Date"
+msgstr "Kiszállítás dátuma"
+
+msgctxt "field:sale.sale,state:"
+msgid "State"
+msgstr "Állapot"
+
+msgctxt "field:sale.sale,tax_amount:"
+msgid "Tax"
+msgstr "Adó"
+
+msgctxt "field:sale.sale,tax_amount_cache:"
+msgid "Tax Cache"
+msgstr ""
+
+msgctxt "field:sale.sale,total_amount:"
+msgid "Total"
+msgstr "Összesen"
+
+#, fuzzy
+msgctxt "field:sale.sale,total_amount_cache:"
+msgid "Total Cache"
+msgstr "Összesen"
+
+msgctxt "field:sale.sale,untaxed_amount:"
+msgid "Untaxed"
+msgstr "Nettó"
+
+msgctxt "field:sale.sale,untaxed_amount_cache:"
+msgid "Untaxed Cache"
+msgstr ""
+
+msgctxt "field:sale.sale,warehouse:"
+msgid "Warehouse"
+msgstr "Raktár"
+
+msgctxt "field:sale.sale-ignored-account.invoice,invoice:"
+msgid "Invoice"
+msgstr "Számla"
+
+msgctxt "field:sale.sale-ignored-account.invoice,sale:"
+msgid "Sale"
+msgstr "Vevői rendelés"
+
+msgctxt "field:sale.sale-recreated-account.invoice,invoice:"
+msgid "Invoice"
+msgstr "Számla"
+
+msgctxt "field:sale.sale-recreated-account.invoice,sale:"
+msgid "Sale"
+msgstr "Vevői rendelés"
+
+msgctxt "field:stock.move,sale:"
+msgid "Sale"
+msgstr "Vevői rendelés"
+
+msgctxt "field:stock.move,sale_exception_state:"
+msgid "Exception State"
+msgstr "Visszautasítás kezelése"
+
+msgctxt "help:product.configuration,default_lead_time:"
+msgid ""
+"The time from confirming the sales order to sending the products.\n"
+"Used for products without a lead time."
+msgstr ""
+"Az átfutási idő a vevői rendelés jóváhagyásától az áru kiszállításáig.\n"
+"Azoknál a termékeknél használja a rendszer, amiknél nincs egyéni átfutási idő megadva."
+
+msgctxt "help:product.product,lead_time:"
+msgid ""
+"The time from confirming the sales order to sending the products.\n"
+"If empty the default lead time from the configuration is used."
+msgstr ""
+"Az átfutási idő a vevői rendelés jóváhagyásától az áru kiszállításáig.\n"
+"Ha üres, a termékbeállításoknál megadott átfutási időt használja a rendszer."
+
+msgctxt "help:product.template,lead_time:"
+msgid ""
+"The time from confirming the sales order to sending the products.\n"
+"If empty the default lead time from the configuration is used."
+msgstr ""
+"Az átfutási idő a vevői rendelés jóváhagyásától az áru kiszállításáig.\n"
+"Ha üres, a termékbeállításoknál megadott átfutási időt használja a rendszer."
+
+msgctxt "help:sale.configuration,sale_process_after:"
+msgid ""
+"The grace period during which confirmed sale can still be reset to draft.\n"
+"Applied if a worker queue is activated."
+msgstr ""
+
+msgctxt "help:sale.handle.invoice.exception.ask,recreate_invoices:"
+msgid ""
+"The selected invoices will be recreated. The other ones will be ignored."
+msgstr ""
+"A kiválasztott számlákat újra létrehozza a rendszer. A többi figyelmen kívül"
+" hagyja."
+
+msgctxt "help:sale.sale,shipping_date:"
+msgid "When the shipping of goods should start."
+msgstr "Mikor kezdődjön az áru kiszállítása."
+
+msgctxt "model:ir.action,name:act_invoice_form"
+msgid "Invoices"
+msgstr "Számlák"
+
+msgctxt "model:ir.action,name:act_open_customer"
+msgid "Parties associated to Sales"
+msgstr "Vevők vevői rendeléssel"
+
+msgctxt "model:ir.action,name:act_product"
+msgid "Products"
+msgstr "Termékek"
+
+msgctxt "model:ir.action,name:act_reporting_category"
+msgid "Sales per Category"
+msgstr "Eladások termék kategóriánként"
+
+msgctxt "model:ir.action,name:act_reporting_category_time_series"
+msgid "Sales per Category"
+msgstr "Eladások termék kategóriánként"
+
+msgctxt "model:ir.action,name:act_reporting_category_tree"
+msgid "Sales per Category"
+msgstr "Eladások termék kategóriánként"
+
+msgctxt "model:ir.action,name:act_reporting_country_subdivision_time_series"
+msgid "Sales per Subdivision"
+msgstr "Sales per Subdivision"
+
+msgctxt "model:ir.action,name:act_reporting_country_time_series"
+msgid "Sales per Country"
+msgstr "Sales per Country"
+
+msgctxt "model:ir.action,name:act_reporting_customer"
+msgid "Sales per Customer"
+msgstr "Eladások vevőnként"
+
+msgctxt "model:ir.action,name:act_reporting_customer_time_series"
+msgid "Sales per Customer"
+msgstr "Eladások vevőnként"
+
+msgctxt "model:ir.action,name:act_reporting_product"
+msgid "Sales per Product"
+msgstr "Eladások termékenként"
+
+msgctxt "model:ir.action,name:act_reporting_product_time_series"
+msgid "Sales per Product"
+msgstr "Eladások termékenként"
+
+msgctxt "model:ir.action,name:act_reporting_region"
+msgid "Sales per Region"
+msgstr "Eladások régiónként"
+
+msgctxt "model:ir.action,name:act_return_form"
+msgid "Returns"
+msgstr "Visszaküldött áru"
+
+msgctxt "model:ir.action,name:act_sale_configuration_form"
+msgid "Configuration"
+msgstr "Beállítások"
+
+msgctxt "model:ir.action,name:act_sale_form"
+msgid "Sales"
+msgstr "Vevői rendelések"
+
+msgctxt "model:ir.action,name:act_sale_form2"
+msgid "Sales"
+msgstr "Vevői rendelések"
+
+msgctxt "model:ir.action,name:act_sale_invoice_relate"
+msgid "Sales"
+msgstr "Vevői rendelések"
+
+msgctxt "model:ir.action,name:act_sale_move_relate"
+msgid "Moves"
+msgstr "Készletmozgások"
+
+msgctxt "model:ir.action,name:act_sale_shipment_returns_relate"
+msgid "Sales"
+msgstr "Vevői rendelések"
+
+msgctxt "model:ir.action,name:act_sale_shipments_relate"
+msgid "Sales"
+msgstr "Vevői rendelések"
+
+msgctxt "model:ir.action,name:act_shipment_form"
+msgid "Shipments"
+msgstr "Szállítmányok"
+
+msgctxt "model:ir.action,name:report_sale"
+msgid "Sale"
+msgstr "Vevői rendelés"
+
+msgctxt "model:ir.action,name:wizard_invoice_handle_exception"
+msgid "Handle Invoice Exception"
+msgstr "Visszautasított számla kezelése"
+
+msgctxt "model:ir.action,name:wizard_modify_header"
+msgid "Modify Header"
+msgstr "Fejléc módosítása"
+
+msgctxt "model:ir.action,name:wizard_reporting_region_open"
+msgid "Open Region"
+msgstr "Open Region"
+
+msgctxt "model:ir.action,name:wizard_return_sale"
+msgid "Return Sale"
+msgstr "Vevői rendelés visszavételezése"
+
+msgctxt "model:ir.action,name:wizard_shipment_handle_exception"
+msgid "Handle Shipment Exception"
+msgstr "Visszautasított szállítmány kezelése"
+
+msgctxt "model:ir.action.act_window.domain,name:act_sale_form_domain_all"
+msgid "All"
+msgstr "összes"
+
+msgctxt ""
+"model:ir.action.act_window.domain,name:act_sale_form_domain_confirmed"
+msgid "Confirmed"
+msgstr "jóváhagyott"
+
+msgctxt "model:ir.action.act_window.domain,name:act_sale_form_domain_draft"
+msgid "Draft"
+msgstr "vázlat"
+
+msgctxt ""
+"model:ir.action.act_window.domain,name:act_sale_form_domain_exception"
+msgid "Exception"
+msgstr "visszautasítva"
+
+msgctxt ""
+"model:ir.action.act_window.domain,name:act_sale_form_domain_processing"
+msgid "Processing"
+msgstr "folyamatban"
+
+msgctxt ""
+"model:ir.action.act_window.domain,name:act_sale_form_domain_quotation"
+msgid "Quotation"
+msgstr "ajánlat"
+
+msgctxt "model:ir.message,text:msg_erase_party_pending_sale"
+msgid ""
+"You cannot erase party \"%(party)s\" while they have pending sales with "
+"company \"%(company)s\"."
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_sale_customer_location_required"
+msgid ""
+"To process sale \"%(sale)s\" you must set a customer location on party "
+"\"%(party)s\"."
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_sale_delete_cancel"
+msgid "To delete sale \"%(sale)s\" you must cancel it."
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_sale_invalid_method"
+msgid ""
+"You cannot use together invoice \"%(invoice_method)s\" and shipment "
+"\"%(shipment_method)s\" on sale \"%(sale)s\"."
+msgstr ""
+
+msgctxt ""
+"model:ir.message,text:msg_sale_invoice_address_required_for_quotation"
+msgid "To get a quote for sale \"%(sale)s\" you must enter an invoice address."
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_sale_invoice_reset_draft"
+msgid ""
+"You cannot reset invoice \"%(invoice)s\" to draft because it was generated "
+"by a sale."
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_sale_line_delete_cancel_draft"
+msgid ""
+"To delete line \"%(line)s\" you must cancel or reset to draft sale "
+"\"%(sale)s\"."
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_sale_missing_account_revenue"
+msgid "To invoice sale \"%(sale)s\" you must configure a default account revenue."
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_sale_modify_header_draft"
+msgid "To modify the header of sale \"%(sale)s\", it must be in \"draft\" state."
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_sale_move_reset_draft"
+msgid ""
+"You cannot reset move \"%(move)s\" to draft because it was generated by a "
+"sale."
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_sale_product_missing_account_revenue"
+msgid ""
+"To invoice sale \"%(sale)s\" you must define an account revenue for product "
+"\"%(product)s\"."
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_sale_reporting_company"
+msgid "Company"
+msgstr "Cég"
+
+msgctxt "model:ir.message,text:msg_sale_reporting_currency"
+msgid "Currency"
+msgstr "Pénznem"
+
+#, fuzzy
+msgctxt "model:ir.message,text:msg_sale_reporting_currency_digits"
+msgid "Currency Digits"
+msgstr "Pénznem"
+
+msgctxt "model:ir.message,text:msg_sale_reporting_number"
+msgid "#"
+msgstr "#"
+
+msgctxt "model:ir.message,text:msg_sale_reporting_number_help"
+msgid "Number of sales"
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_sale_reporting_revenue"
+msgid "Revenue"
+msgstr "Árbevétel"
+
+msgctxt "model:ir.message,text:msg_sale_reporting_revenue_trend"
+msgid "Revenue Trend"
+msgstr "Eladások tendenciája"
+
+msgctxt ""
+"model:ir.message,text:msg_sale_shipment_address_required_for_quotation"
+msgid "To get a quote for sale \"%(sale)s\" you must enter a shipment address."
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_sale_warehouse_required_for_quotation"
+msgid "To get a quote for sale \"%(sale)s\" you must enter a warehouse."
+msgstr ""
+
+msgctxt "model:ir.model.button,string:sale_cancel_button"
+msgid "Cancel"
+msgstr "Érvénytelenítés"
+
+msgctxt "model:ir.model.button,string:sale_confirm_button"
+msgid "Confirm"
+msgstr "Jóváhagyás"
+
+msgctxt "model:ir.model.button,string:sale_draft_button"
+msgid "Draft"
+msgstr "vázlat"
+
+msgctxt "model:ir.model.button,string:sale_handle_invoice_exception_button"
+msgid "Handle Invoice Exception"
+msgstr "Visszautasított számla kezelése"
+
+msgctxt "model:ir.model.button,string:sale_handle_shipment_exception_button"
+msgid "Handle Shipment Exception"
+msgstr "Visszautasított szállítmány kezelése"
+
+msgctxt "model:ir.model.button,string:sale_modify_header_button"
+msgid "Modify Header"
+msgstr "Fejléc módosítása"
+
+msgctxt "model:ir.model.button,string:sale_process_button"
+msgid "Process"
+msgstr "Feldolgozás"
+
+msgctxt "model:ir.model.button,string:sale_quote_button"
+msgid "Quote"
+msgstr "Ajánlatba"
+
+msgctxt "model:ir.rule.group,name:rule_group_reporting_category_companies"
+msgid "User in companies"
+msgstr ""
+
+msgctxt ""
+"model:ir.rule.group,name:rule_group_reporting_category_time_series_companies"
+msgid "User in companies"
+msgstr ""
+
+msgctxt ""
+"model:ir.rule.group,name:rule_group_reporting_country_subdivision_time_series_companies"
+msgid "User in companies"
+msgstr ""
+
+msgctxt ""
+"model:ir.rule.group,name:rule_group_reporting_country_time_series_companies"
+msgid "User in companies"
+msgstr ""
+
+msgctxt "model:ir.rule.group,name:rule_group_reporting_customer_companies"
+msgid "User in companies"
+msgstr ""
+
+msgctxt ""
+"model:ir.rule.group,name:rule_group_reporting_customer_time_series_companies"
+msgid "User in companies"
+msgstr ""
+
+msgctxt "model:ir.rule.group,name:rule_group_reporting_product_companies"
+msgid "User in companies"
+msgstr ""
+
+msgctxt ""
+"model:ir.rule.group,name:rule_group_reporting_product_time_series_companies"
+msgid "User in companies"
+msgstr ""
+
+msgctxt "model:ir.rule.group,name:rule_group_reporting_region_companies"
+msgid "User in companies"
+msgstr ""
+
+msgctxt "model:ir.rule.group,name:rule_group_sale_companies"
+msgid "User in companies"
+msgstr ""
+
+msgctxt "model:ir.sequence,name:sequence_sale"
+msgid "Sale"
+msgstr "Vevői rendelés"
+
+msgctxt "model:ir.sequence.type,name:sequence_type_sale"
+msgid "Sale"
+msgstr "Vevői rendelés"
+
+msgctxt "model:ir.ui.menu,name:menu_configuration"
+msgid "Configuration"
+msgstr "Beállítások"
+
+msgctxt "model:ir.ui.menu,name:menu_customer"
+msgid "Associated to Sales"
+msgstr "Vevői rendeléssel"
+
+msgctxt "model:ir.ui.menu,name:menu_product"
+msgid "Products"
+msgstr "Termékek"
+
+msgctxt "model:ir.ui.menu,name:menu_reporting"
+msgid "Reporting"
+msgstr "Jelentések"
+
+msgctxt "model:ir.ui.menu,name:menu_reporting_sale"
+msgid "Sales"
+msgstr "Vevői rendelések"
+
+msgctxt "model:ir.ui.menu,name:menu_sale"
+msgid "Sales"
+msgstr "Értékesítés"
+
+msgctxt "model:ir.ui.menu,name:menu_sale_configuration"
+msgid "Configuration"
+msgstr "Beállítások"
+
+msgctxt "model:ir.ui.menu,name:menu_sale_form"
+msgid "Sales"
+msgstr "Vevői rendelések"
+
+msgctxt "model:product.configuration.default_lead_time,name:"
+msgid "Product Default Lead Time"
+msgstr ""
+
+msgctxt "model:product.sale.context,name:"
+msgid "Product Sale Context"
+msgstr ""
+
+msgctxt "model:res.group,name:group_sale"
+msgid "Sales"
+msgstr "Vevői rendelések"
+
+msgctxt "model:res.group,name:group_sale_admin"
+msgid "Sales Administrator"
+msgstr "Sales Administrator"
+
+#, fuzzy
+msgctxt "model:sale.configuration,name:"
+msgid "Sale Configuration"
+msgstr "Sales Configuration"
+
+msgctxt "model:sale.configuration.sale_method,name:"
+msgid "Sale Configuration Sale Method"
+msgstr ""
+
+msgctxt "model:sale.configuration.sequence,name:"
+msgid "Sale Configuration Sequence"
+msgstr ""
+
+msgctxt "model:sale.handle.invoice.exception.ask,name:"
+msgid "Handle Invoice Exception"
+msgstr "Visszautasított számla kezelése"
+
+msgctxt "model:sale.handle.shipment.exception.ask,name:"
+msgid "Handle Shipment Exception"
+msgstr "Visszautasított szállítmány kezelése"
+
+msgctxt "model:sale.line,name:"
+msgid "Sale Line"
+msgstr "Vevői rendelés sora"
+
+msgctxt "model:sale.line-account.tax,name:"
+msgid "Sale Line - Tax"
+msgstr ""
+
+msgctxt "model:sale.line-ignored-stock.move,name:"
+msgid "Sale Line - Ignored Move"
+msgstr ""
+
+msgctxt "model:sale.line-recreated-stock.move,name:"
+msgid "Sale Line - Recreated Move"
+msgstr ""
+
+msgctxt "model:sale.reporting.category,name:"
+msgid "Sale Reporting per Category"
+msgstr ""
+
+msgctxt "model:sale.reporting.category.time_series,name:"
+msgid "Sale Reporting per Category"
+msgstr ""
+
+msgctxt "model:sale.reporting.category.tree,name:"
+msgid "Sale Reporting per Category"
+msgstr ""
+
+msgctxt "model:sale.reporting.context,name:"
+msgid "Sale Reporting Context"
+msgstr ""
+
+msgctxt "model:sale.reporting.country,name:"
+msgid "Sale Reporting per Country"
+msgstr ""
+
+msgctxt "model:sale.reporting.country.subdivision,name:"
+msgid "Sale Reporting per Subdivision"
+msgstr ""
+
+msgctxt "model:sale.reporting.country.subdivision.time_series,name:"
+msgid "Sale Reporting per Subdivision"
+msgstr ""
+
+msgctxt "model:sale.reporting.country.time_series,name:"
+msgid "Sale Reporting per Country"
+msgstr ""
+
+msgctxt "model:sale.reporting.customer,name:"
+msgid "Sale Reporting per Customer"
+msgstr ""
+
+msgctxt "model:sale.reporting.customer.time_series,name:"
+msgid "Sale Reporting per Customer"
+msgstr ""
+
+msgctxt "model:sale.reporting.product,name:"
+msgid "Sale Reporting per Product"
+msgstr ""
+
+msgctxt "model:sale.reporting.product.time_series,name:"
+msgid "Sale Reporting per Product"
+msgstr ""
+
+msgctxt "model:sale.reporting.region,name:"
+msgid "Sale Reporting per Region"
+msgstr ""
+
+msgctxt "model:sale.return_sale.start,name:"
+msgid "Return Sale"
+msgstr "Vevői rendelés visszavételezése"
+
+msgctxt "model:sale.sale,name:"
+msgid "Sale"
+msgstr "Vevői rendelés"
+
+msgctxt "model:sale.sale-ignored-account.invoice,name:"
+msgid "Sale - Ignored Invoice"
+msgstr ""
+
+msgctxt "model:sale.sale-recreated-account.invoice,name:"
+msgid "Sale - Recreated Invoice"
+msgstr ""
+
+msgctxt "report:sale.sale:"
+msgid ":"
+msgstr ":"
+
+msgctxt "report:sale.sale:"
+msgid "Amount"
+msgstr "Összeg"
+
+msgctxt "report:sale.sale:"
+msgid "Date:"
+msgstr "Dátum:"
+
+msgctxt "report:sale.sale:"
+msgid "Description"
+msgstr "Leírás"
+
+#, fuzzy
+msgctxt "report:sale.sale:"
+msgid "Description:"
+msgstr "Leírás"
+
+msgctxt "report:sale.sale:"
+msgid "Draft Sale Order"
+msgstr ""
+
+msgctxt "report:sale.sale:"
+msgid "Quantity"
+msgstr "Mennyiség"
+
+msgctxt "report:sale.sale:"
+msgid "Quotation N°:"
+msgstr ""
+
+msgctxt "report:sale.sale:"
+msgid "Reference:"
+msgstr "Hivatkozás:"
+
+msgctxt "report:sale.sale:"
+msgid "Sale Order N°:"
+msgstr ""
+
+msgctxt "report:sale.sale:"
+msgid "Taxes"
+msgstr "Adók"
+
+msgctxt "report:sale.sale:"
+msgid "Taxes:"
+msgstr "Adók:"
+
+msgctxt "report:sale.sale:"
+msgid "Total (excl. taxes):"
+msgstr ""
+
+msgctxt "report:sale.sale:"
+msgid "Total:"
+msgstr "Összesen:"
+
+msgctxt "report:sale.sale:"
+msgid "Unit Price"
+msgstr "Egységár"
+
+msgctxt "selection:account.invoice,sale_exception_state:"
+msgid "Ignored"
+msgstr "figyelmen kívül hagyva"
+
+msgctxt "selection:account.invoice,sale_exception_state:"
+msgid "Recreated"
+msgstr "újra létrehozva"
+
+msgctxt "selection:sale.line,type:"
+msgid "Comment"
+msgstr "Megjegyzés"
+
+msgctxt "selection:sale.line,type:"
+msgid "Line"
+msgstr "Sor"
+
+msgctxt "selection:sale.line,type:"
+msgid "Subtotal"
+msgstr "Részösszeg"
+
+msgctxt "selection:sale.line,type:"
+msgid "Title"
+msgstr "Címsor"
+
+msgctxt "selection:sale.reporting.context,period:"
+msgid "Day"
+msgstr "Nap"
+
+msgctxt "selection:sale.reporting.context,period:"
+msgid "Month"
+msgstr "Hónap"
+
+msgctxt "selection:sale.reporting.context,period:"
+msgid "Year"
+msgstr "Év"
+
+msgctxt "selection:sale.sale,invoice_method:"
+msgid "Manual"
+msgstr "kézzel"
+
+msgctxt "selection:sale.sale,invoice_method:"
+msgid "On Order Processed"
+msgstr "a rendelés alapján"
+
+msgctxt "selection:sale.sale,invoice_method:"
+msgid "On Shipment Sent"
+msgstr "a vevői szállítmány alapján"
+
+msgctxt "selection:sale.sale,invoice_state:"
+msgid "Exception"
+msgstr "visszautasítva"
+
+msgctxt "selection:sale.sale,invoice_state:"
+msgid "None"
+msgstr "nincs"
+
+msgctxt "selection:sale.sale,invoice_state:"
+msgid "Paid"
+msgstr "Fizetve"
+
+msgctxt "selection:sale.sale,invoice_state:"
+msgid "Waiting"
+msgstr "várakozik"
+
+msgctxt "selection:sale.sale,shipment_method:"
+msgid "Manual"
+msgstr "kézzel"
+
+msgctxt "selection:sale.sale,shipment_method:"
+msgid "On Invoice Paid"
+msgstr "a kifizetett számla alapján"
+
+msgctxt "selection:sale.sale,shipment_method:"
+msgid "On Order Processed"
+msgstr "a rendelés alapján"
+
+msgctxt "selection:sale.sale,shipment_state:"
+msgid "Exception"
+msgstr "visszautasítva"
+
+msgctxt "selection:sale.sale,shipment_state:"
+msgid "None"
+msgstr "nincs"
+
+msgctxt "selection:sale.sale,shipment_state:"
+msgid "Sent"
+msgstr ""
+
+msgctxt "selection:sale.sale,shipment_state:"
+msgid "Waiting"
+msgstr "várakozik"
+
+msgctxt "selection:sale.sale,state:"
+msgid "Cancelled"
+msgstr "érvénytelen"
+
+msgctxt "selection:sale.sale,state:"
+msgid "Confirmed"
+msgstr "jóváhagyott"
+
+msgctxt "selection:sale.sale,state:"
+msgid "Done"
+msgstr "Kész"
+
+msgctxt "selection:sale.sale,state:"
+msgid "Draft"
+msgstr "vázlat"
+
+msgctxt "selection:sale.sale,state:"
+msgid "Processing"
+msgstr "folyamatban"
+
+msgctxt "selection:sale.sale,state:"
+msgid "Quotation"
+msgstr "ajánlat"
+
+msgctxt "selection:stock.move,sale_exception_state:"
+msgid "Ignored"
+msgstr "figyelmen kívül hagyva"
+
+msgctxt "selection:stock.move,sale_exception_state:"
+msgid "Recreated"
+msgstr "újra létrehozva"
+
+msgctxt "view:party.party:"
+msgid "Sale"
+msgstr "Vevő"
+
+msgctxt "view:product.template:"
+msgid "Customers"
+msgstr "Értékesítés"
+
+msgctxt "view:sale.handle.invoice.exception.ask:"
+msgid "Choose invoices to recreate:"
+msgstr "Válassza ki a számlákat, amiket újra létre szeretne hozni:"
+
+msgctxt "view:sale.handle.shipment.exception.ask:"
+msgid "Choose move to recreate:"
+msgstr "Válassza ki a készletmozgásokat, amiket újra létre szeretne hozni:"
+
+msgctxt "view:sale.line:"
+msgid "General"
+msgstr "Általános"
+
+msgctxt "view:sale.line:"
+msgid "Notes"
+msgstr "Jegyzetek"
+
+msgctxt "view:sale.line:"
+msgid "Taxes"
+msgstr "Adók"
+
+msgctxt "view:sale.return_sale.start:"
+msgid "Are you sure to return these/this sale(s)?"
+msgstr "Biztos, hogy vissza akarja vételezni ez(eke)t a rendelés(eke)t?"
+
+msgctxt "view:sale.sale:"
+msgid "Other Info"
+msgstr "Egyéb info"
+
+msgctxt "view:sale.sale:"
+msgid "Sale"
+msgstr "Vevői rendelés"
+
+msgctxt "wizard_button:sale.handle.invoice.exception,ask,end:"
+msgid "Cancel"
+msgstr "Mégse"
+
+msgctxt "wizard_button:sale.handle.invoice.exception,ask,handle:"
+msgid "OK"
+msgstr "OK"
+
+msgctxt "wizard_button:sale.handle.shipment.exception,ask,end:"
+msgid "Cancel"
+msgstr "Mégse"
+
+msgctxt "wizard_button:sale.handle.shipment.exception,ask,handle:"
+msgid "OK"
+msgstr "OK"
+
+msgctxt "wizard_button:sale.modify_header,start,end:"
+msgid "Cancel"
+msgstr "Mégse"
+
+msgctxt "wizard_button:sale.modify_header,start,modify:"
+msgid "Modify"
+msgstr "Módosítás"
+
+msgctxt "wizard_button:sale.return_sale,start,end:"
+msgid "Cancel"
+msgstr "Mégse"
+
+msgctxt "wizard_button:sale.return_sale,start,return_:"
+msgid "Return"
+msgstr "Visszavételezés"
diff --git a/modules/sale/locale/id.po b/modules/sale/locale/id.po
new file mode 100644
index 0000000000..6195163e86
--- /dev/null
+++ b/modules/sale/locale/id.po
@@ -0,0 +1,1372 @@
+#
+msgid ""
+msgstr "Content-Type: text/plain; charset=utf-8\n"
+
+msgctxt "field:account.invoice,sale_exception_state:"
+msgid "Exception State"
+msgstr ""
+
+msgctxt "field:account.invoice,sales:"
+msgid "Sales"
+msgstr ""
+
+msgctxt "field:product.configuration,default_lead_time:"
+msgid "Default Lead Time"
+msgstr ""
+
+#, fuzzy
+msgctxt "field:product.configuration.default_lead_time,company:"
+msgid "Company"
+msgstr "Perusahaan"
+
+msgctxt "field:product.configuration.default_lead_time,default_lead_time:"
+msgid "Default Lead Time"
+msgstr ""
+
+msgctxt "field:product.product,lead_time:"
+msgid "Lead Time"
+msgstr ""
+
+msgctxt "field:product.product,salable:"
+msgid "Salable"
+msgstr ""
+
+msgctxt "field:product.product,sale_price_uom:"
+msgid "Sale Price"
+msgstr ""
+
+msgctxt "field:product.product,sale_uom:"
+msgid "Sale UOM"
+msgstr ""
+
+#, fuzzy
+msgctxt "field:product.sale.context,company:"
+msgid "Company"
+msgstr "Perusahaan"
+
+#, fuzzy
+msgctxt "field:product.sale.context,currency:"
+msgid "Currency"
+msgstr "Mata uang"
+
+#, fuzzy
+msgctxt "field:product.sale.context,customer:"
+msgid "Customer"
+msgstr "Penjualan per Pelanggan"
+
+#, fuzzy
+msgctxt "field:product.sale.context,locations:"
+msgid "Warehouses"
+msgstr "Gudang"
+
+msgctxt "field:product.sale.context,quantity:"
+msgid "Quantity"
+msgstr ""
+
+#, fuzzy
+msgctxt "field:product.sale.context,sale_date:"
+msgid "Sale Date"
+msgstr "Tanggal Penjualan"
+
+msgctxt "field:product.sale.context,stock_date_end:"
+msgid "Stock End Date"
+msgstr ""
+
+msgctxt "field:product.template,lead_time:"
+msgid "Lead Time"
+msgstr ""
+
+msgctxt "field:product.template,salable:"
+msgid "Salable"
+msgstr ""
+
+msgctxt "field:product.template,sale_uom:"
+msgid "Sale UOM"
+msgstr ""
+
+msgctxt "field:sale.configuration,sale_invoice_method:"
+msgid "Sale Invoice Method"
+msgstr ""
+
+msgctxt "field:sale.configuration,sale_process_after:"
+msgid "Process Sale after"
+msgstr ""
+
+msgctxt "field:sale.configuration,sale_sequence:"
+msgid "Sale Sequence"
+msgstr ""
+
+msgctxt "field:sale.configuration,sale_shipment_method:"
+msgid "Sale Shipment Method"
+msgstr ""
+
+msgctxt "field:sale.configuration.sale_method,sale_invoice_method:"
+msgid "Sale Invoice Method"
+msgstr ""
+
+msgctxt "field:sale.configuration.sale_method,sale_shipment_method:"
+msgid "Sale Shipment Method"
+msgstr ""
+
+msgctxt "field:sale.configuration.sequence,company:"
+msgid "Company"
+msgstr "Perusahaan"
+
+msgctxt "field:sale.configuration.sequence,sale_sequence:"
+msgid "Sale Sequence"
+msgstr ""
+
+msgctxt "field:sale.handle.invoice.exception.ask,domain_invoices:"
+msgid "Domain Invoices"
+msgstr ""
+
+msgctxt "field:sale.handle.invoice.exception.ask,recreate_invoices:"
+msgid "Recreate Invoices"
+msgstr ""
+
+msgctxt "field:sale.handle.shipment.exception.ask,domain_moves:"
+msgid "Domain Moves"
+msgstr ""
+
+msgctxt "field:sale.handle.shipment.exception.ask,recreate_moves:"
+msgid "Recreate Moves"
+msgstr ""
+
+msgctxt "field:sale.line,actual_quantity:"
+msgid "Actual Quantity"
+msgstr ""
+
+msgctxt "field:sale.line,amount:"
+msgid "Amount"
+msgstr "Jumlah"
+
+#, fuzzy
+msgctxt "field:sale.line,company:"
+msgid "Company"
+msgstr "Perusahaan"
+
+#, fuzzy
+msgctxt "field:sale.line,currency:"
+msgid "Currency"
+msgstr "Mata uang"
+
+msgctxt "field:sale.line,description:"
+msgid "Description"
+msgstr "Deskripsi"
+
+msgctxt "field:sale.line,from_location:"
+msgid "From Location"
+msgstr ""
+
+msgctxt "field:sale.line,invoice_lines:"
+msgid "Invoice Lines"
+msgstr "Baris Faktur"
+
+msgctxt "field:sale.line,move_done:"
+msgid "Moves Done"
+msgstr "Perpindahan Selesai"
+
+msgctxt "field:sale.line,move_exception:"
+msgid "Moves Exception"
+msgstr ""
+
+msgctxt "field:sale.line,moves:"
+msgid "Moves"
+msgstr "Perpindahan"
+
+msgctxt "field:sale.line,moves_ignored:"
+msgid "Ignored Moves"
+msgstr ""
+
+msgctxt "field:sale.line,moves_recreated:"
+msgid "Recreated Moves"
+msgstr ""
+
+msgctxt "field:sale.line,note:"
+msgid "Note"
+msgstr "Catatan"
+
+msgctxt "field:sale.line,product:"
+msgid "Product"
+msgstr "Produk"
+
+msgctxt "field:sale.line,product_uom_category:"
+msgid "Product Uom Category"
+msgstr ""
+
+msgctxt "field:sale.line,quantity:"
+msgid "Quantity"
+msgstr ""
+
+msgctxt "field:sale.line,sale:"
+msgid "Sale"
+msgstr "Penjualan"
+
+msgctxt "field:sale.line,sale_state:"
+msgid "Sale State"
+msgstr ""
+
+msgctxt "field:sale.line,shipping_date:"
+msgid "Shipping Date"
+msgstr ""
+
+msgctxt "field:sale.line,summary:"
+msgid "Summary"
+msgstr ""
+
+msgctxt "field:sale.line,taxes:"
+msgid "Taxes"
+msgstr ""
+
+msgctxt "field:sale.line,to_location:"
+msgid "To Location"
+msgstr ""
+
+msgctxt "field:sale.line,type:"
+msgid "Type"
+msgstr ""
+
+msgctxt "field:sale.line,unit:"
+msgid "Unit"
+msgstr ""
+
+msgctxt "field:sale.line,unit_digits:"
+msgid "Unit Digits"
+msgstr ""
+
+msgctxt "field:sale.line,unit_price:"
+msgid "Unit Price"
+msgstr ""
+
+msgctxt "field:sale.line,warehouse:"
+msgid "Warehouse"
+msgstr "Gudang"
+
+msgctxt "field:sale.line-account.tax,line:"
+msgid "Sale Line"
+msgstr "Baris Penjualan"
+
+msgctxt "field:sale.line-account.tax,tax:"
+msgid "Tax"
+msgstr "Pajak"
+
+msgctxt "field:sale.line-ignored-stock.move,move:"
+msgid "Move"
+msgstr "Perpindahan"
+
+msgctxt "field:sale.line-ignored-stock.move,sale_line:"
+msgid "Sale Line"
+msgstr "Baris Penjualan"
+
+msgctxt "field:sale.line-recreated-stock.move,move:"
+msgid "Move"
+msgstr "Perpindahan"
+
+msgctxt "field:sale.line-recreated-stock.move,sale_line:"
+msgid "Sale Line"
+msgstr "Baris Penjualan"
+
+msgctxt "field:sale.reporting.category,category:"
+msgid "Category"
+msgstr "Kategori"
+
+msgctxt "field:sale.reporting.category,time_series:"
+msgid "Time Series"
+msgstr ""
+
+msgctxt "field:sale.reporting.category.time_series,category:"
+msgid "Category"
+msgstr "Kategori"
+
+msgctxt "field:sale.reporting.category.time_series,date:"
+msgid "Date"
+msgstr "Tanggal"
+
+msgctxt "field:sale.reporting.category.tree,children:"
+msgid "Children"
+msgstr "Cabang"
+
+msgctxt "field:sale.reporting.category.tree,currency_digits:"
+msgid "Currency Digits"
+msgstr ""
+
+msgctxt "field:sale.reporting.category.tree,name:"
+msgid "Name"
+msgstr "Nama"
+
+msgctxt "field:sale.reporting.category.tree,parent:"
+msgid "Parent"
+msgstr "Induk"
+
+msgctxt "field:sale.reporting.category.tree,revenue:"
+msgid "Revenue"
+msgstr "Pendapatan"
+
+msgctxt "field:sale.reporting.context,company:"
+msgid "Company"
+msgstr "Perusahaan"
+
+msgctxt "field:sale.reporting.context,from_date:"
+msgid "From Date"
+msgstr "Dari Tanggal"
+
+msgctxt "field:sale.reporting.context,period:"
+msgid "Period"
+msgstr "Periode"
+
+msgctxt "field:sale.reporting.context,to_date:"
+msgid "To Date"
+msgstr "Ke Tanggal"
+
+msgctxt "field:sale.reporting.context,warehouse:"
+msgid "Warehouse"
+msgstr "Gudang"
+
+msgctxt "field:sale.reporting.country,country:"
+msgid "Country"
+msgstr "Negara"
+
+msgctxt "field:sale.reporting.country,time_series:"
+msgid "Time Series"
+msgstr ""
+
+msgctxt "field:sale.reporting.country.subdivision,country:"
+msgid "Country"
+msgstr "Negara"
+
+msgctxt "field:sale.reporting.country.subdivision,subdivision:"
+msgid "Subdivision"
+msgstr ""
+
+msgctxt "field:sale.reporting.country.subdivision,time_series:"
+msgid "Time Series"
+msgstr ""
+
+msgctxt "field:sale.reporting.country.subdivision.time_series,country:"
+msgid "Country"
+msgstr ""
+
+msgctxt "field:sale.reporting.country.subdivision.time_series,date:"
+msgid "Date"
+msgstr "Tanggal"
+
+msgctxt "field:sale.reporting.country.subdivision.time_series,subdivision:"
+msgid "Subdivision"
+msgstr ""
+
+msgctxt "field:sale.reporting.country.time_series,country:"
+msgid "Country"
+msgstr "Negara"
+
+msgctxt "field:sale.reporting.country.time_series,date:"
+msgid "Date"
+msgstr "Tanggal"
+
+msgctxt "field:sale.reporting.customer,customer:"
+msgid "Customer"
+msgstr ""
+
+msgctxt "field:sale.reporting.customer,time_series:"
+msgid "Time Series"
+msgstr ""
+
+msgctxt "field:sale.reporting.customer.time_series,customer:"
+msgid "Customer"
+msgstr ""
+
+msgctxt "field:sale.reporting.customer.time_series,date:"
+msgid "Date"
+msgstr "Tanggal"
+
+msgctxt "field:sale.reporting.product,product:"
+msgid "Product"
+msgstr "Produk"
+
+msgctxt "field:sale.reporting.product,time_series:"
+msgid "Time Series"
+msgstr ""
+
+msgctxt "field:sale.reporting.product.time_series,date:"
+msgid "Date"
+msgstr "Tanggal"
+
+msgctxt "field:sale.reporting.product.time_series,product:"
+msgid "Product"
+msgstr "Produk"
+
+msgctxt "field:sale.reporting.region,children:"
+msgid "Children"
+msgstr "Cabang"
+
+msgctxt "field:sale.reporting.region,parent:"
+msgid "Parent"
+msgstr "Induk"
+
+msgctxt "field:sale.reporting.region,region:"
+msgid "Region"
+msgstr ""
+
+msgctxt "field:sale.sale,comment:"
+msgid "Comment"
+msgstr "Komentar"
+
+msgctxt "field:sale.sale,company:"
+msgid "Company"
+msgstr "Perusahaan"
+
+#, fuzzy
+msgctxt "field:sale.sale,confirmed_by:"
+msgid "Confirmed By"
+msgstr "Konfirmasi"
+
+msgctxt "field:sale.sale,contact:"
+msgid "Contact"
+msgstr ""
+
+msgctxt "field:sale.sale,currency:"
+msgid "Currency"
+msgstr "Mata uang"
+
+msgctxt "field:sale.sale,currency_digits:"
+msgid "Currency Digits"
+msgstr ""
+
+msgctxt "field:sale.sale,description:"
+msgid "Description"
+msgstr "Deskripsi"
+
+msgctxt "field:sale.sale,invoice_address:"
+msgid "Invoice Address"
+msgstr "Alamat Faktur"
+
+msgctxt "field:sale.sale,invoice_method:"
+msgid "Invoice Method"
+msgstr "Metode Faktur"
+
+#, fuzzy
+msgctxt "field:sale.sale,invoice_party:"
+msgid "Invoice Party"
+msgstr "Status Faktur"
+
+msgctxt "field:sale.sale,invoice_state:"
+msgid "Invoice State"
+msgstr "Status Faktur"
+
+msgctxt "field:sale.sale,invoices:"
+msgid "Invoices"
+msgstr "Faktur-faktur"
+
+msgctxt "field:sale.sale,invoices_ignored:"
+msgid "Ignored Invoices"
+msgstr "Faktur-faktur yang Diabaikan"
+
+msgctxt "field:sale.sale,invoices_recreated:"
+msgid "Recreated Invoices"
+msgstr ""
+
+msgctxt "field:sale.sale,lines:"
+msgid "Lines"
+msgstr "Baris"
+
+msgctxt "field:sale.sale,moves:"
+msgid "Moves"
+msgstr "Perpindahan"
+
+msgctxt "field:sale.sale,number:"
+msgid "Number"
+msgstr "Nomor"
+
+msgctxt "field:sale.sale,origin:"
+msgid "Origin"
+msgstr "Asal"
+
+msgctxt "field:sale.sale,party:"
+msgid "Party"
+msgstr "Pihak"
+
+msgctxt "field:sale.sale,party_lang:"
+msgid "Party Language"
+msgstr ""
+
+msgctxt "field:sale.sale,payment_term:"
+msgid "Payment Term"
+msgstr "Masa Pembayaran"
+
+msgctxt "field:sale.sale,quoted_by:"
+msgid "Quoted By"
+msgstr "Dikutip Oleh"
+
+msgctxt "field:sale.sale,reference:"
+msgid "Reference"
+msgstr "Referensi"
+
+msgctxt "field:sale.sale,sale_date:"
+msgid "Sale Date"
+msgstr "Tanggal Penjualan"
+
+msgctxt "field:sale.sale,shipment_address:"
+msgid "Shipment Address"
+msgstr ""
+
+msgctxt "field:sale.sale,shipment_method:"
+msgid "Shipment Method"
+msgstr ""
+
+msgctxt "field:sale.sale,shipment_party:"
+msgid "Shipment Party"
+msgstr ""
+
+msgctxt "field:sale.sale,shipment_returns:"
+msgid "Shipment Returns"
+msgstr ""
+
+msgctxt "field:sale.sale,shipment_state:"
+msgid "Shipment State"
+msgstr ""
+
+msgctxt "field:sale.sale,shipments:"
+msgid "Shipments"
+msgstr ""
+
+msgctxt "field:sale.sale,shipping_date:"
+msgid "Shipping Date"
+msgstr ""
+
+msgctxt "field:sale.sale,state:"
+msgid "State"
+msgstr "Status"
+
+msgctxt "field:sale.sale,tax_amount:"
+msgid "Tax"
+msgstr "Pajak"
+
+msgctxt "field:sale.sale,tax_amount_cache:"
+msgid "Tax Cache"
+msgstr ""
+
+msgctxt "field:sale.sale,total_amount:"
+msgid "Total"
+msgstr "Total"
+
+#, fuzzy
+msgctxt "field:sale.sale,total_amount_cache:"
+msgid "Total Cache"
+msgstr "Total"
+
+msgctxt "field:sale.sale,untaxed_amount:"
+msgid "Untaxed"
+msgstr ""
+
+msgctxt "field:sale.sale,untaxed_amount_cache:"
+msgid "Untaxed Cache"
+msgstr ""
+
+msgctxt "field:sale.sale,warehouse:"
+msgid "Warehouse"
+msgstr "Gudang"
+
+msgctxt "field:sale.sale-ignored-account.invoice,invoice:"
+msgid "Invoice"
+msgstr "Faktur"
+
+msgctxt "field:sale.sale-ignored-account.invoice,sale:"
+msgid "Sale"
+msgstr "Penjualan"
+
+msgctxt "field:sale.sale-recreated-account.invoice,invoice:"
+msgid "Invoice"
+msgstr "Faktur"
+
+msgctxt "field:sale.sale-recreated-account.invoice,sale:"
+msgid "Sale"
+msgstr "Penjualan"
+
+msgctxt "field:stock.move,sale:"
+msgid "Sale"
+msgstr "Penjualan"
+
+msgctxt "field:stock.move,sale_exception_state:"
+msgid "Exception State"
+msgstr ""
+
+msgctxt "help:product.configuration,default_lead_time:"
+msgid ""
+"The time from confirming the sales order to sending the products.\n"
+"Used for products without a lead time."
+msgstr ""
+
+msgctxt "help:product.product,lead_time:"
+msgid ""
+"The time from confirming the sales order to sending the products.\n"
+"If empty the default lead time from the configuration is used."
+msgstr ""
+
+msgctxt "help:product.template,lead_time:"
+msgid ""
+"The time from confirming the sales order to sending the products.\n"
+"If empty the default lead time from the configuration is used."
+msgstr ""
+
+msgctxt "help:sale.configuration,sale_process_after:"
+msgid ""
+"The grace period during which confirmed sale can still be reset to draft.\n"
+"Applied if a worker queue is activated."
+msgstr ""
+
+msgctxt "help:sale.handle.invoice.exception.ask,recreate_invoices:"
+msgid ""
+"The selected invoices will be recreated. The other ones will be ignored."
+msgstr ""
+
+msgctxt "help:sale.sale,shipping_date:"
+msgid "When the shipping of goods should start."
+msgstr ""
+
+msgctxt "model:ir.action,name:act_invoice_form"
+msgid "Invoices"
+msgstr "Faktur-faktur"
+
+msgctxt "model:ir.action,name:act_open_customer"
+msgid "Parties associated to Sales"
+msgstr "Pihak terkait dengan Penjualan"
+
+#, fuzzy
+msgctxt "model:ir.action,name:act_product"
+msgid "Products"
+msgstr "Produk"
+
+msgctxt "model:ir.action,name:act_reporting_category"
+msgid "Sales per Category"
+msgstr "Penjualan per Kategori"
+
+msgctxt "model:ir.action,name:act_reporting_category_time_series"
+msgid "Sales per Category"
+msgstr "Penjualan per Kategori"
+
+msgctxt "model:ir.action,name:act_reporting_category_tree"
+msgid "Sales per Category"
+msgstr "Penjualan per Kategori"
+
+msgctxt "model:ir.action,name:act_reporting_country_subdivision_time_series"
+msgid "Sales per Subdivision"
+msgstr "Penjualan per Subdivisi"
+
+msgctxt "model:ir.action,name:act_reporting_country_time_series"
+msgid "Sales per Country"
+msgstr "Penjualan per Negara"
+
+msgctxt "model:ir.action,name:act_reporting_customer"
+msgid "Sales per Customer"
+msgstr "Penjualan per Pelanggan"
+
+msgctxt "model:ir.action,name:act_reporting_customer_time_series"
+msgid "Sales per Customer"
+msgstr "Penjualan per Pelanggan"
+
+msgctxt "model:ir.action,name:act_reporting_product"
+msgid "Sales per Product"
+msgstr "Penjualan per Produk"
+
+msgctxt "model:ir.action,name:act_reporting_product_time_series"
+msgid "Sales per Product"
+msgstr "Penjualan per Produk"
+
+msgctxt "model:ir.action,name:act_reporting_region"
+msgid "Sales per Region"
+msgstr "Penjualan per Wilayah"
+
+msgctxt "model:ir.action,name:act_return_form"
+msgid "Returns"
+msgstr ""
+
+#, fuzzy
+msgctxt "model:ir.action,name:act_sale_configuration_form"
+msgid "Configuration"
+msgstr "Konfigurasi"
+
+msgctxt "model:ir.action,name:act_sale_form"
+msgid "Sales"
+msgstr ""
+
+msgctxt "model:ir.action,name:act_sale_form2"
+msgid "Sales"
+msgstr ""
+
+msgctxt "model:ir.action,name:act_sale_invoice_relate"
+msgid "Sales"
+msgstr ""
+
+#, fuzzy
+msgctxt "model:ir.action,name:act_sale_move_relate"
+msgid "Moves"
+msgstr "Perpindahan"
+
+msgctxt "model:ir.action,name:act_sale_shipment_returns_relate"
+msgid "Sales"
+msgstr ""
+
+msgctxt "model:ir.action,name:act_sale_shipments_relate"
+msgid "Sales"
+msgstr ""
+
+msgctxt "model:ir.action,name:act_shipment_form"
+msgid "Shipments"
+msgstr ""
+
+msgctxt "model:ir.action,name:report_sale"
+msgid "Sale"
+msgstr "Penjualan"
+
+msgctxt "model:ir.action,name:wizard_invoice_handle_exception"
+msgid "Handle Invoice Exception"
+msgstr ""
+
+msgctxt "model:ir.action,name:wizard_modify_header"
+msgid "Modify Header"
+msgstr ""
+
+msgctxt "model:ir.action,name:wizard_reporting_region_open"
+msgid "Open Region"
+msgstr ""
+
+msgctxt "model:ir.action,name:wizard_return_sale"
+msgid "Return Sale"
+msgstr ""
+
+msgctxt "model:ir.action,name:wizard_shipment_handle_exception"
+msgid "Handle Shipment Exception"
+msgstr ""
+
+msgctxt "model:ir.action.act_window.domain,name:act_sale_form_domain_all"
+msgid "All"
+msgstr ""
+
+msgctxt ""
+"model:ir.action.act_window.domain,name:act_sale_form_domain_confirmed"
+msgid "Confirmed"
+msgstr ""
+
+msgctxt "model:ir.action.act_window.domain,name:act_sale_form_domain_draft"
+msgid "Draft"
+msgstr "Rancangan"
+
+msgctxt ""
+"model:ir.action.act_window.domain,name:act_sale_form_domain_exception"
+msgid "Exception"
+msgstr ""
+
+msgctxt ""
+"model:ir.action.act_window.domain,name:act_sale_form_domain_processing"
+msgid "Processing"
+msgstr ""
+
+msgctxt ""
+"model:ir.action.act_window.domain,name:act_sale_form_domain_quotation"
+msgid "Quotation"
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_erase_party_pending_sale"
+msgid ""
+"You cannot erase party \"%(party)s\" while they have pending sales with "
+"company \"%(company)s\"."
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_sale_customer_location_required"
+msgid ""
+"To process sale \"%(sale)s\" you must set a customer location on party "
+"\"%(party)s\"."
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_sale_delete_cancel"
+msgid "To delete sale \"%(sale)s\" you must cancel it."
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_sale_invalid_method"
+msgid ""
+"You cannot use together invoice \"%(invoice_method)s\" and shipment "
+"\"%(shipment_method)s\" on sale \"%(sale)s\"."
+msgstr ""
+
+msgctxt ""
+"model:ir.message,text:msg_sale_invoice_address_required_for_quotation"
+msgid "To get a quote for sale \"%(sale)s\" you must enter an invoice address."
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_sale_invoice_reset_draft"
+msgid ""
+"You cannot reset invoice \"%(invoice)s\" to draft because it was generated "
+"by a sale."
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_sale_line_delete_cancel_draft"
+msgid ""
+"To delete line \"%(line)s\" you must cancel or reset to draft sale "
+"\"%(sale)s\"."
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_sale_missing_account_revenue"
+msgid "To invoice sale \"%(sale)s\" you must configure a default account revenue."
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_sale_modify_header_draft"
+msgid "To modify the header of sale \"%(sale)s\", it must be in \"draft\" state."
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_sale_move_reset_draft"
+msgid ""
+"You cannot reset move \"%(move)s\" to draft because it was generated by a "
+"sale."
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_sale_product_missing_account_revenue"
+msgid ""
+"To invoice sale \"%(sale)s\" you must define an account revenue for product "
+"\"%(product)s\"."
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_sale_reporting_company"
+msgid "Company"
+msgstr "Perusahaan"
+
+#, fuzzy
+msgctxt "model:ir.message,text:msg_sale_reporting_currency"
+msgid "Currency"
+msgstr "Mata uang"
+
+#, fuzzy
+msgctxt "model:ir.message,text:msg_sale_reporting_currency_digits"
+msgid "Currency Digits"
+msgstr "Mata uang"
+
+msgctxt "model:ir.message,text:msg_sale_reporting_number"
+msgid "#"
+msgstr "#"
+
+msgctxt "model:ir.message,text:msg_sale_reporting_number_help"
+msgid "Number of sales"
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_sale_reporting_revenue"
+msgid "Revenue"
+msgstr "Pendapatan"
+
+#, fuzzy
+msgctxt "model:ir.message,text:msg_sale_reporting_revenue_trend"
+msgid "Revenue Trend"
+msgstr "Pendapatan"
+
+msgctxt ""
+"model:ir.message,text:msg_sale_shipment_address_required_for_quotation"
+msgid "To get a quote for sale \"%(sale)s\" you must enter a shipment address."
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_sale_warehouse_required_for_quotation"
+msgid "To get a quote for sale \"%(sale)s\" you must enter a warehouse."
+msgstr ""
+
+msgctxt "model:ir.model.button,string:sale_cancel_button"
+msgid "Cancel"
+msgstr "Batal"
+
+msgctxt "model:ir.model.button,string:sale_confirm_button"
+msgid "Confirm"
+msgstr "Konfirmasi"
+
+msgctxt "model:ir.model.button,string:sale_draft_button"
+msgid "Draft"
+msgstr "Rancangan"
+
+msgctxt "model:ir.model.button,string:sale_handle_invoice_exception_button"
+msgid "Handle Invoice Exception"
+msgstr ""
+
+msgctxt "model:ir.model.button,string:sale_handle_shipment_exception_button"
+msgid "Handle Shipment Exception"
+msgstr ""
+
+msgctxt "model:ir.model.button,string:sale_modify_header_button"
+msgid "Modify Header"
+msgstr ""
+
+msgctxt "model:ir.model.button,string:sale_process_button"
+msgid "Process"
+msgstr "Proses"
+
+msgctxt "model:ir.model.button,string:sale_quote_button"
+msgid "Quote"
+msgstr ""
+
+#, fuzzy
+msgctxt "model:ir.rule.group,name:rule_group_reporting_category_companies"
+msgid "User in companies"
+msgstr "Pengguna di dalam perusahaan"
+
+#, fuzzy
+msgctxt ""
+"model:ir.rule.group,name:rule_group_reporting_category_time_series_companies"
+msgid "User in companies"
+msgstr "Pengguna di dalam perusahaan"
+
+#, fuzzy
+msgctxt ""
+"model:ir.rule.group,name:rule_group_reporting_country_subdivision_time_series_companies"
+msgid "User in companies"
+msgstr "Pengguna di dalam perusahaan"
+
+#, fuzzy
+msgctxt ""
+"model:ir.rule.group,name:rule_group_reporting_country_time_series_companies"
+msgid "User in companies"
+msgstr "Pengguna di dalam perusahaan"
+
+#, fuzzy
+msgctxt "model:ir.rule.group,name:rule_group_reporting_customer_companies"
+msgid "User in companies"
+msgstr "Pengguna di dalam perusahaan"
+
+#, fuzzy
+msgctxt ""
+"model:ir.rule.group,name:rule_group_reporting_customer_time_series_companies"
+msgid "User in companies"
+msgstr "Pengguna di dalam perusahaan"
+
+#, fuzzy
+msgctxt "model:ir.rule.group,name:rule_group_reporting_product_companies"
+msgid "User in companies"
+msgstr "Pengguna di dalam perusahaan"
+
+#, fuzzy
+msgctxt ""
+"model:ir.rule.group,name:rule_group_reporting_product_time_series_companies"
+msgid "User in companies"
+msgstr "Pengguna di dalam perusahaan"
+
+#, fuzzy
+msgctxt "model:ir.rule.group,name:rule_group_reporting_region_companies"
+msgid "User in companies"
+msgstr "Pengguna di dalam perusahaan"
+
+#, fuzzy
+msgctxt "model:ir.rule.group,name:rule_group_sale_companies"
+msgid "User in companies"
+msgstr "Pengguna di dalam perusahaan"
+
+msgctxt "model:ir.sequence,name:sequence_sale"
+msgid "Sale"
+msgstr "Penjualan"
+
+msgctxt "model:ir.sequence.type,name:sequence_type_sale"
+msgid "Sale"
+msgstr "Penjualan"
+
+msgctxt "model:ir.ui.menu,name:menu_configuration"
+msgid "Configuration"
+msgstr "Konfigurasi"
+
+#, fuzzy
+msgctxt "model:ir.ui.menu,name:menu_customer"
+msgid "Associated to Sales"
+msgstr "Pihak terkait dengan Penjualan"
+
+#, fuzzy
+msgctxt "model:ir.ui.menu,name:menu_product"
+msgid "Products"
+msgstr "Produk"
+
+msgctxt "model:ir.ui.menu,name:menu_reporting"
+msgid "Reporting"
+msgstr "Pelaporan"
+
+msgctxt "model:ir.ui.menu,name:menu_reporting_sale"
+msgid "Sales"
+msgstr ""
+
+msgctxt "model:ir.ui.menu,name:menu_sale"
+msgid "Sales"
+msgstr ""
+
+#, fuzzy
+msgctxt "model:ir.ui.menu,name:menu_sale_configuration"
+msgid "Configuration"
+msgstr "Konfigurasi"
+
+msgctxt "model:ir.ui.menu,name:menu_sale_form"
+msgid "Sales"
+msgstr ""
+
+msgctxt "model:product.configuration.default_lead_time,name:"
+msgid "Product Default Lead Time"
+msgstr ""
+
+msgctxt "model:product.sale.context,name:"
+msgid "Product Sale Context"
+msgstr ""
+
+msgctxt "model:res.group,name:group_sale"
+msgid "Sales"
+msgstr ""
+
+msgctxt "model:res.group,name:group_sale_admin"
+msgid "Sales Administrator"
+msgstr ""
+
+msgctxt "model:sale.configuration,name:"
+msgid "Sale Configuration"
+msgstr ""
+
+msgctxt "model:sale.configuration.sale_method,name:"
+msgid "Sale Configuration Sale Method"
+msgstr ""
+
+msgctxt "model:sale.configuration.sequence,name:"
+msgid "Sale Configuration Sequence"
+msgstr ""
+
+msgctxt "model:sale.handle.invoice.exception.ask,name:"
+msgid "Handle Invoice Exception"
+msgstr ""
+
+msgctxt "model:sale.handle.shipment.exception.ask,name:"
+msgid "Handle Shipment Exception"
+msgstr ""
+
+msgctxt "model:sale.line,name:"
+msgid "Sale Line"
+msgstr "Baris Penjualan"
+
+msgctxt "model:sale.line-account.tax,name:"
+msgid "Sale Line - Tax"
+msgstr "Baris Penjualan - Pajak"
+
+msgctxt "model:sale.line-ignored-stock.move,name:"
+msgid "Sale Line - Ignored Move"
+msgstr "Baris Penjualan - Perpindahan Diabaikan"
+
+msgctxt "model:sale.line-recreated-stock.move,name:"
+msgid "Sale Line - Recreated Move"
+msgstr ""
+
+msgctxt "model:sale.reporting.category,name:"
+msgid "Sale Reporting per Category"
+msgstr ""
+
+msgctxt "model:sale.reporting.category.time_series,name:"
+msgid "Sale Reporting per Category"
+msgstr ""
+
+msgctxt "model:sale.reporting.category.tree,name:"
+msgid "Sale Reporting per Category"
+msgstr ""
+
+msgctxt "model:sale.reporting.context,name:"
+msgid "Sale Reporting Context"
+msgstr ""
+
+msgctxt "model:sale.reporting.country,name:"
+msgid "Sale Reporting per Country"
+msgstr ""
+
+msgctxt "model:sale.reporting.country.subdivision,name:"
+msgid "Sale Reporting per Subdivision"
+msgstr ""
+
+msgctxt "model:sale.reporting.country.subdivision.time_series,name:"
+msgid "Sale Reporting per Subdivision"
+msgstr ""
+
+msgctxt "model:sale.reporting.country.time_series,name:"
+msgid "Sale Reporting per Country"
+msgstr ""
+
+msgctxt "model:sale.reporting.customer,name:"
+msgid "Sale Reporting per Customer"
+msgstr ""
+
+msgctxt "model:sale.reporting.customer.time_series,name:"
+msgid "Sale Reporting per Customer"
+msgstr ""
+
+msgctxt "model:sale.reporting.product,name:"
+msgid "Sale Reporting per Product"
+msgstr ""
+
+msgctxt "model:sale.reporting.product.time_series,name:"
+msgid "Sale Reporting per Product"
+msgstr ""
+
+msgctxt "model:sale.reporting.region,name:"
+msgid "Sale Reporting per Region"
+msgstr ""
+
+msgctxt "model:sale.return_sale.start,name:"
+msgid "Return Sale"
+msgstr ""
+
+msgctxt "model:sale.sale,name:"
+msgid "Sale"
+msgstr "Penjualan"
+
+msgctxt "model:sale.sale-ignored-account.invoice,name:"
+msgid "Sale - Ignored Invoice"
+msgstr "Penjualan - Faktur yang Diabaikan"
+
+msgctxt "model:sale.sale-recreated-account.invoice,name:"
+msgid "Sale - Recreated Invoice"
+msgstr "Penjualan - Faktur yang Dibuat Ulang"
+
+msgctxt "report:sale.sale:"
+msgid ":"
+msgstr ":"
+
+msgctxt "report:sale.sale:"
+msgid "Amount"
+msgstr "Jumlah"
+
+msgctxt "report:sale.sale:"
+msgid "Date:"
+msgstr "Tanggal:"
+
+msgctxt "report:sale.sale:"
+msgid "Description"
+msgstr "Deskripsi"
+
+msgctxt "report:sale.sale:"
+msgid "Description:"
+msgstr "Deskripsi:"
+
+msgctxt "report:sale.sale:"
+msgid "Draft Sale Order"
+msgstr ""
+
+msgctxt "report:sale.sale:"
+msgid "Quantity"
+msgstr ""
+
+msgctxt "report:sale.sale:"
+msgid "Quotation N°:"
+msgstr ""
+
+msgctxt "report:sale.sale:"
+msgid "Reference:"
+msgstr ""
+
+msgctxt "report:sale.sale:"
+msgid "Sale Order N°:"
+msgstr ""
+
+msgctxt "report:sale.sale:"
+msgid "Taxes"
+msgstr ""
+
+msgctxt "report:sale.sale:"
+msgid "Taxes:"
+msgstr ""
+
+msgctxt "report:sale.sale:"
+msgid "Total (excl. taxes):"
+msgstr "Total (di luar pajak):"
+
+msgctxt "report:sale.sale:"
+msgid "Total:"
+msgstr "Total:"
+
+msgctxt "report:sale.sale:"
+msgid "Unit Price"
+msgstr ""
+
+msgctxt "selection:account.invoice,sale_exception_state:"
+msgid "Ignored"
+msgstr ""
+
+msgctxt "selection:account.invoice,sale_exception_state:"
+msgid "Recreated"
+msgstr ""
+
+msgctxt "selection:sale.line,type:"
+msgid "Comment"
+msgstr "Komentar"
+
+msgctxt "selection:sale.line,type:"
+msgid "Line"
+msgstr ""
+
+msgctxt "selection:sale.line,type:"
+msgid "Subtotal"
+msgstr ""
+
+msgctxt "selection:sale.line,type:"
+msgid "Title"
+msgstr ""
+
+msgctxt "selection:sale.reporting.context,period:"
+msgid "Day"
+msgstr "Hari"
+
+msgctxt "selection:sale.reporting.context,period:"
+msgid "Month"
+msgstr "Bulan"
+
+msgctxt "selection:sale.reporting.context,period:"
+msgid "Year"
+msgstr "Tahun"
+
+msgctxt "selection:sale.sale,invoice_method:"
+msgid "Manual"
+msgstr ""
+
+msgctxt "selection:sale.sale,invoice_method:"
+msgid "On Order Processed"
+msgstr ""
+
+msgctxt "selection:sale.sale,invoice_method:"
+msgid "On Shipment Sent"
+msgstr ""
+
+msgctxt "selection:sale.sale,invoice_state:"
+msgid "Exception"
+msgstr ""
+
+msgctxt "selection:sale.sale,invoice_state:"
+msgid "None"
+msgstr "Tidak ada"
+
+msgctxt "selection:sale.sale,invoice_state:"
+msgid "Paid"
+msgstr ""
+
+msgctxt "selection:sale.sale,invoice_state:"
+msgid "Waiting"
+msgstr ""
+
+msgctxt "selection:sale.sale,shipment_method:"
+msgid "Manual"
+msgstr ""
+
+msgctxt "selection:sale.sale,shipment_method:"
+msgid "On Invoice Paid"
+msgstr ""
+
+msgctxt "selection:sale.sale,shipment_method:"
+msgid "On Order Processed"
+msgstr ""
+
+msgctxt "selection:sale.sale,shipment_state:"
+msgid "Exception"
+msgstr ""
+
+msgctxt "selection:sale.sale,shipment_state:"
+msgid "None"
+msgstr "Tidak ada"
+
+msgctxt "selection:sale.sale,shipment_state:"
+msgid "Sent"
+msgstr ""
+
+msgctxt "selection:sale.sale,shipment_state:"
+msgid "Waiting"
+msgstr ""
+
+#, fuzzy
+msgctxt "selection:sale.sale,state:"
+msgid "Cancelled"
+msgstr "Batal"
+
+msgctxt "selection:sale.sale,state:"
+msgid "Confirmed"
+msgstr ""
+
+msgctxt "selection:sale.sale,state:"
+msgid "Done"
+msgstr ""
+
+msgctxt "selection:sale.sale,state:"
+msgid "Draft"
+msgstr "Rancangan"
+
+msgctxt "selection:sale.sale,state:"
+msgid "Processing"
+msgstr ""
+
+msgctxt "selection:sale.sale,state:"
+msgid "Quotation"
+msgstr ""
+
+msgctxt "selection:stock.move,sale_exception_state:"
+msgid "Ignored"
+msgstr ""
+
+msgctxt "selection:stock.move,sale_exception_state:"
+msgid "Recreated"
+msgstr ""
+
+msgctxt "view:party.party:"
+msgid "Sale"
+msgstr "Penjualan"
+
+msgctxt "view:product.template:"
+msgid "Customers"
+msgstr ""
+
+msgctxt "view:sale.handle.invoice.exception.ask:"
+msgid "Choose invoices to recreate:"
+msgstr ""
+
+msgctxt "view:sale.handle.shipment.exception.ask:"
+msgid "Choose move to recreate:"
+msgstr ""
+
+msgctxt "view:sale.line:"
+msgid "General"
+msgstr "Umum"
+
+msgctxt "view:sale.line:"
+msgid "Notes"
+msgstr ""
+
+msgctxt "view:sale.line:"
+msgid "Taxes"
+msgstr ""
+
+msgctxt "view:sale.return_sale.start:"
+msgid "Are you sure to return these/this sale(s)?"
+msgstr ""
+
+msgctxt "view:sale.sale:"
+msgid "Other Info"
+msgstr "Info Lain"
+
+msgctxt "view:sale.sale:"
+msgid "Sale"
+msgstr "Penjualan"
+
+msgctxt "wizard_button:sale.handle.invoice.exception,ask,end:"
+msgid "Cancel"
+msgstr "Batal"
+
+msgctxt "wizard_button:sale.handle.invoice.exception,ask,handle:"
+msgid "OK"
+msgstr "OK"
+
+msgctxt "wizard_button:sale.handle.shipment.exception,ask,end:"
+msgid "Cancel"
+msgstr "Batal"
+
+msgctxt "wizard_button:sale.handle.shipment.exception,ask,handle:"
+msgid "OK"
+msgstr "OK"
+
+msgctxt "wizard_button:sale.modify_header,start,end:"
+msgid "Cancel"
+msgstr "Batal"
+
+msgctxt "wizard_button:sale.modify_header,start,modify:"
+msgid "Modify"
+msgstr ""
+
+msgctxt "wizard_button:sale.return_sale,start,end:"
+msgid "Cancel"
+msgstr "Batal"
+
+msgctxt "wizard_button:sale.return_sale,start,return_:"
+msgid "Return"
+msgstr ""
diff --git a/modules/sale/locale/it.po b/modules/sale/locale/it.po
new file mode 100644
index 0000000000..190c58f6bb
--- /dev/null
+++ b/modules/sale/locale/it.po
@@ -0,0 +1,1407 @@
+#
+msgid ""
+msgstr "Content-Type: text/plain; charset=utf-8\n"
+
+msgctxt "field:account.invoice,sale_exception_state:"
+msgid "Exception State"
+msgstr "stato di eccezione"
+
+msgctxt "field:account.invoice,sales:"
+msgid "Sales"
+msgstr "Vendite"
+
+#, fuzzy
+msgctxt "field:product.configuration,default_lead_time:"
+msgid "Default Lead Time"
+msgstr "lead time"
+
+#, fuzzy
+msgctxt "field:product.configuration.default_lead_time,company:"
+msgid "Company"
+msgstr "Azienda"
+
+#, fuzzy
+msgctxt "field:product.configuration.default_lead_time,default_lead_time:"
+msgid "Default Lead Time"
+msgstr "lead time"
+
+msgctxt "field:product.product,lead_time:"
+msgid "Lead Time"
+msgstr "lead time"
+
+msgctxt "field:product.product,salable:"
+msgid "Salable"
+msgstr "vendibile"
+
+msgctxt "field:product.product,sale_price_uom:"
+msgid "Sale Price"
+msgstr ""
+
+msgctxt "field:product.product,sale_uom:"
+msgid "Sale UOM"
+msgstr "UdM di vendita"
+
+#, fuzzy
+msgctxt "field:product.sale.context,company:"
+msgid "Company"
+msgstr "Azienda"
+
+#, fuzzy
+msgctxt "field:product.sale.context,currency:"
+msgid "Currency"
+msgstr "Valuta"
+
+#, fuzzy
+msgctxt "field:product.sale.context,customer:"
+msgid "Customer"
+msgstr "Clienti"
+
+#, fuzzy
+msgctxt "field:product.sale.context,locations:"
+msgid "Warehouses"
+msgstr "Magazzino"
+
+msgctxt "field:product.sale.context,quantity:"
+msgid "Quantity"
+msgstr "Quantità"
+
+#, fuzzy
+msgctxt "field:product.sale.context,sale_date:"
+msgid "Sale Date"
+msgstr "data ordine"
+
+msgctxt "field:product.sale.context,stock_date_end:"
+msgid "Stock End Date"
+msgstr ""
+
+msgctxt "field:product.template,lead_time:"
+msgid "Lead Time"
+msgstr "lead time"
+
+msgctxt "field:product.template,salable:"
+msgid "Salable"
+msgstr "vendibile"
+
+msgctxt "field:product.template,sale_uom:"
+msgid "Sale UOM"
+msgstr "UdM di vendita"
+
+msgctxt "field:sale.configuration,sale_invoice_method:"
+msgid "Sale Invoice Method"
+msgstr "metodo di fatturazione vendita"
+
+msgctxt "field:sale.configuration,sale_process_after:"
+msgid "Process Sale after"
+msgstr ""
+
+msgctxt "field:sale.configuration,sale_sequence:"
+msgid "Sale Sequence"
+msgstr "sequenza ordine"
+
+msgctxt "field:sale.configuration,sale_shipment_method:"
+msgid "Sale Shipment Method"
+msgstr "metodo di spedizione dell'ordine"
+
+#, fuzzy
+msgctxt "field:sale.configuration.sale_method,sale_invoice_method:"
+msgid "Sale Invoice Method"
+msgstr "metodo di fatturazione vendita"
+
+#, fuzzy
+msgctxt "field:sale.configuration.sale_method,sale_shipment_method:"
+msgid "Sale Shipment Method"
+msgstr "metodo di spedizione dell'ordine"
+
+msgctxt "field:sale.configuration.sequence,company:"
+msgid "Company"
+msgstr "Azienda"
+
+#, fuzzy
+msgctxt "field:sale.configuration.sequence,sale_sequence:"
+msgid "Sale Sequence"
+msgstr "sequenza ordine"
+
+msgctxt "field:sale.handle.invoice.exception.ask,domain_invoices:"
+msgid "Domain Invoices"
+msgstr "dominio fatture"
+
+msgctxt "field:sale.handle.invoice.exception.ask,recreate_invoices:"
+msgid "Recreate Invoices"
+msgstr "ricrea fatture"
+
+msgctxt "field:sale.handle.shipment.exception.ask,domain_moves:"
+msgid "Domain Moves"
+msgstr "dominio movimenti"
+
+msgctxt "field:sale.handle.shipment.exception.ask,recreate_moves:"
+msgid "Recreate Moves"
+msgstr "ricrea movimenti"
+
+#, fuzzy
+msgctxt "field:sale.line,actual_quantity:"
+msgid "Actual Quantity"
+msgstr "Quantità"
+
+msgctxt "field:sale.line,amount:"
+msgid "Amount"
+msgstr "Importo"
+
+#, fuzzy
+msgctxt "field:sale.line,company:"
+msgid "Company"
+msgstr "Azienda"
+
+#, fuzzy
+msgctxt "field:sale.line,currency:"
+msgid "Currency"
+msgstr "Valuta"
+
+msgctxt "field:sale.line,description:"
+msgid "Description"
+msgstr "Descrizione"
+
+msgctxt "field:sale.line,from_location:"
+msgid "From Location"
+msgstr "da locazione"
+
+msgctxt "field:sale.line,invoice_lines:"
+msgid "Invoice Lines"
+msgstr "Righe fattura"
+
+msgctxt "field:sale.line,move_done:"
+msgid "Moves Done"
+msgstr "movimenti eseguiti"
+
+msgctxt "field:sale.line,move_exception:"
+msgid "Moves Exception"
+msgstr "eccezione movimenti"
+
+msgctxt "field:sale.line,moves:"
+msgid "Moves"
+msgstr "Movimenti"
+
+msgctxt "field:sale.line,moves_ignored:"
+msgid "Ignored Moves"
+msgstr "movimenti ignorati"
+
+msgctxt "field:sale.line,moves_recreated:"
+msgid "Recreated Moves"
+msgstr "movimenti ricreati"
+
+msgctxt "field:sale.line,note:"
+msgid "Note"
+msgstr "Nota"
+
+msgctxt "field:sale.line,product:"
+msgid "Product"
+msgstr "Prodotto"
+
+msgctxt "field:sale.line,product_uom_category:"
+msgid "Product Uom Category"
+msgstr "Categoria unità di misura prodotto"
+
+msgctxt "field:sale.line,quantity:"
+msgid "Quantity"
+msgstr "Quantità"
+
+msgctxt "field:sale.line,sale:"
+msgid "Sale"
+msgstr "Vendite"
+
+msgctxt "field:sale.line,sale_state:"
+msgid "Sale State"
+msgstr "stato ordine"
+
+msgctxt "field:sale.line,shipping_date:"
+msgid "Shipping Date"
+msgstr "data di spedizione"
+
+msgctxt "field:sale.line,summary:"
+msgid "Summary"
+msgstr ""
+
+msgctxt "field:sale.line,taxes:"
+msgid "Taxes"
+msgstr "Imposte"
+
+msgctxt "field:sale.line,to_location:"
+msgid "To Location"
+msgstr "a locazione"
+
+msgctxt "field:sale.line,type:"
+msgid "Type"
+msgstr "Tipo"
+
+msgctxt "field:sale.line,unit:"
+msgid "Unit"
+msgstr "Unità"
+
+msgctxt "field:sale.line,unit_digits:"
+msgid "Unit Digits"
+msgstr "Posizioni Unità"
+
+msgctxt "field:sale.line,unit_price:"
+msgid "Unit Price"
+msgstr "Prezzo unitario"
+
+msgctxt "field:sale.line,warehouse:"
+msgid "Warehouse"
+msgstr "Magazzino"
+
+msgctxt "field:sale.line-account.tax,line:"
+msgid "Sale Line"
+msgstr "riga ordine"
+
+msgctxt "field:sale.line-account.tax,tax:"
+msgid "Tax"
+msgstr "Imposta"
+
+msgctxt "field:sale.line-ignored-stock.move,move:"
+msgid "Move"
+msgstr "Movimento"
+
+msgctxt "field:sale.line-ignored-stock.move,sale_line:"
+msgid "Sale Line"
+msgstr "riga ordine"
+
+msgctxt "field:sale.line-recreated-stock.move,move:"
+msgid "Move"
+msgstr "Movimento"
+
+msgctxt "field:sale.line-recreated-stock.move,sale_line:"
+msgid "Sale Line"
+msgstr "riga ordine"
+
+msgctxt "field:sale.reporting.category,category:"
+msgid "Category"
+msgstr ""
+
+msgctxt "field:sale.reporting.category,time_series:"
+msgid "Time Series"
+msgstr ""
+
+msgctxt "field:sale.reporting.category.time_series,category:"
+msgid "Category"
+msgstr ""
+
+#, fuzzy
+msgctxt "field:sale.reporting.category.time_series,date:"
+msgid "Date"
+msgstr "Data:"
+
+msgctxt "field:sale.reporting.category.tree,children:"
+msgid "Children"
+msgstr ""
+
+#, fuzzy
+msgctxt "field:sale.reporting.category.tree,currency_digits:"
+msgid "Currency Digits"
+msgstr "posizioni valuta"
+
+msgctxt "field:sale.reporting.category.tree,name:"
+msgid "Name"
+msgstr "Nome"
+
+msgctxt "field:sale.reporting.category.tree,parent:"
+msgid "Parent"
+msgstr "Padre"
+
+msgctxt "field:sale.reporting.category.tree,revenue:"
+msgid "Revenue"
+msgstr ""
+
+msgctxt "field:sale.reporting.context,company:"
+msgid "Company"
+msgstr "Azienda"
+
+msgctxt "field:sale.reporting.context,from_date:"
+msgid "From Date"
+msgstr ""
+
+msgctxt "field:sale.reporting.context,period:"
+msgid "Period"
+msgstr ""
+
+msgctxt "field:sale.reporting.context,to_date:"
+msgid "To Date"
+msgstr ""
+
+#, fuzzy
+msgctxt "field:sale.reporting.context,warehouse:"
+msgid "Warehouse"
+msgstr "Magazzino"
+
+msgctxt "field:sale.reporting.country,country:"
+msgid "Country"
+msgstr ""
+
+msgctxt "field:sale.reporting.country,time_series:"
+msgid "Time Series"
+msgstr ""
+
+msgctxt "field:sale.reporting.country.subdivision,country:"
+msgid "Country"
+msgstr ""
+
+msgctxt "field:sale.reporting.country.subdivision,subdivision:"
+msgid "Subdivision"
+msgstr ""
+
+msgctxt "field:sale.reporting.country.subdivision,time_series:"
+msgid "Time Series"
+msgstr ""
+
+msgctxt "field:sale.reporting.country.subdivision.time_series,country:"
+msgid "Country"
+msgstr ""
+
+#, fuzzy
+msgctxt "field:sale.reporting.country.subdivision.time_series,date:"
+msgid "Date"
+msgstr "Data:"
+
+msgctxt "field:sale.reporting.country.subdivision.time_series,subdivision:"
+msgid "Subdivision"
+msgstr ""
+
+msgctxt "field:sale.reporting.country.time_series,country:"
+msgid "Country"
+msgstr ""
+
+#, fuzzy
+msgctxt "field:sale.reporting.country.time_series,date:"
+msgid "Date"
+msgstr "Data:"
+
+#, fuzzy
+msgctxt "field:sale.reporting.customer,customer:"
+msgid "Customer"
+msgstr "Clienti"
+
+msgctxt "field:sale.reporting.customer,time_series:"
+msgid "Time Series"
+msgstr ""
+
+#, fuzzy
+msgctxt "field:sale.reporting.customer.time_series,customer:"
+msgid "Customer"
+msgstr "Clienti"
+
+#, fuzzy
+msgctxt "field:sale.reporting.customer.time_series,date:"
+msgid "Date"
+msgstr "Data:"
+
+msgctxt "field:sale.reporting.product,product:"
+msgid "Product"
+msgstr "Prodotto"
+
+msgctxt "field:sale.reporting.product,time_series:"
+msgid "Time Series"
+msgstr ""
+
+#, fuzzy
+msgctxt "field:sale.reporting.product.time_series,date:"
+msgid "Date"
+msgstr "Data:"
+
+msgctxt "field:sale.reporting.product.time_series,product:"
+msgid "Product"
+msgstr "Prodotto"
+
+msgctxt "field:sale.reporting.region,children:"
+msgid "Children"
+msgstr ""
+
+msgctxt "field:sale.reporting.region,parent:"
+msgid "Parent"
+msgstr "Padre"
+
+msgctxt "field:sale.reporting.region,region:"
+msgid "Region"
+msgstr ""
+
+msgctxt "field:sale.sale,comment:"
+msgid "Comment"
+msgstr "Commento"
+
+msgctxt "field:sale.sale,company:"
+msgid "Company"
+msgstr "Azienda"
+
+#, fuzzy
+msgctxt "field:sale.sale,confirmed_by:"
+msgid "Confirmed By"
+msgstr "Confirmed"
+
+msgctxt "field:sale.sale,contact:"
+msgid "Contact"
+msgstr ""
+
+msgctxt "field:sale.sale,currency:"
+msgid "Currency"
+msgstr "Valuta"
+
+msgctxt "field:sale.sale,currency_digits:"
+msgid "Currency Digits"
+msgstr "posizioni valuta"
+
+msgctxt "field:sale.sale,description:"
+msgid "Description"
+msgstr "Descrizione"
+
+msgctxt "field:sale.sale,invoice_address:"
+msgid "Invoice Address"
+msgstr "Indirizzo di fatturazione"
+
+msgctxt "field:sale.sale,invoice_method:"
+msgid "Invoice Method"
+msgstr "metodo di fatturazione"
+
+#, fuzzy
+msgctxt "field:sale.sale,invoice_party:"
+msgid "Invoice Party"
+msgstr "stato fattura"
+
+msgctxt "field:sale.sale,invoice_state:"
+msgid "Invoice State"
+msgstr "stato fattura"
+
+msgctxt "field:sale.sale,invoices:"
+msgid "Invoices"
+msgstr "Fatture"
+
+msgctxt "field:sale.sale,invoices_ignored:"
+msgid "Ignored Invoices"
+msgstr "fatture ignorate"
+
+msgctxt "field:sale.sale,invoices_recreated:"
+msgid "Recreated Invoices"
+msgstr "fatture ricreate"
+
+msgctxt "field:sale.sale,lines:"
+msgid "Lines"
+msgstr "Righe"
+
+msgctxt "field:sale.sale,moves:"
+msgid "Moves"
+msgstr "Movimenti"
+
+msgctxt "field:sale.sale,number:"
+msgid "Number"
+msgstr "Numero"
+
+msgctxt "field:sale.sale,origin:"
+msgid "Origin"
+msgstr "Origine"
+
+msgctxt "field:sale.sale,party:"
+msgid "Party"
+msgstr "Controparte"
+
+msgctxt "field:sale.sale,party_lang:"
+msgid "Party Language"
+msgstr "Lingua Controparte"
+
+msgctxt "field:sale.sale,payment_term:"
+msgid "Payment Term"
+msgstr "Termine di pagamento"
+
+#, fuzzy
+msgctxt "field:sale.sale,quoted_by:"
+msgid "Quoted By"
+msgstr "Quote"
+
+msgctxt "field:sale.sale,reference:"
+msgid "Reference"
+msgstr "Riferimento"
+
+msgctxt "field:sale.sale,sale_date:"
+msgid "Sale Date"
+msgstr "data ordine"
+
+msgctxt "field:sale.sale,shipment_address:"
+msgid "Shipment Address"
+msgstr "indirizzo di spedizione"
+
+msgctxt "field:sale.sale,shipment_method:"
+msgid "Shipment Method"
+msgstr "metodo di spedizione"
+
+msgctxt "field:sale.sale,shipment_party:"
+msgid "Shipment Party"
+msgstr "controparte di spedizione"
+
+msgctxt "field:sale.sale,shipment_returns:"
+msgid "Shipment Returns"
+msgstr "resi di spedizione"
+
+msgctxt "field:sale.sale,shipment_state:"
+msgid "Shipment State"
+msgstr "Stato spedizione"
+
+msgctxt "field:sale.sale,shipments:"
+msgid "Shipments"
+msgstr "Spedizioni"
+
+#, fuzzy
+msgctxt "field:sale.sale,shipping_date:"
+msgid "Shipping Date"
+msgstr "data di spedizione"
+
+msgctxt "field:sale.sale,state:"
+msgid "State"
+msgstr "Stato"
+
+msgctxt "field:sale.sale,tax_amount:"
+msgid "Tax"
+msgstr "Imposta"
+
+#, fuzzy
+msgctxt "field:sale.sale,tax_amount_cache:"
+msgid "Tax Cache"
+msgstr "ripostiglio imposta"
+
+msgctxt "field:sale.sale,total_amount:"
+msgid "Total"
+msgstr "Totale"
+
+#, fuzzy
+msgctxt "field:sale.sale,total_amount_cache:"
+msgid "Total Cache"
+msgstr "ripostiglio imposta"
+
+msgctxt "field:sale.sale,untaxed_amount:"
+msgid "Untaxed"
+msgstr "Ante imposte"
+
+#, fuzzy
+msgctxt "field:sale.sale,untaxed_amount_cache:"
+msgid "Untaxed Cache"
+msgstr "ante imposte "
+
+msgctxt "field:sale.sale,warehouse:"
+msgid "Warehouse"
+msgstr "Magazzino"
+
+msgctxt "field:sale.sale-ignored-account.invoice,invoice:"
+msgid "Invoice"
+msgstr "Fattura"
+
+msgctxt "field:sale.sale-ignored-account.invoice,sale:"
+msgid "Sale"
+msgstr "Vendite"
+
+msgctxt "field:sale.sale-recreated-account.invoice,invoice:"
+msgid "Invoice"
+msgstr "Fattura"
+
+msgctxt "field:sale.sale-recreated-account.invoice,sale:"
+msgid "Sale"
+msgstr "Vendita"
+
+msgctxt "field:stock.move,sale:"
+msgid "Sale"
+msgstr "Vendita"
+
+msgctxt "field:stock.move,sale_exception_state:"
+msgid "Exception State"
+msgstr "stato eccezione"
+
+msgctxt "help:product.configuration,default_lead_time:"
+msgid ""
+"The time from confirming the sales order to sending the products.\n"
+"Used for products without a lead time."
+msgstr ""
+
+msgctxt "help:product.product,lead_time:"
+msgid ""
+"The time from confirming the sales order to sending the products.\n"
+"If empty the default lead time from the configuration is used."
+msgstr ""
+
+msgctxt "help:product.template,lead_time:"
+msgid ""
+"The time from confirming the sales order to sending the products.\n"
+"If empty the default lead time from the configuration is used."
+msgstr ""
+
+msgctxt "help:sale.configuration,sale_process_after:"
+msgid ""
+"The grace period during which confirmed sale can still be reset to draft.\n"
+"Applied if a worker queue is activated."
+msgstr ""
+
+msgctxt "help:sale.handle.invoice.exception.ask,recreate_invoices:"
+msgid ""
+"The selected invoices will be recreated. The other ones will be ignored."
+msgstr ""
+"Le fatture selezionate verranno ricreate. Le altre verranno tralasciate."
+
+msgctxt "help:sale.sale,shipping_date:"
+msgid "When the shipping of goods should start."
+msgstr ""
+
+msgctxt "model:ir.action,name:act_invoice_form"
+msgid "Invoices"
+msgstr "Fatture"
+
+#, fuzzy
+msgctxt "model:ir.action,name:act_open_customer"
+msgid "Parties associated to Sales"
+msgstr "Parties associated to Sales"
+
+#, fuzzy
+msgctxt "model:ir.action,name:act_product"
+msgid "Products"
+msgstr "Prodotto"
+
+msgctxt "model:ir.action,name:act_reporting_category"
+msgid "Sales per Category"
+msgstr "Sales per Category"
+
+msgctxt "model:ir.action,name:act_reporting_category_time_series"
+msgid "Sales per Category"
+msgstr "Sales per Category"
+
+msgctxt "model:ir.action,name:act_reporting_category_tree"
+msgid "Sales per Category"
+msgstr "Sales per Category"
+
+msgctxt "model:ir.action,name:act_reporting_country_subdivision_time_series"
+msgid "Sales per Subdivision"
+msgstr "Sales per Subdivision"
+
+msgctxt "model:ir.action,name:act_reporting_country_time_series"
+msgid "Sales per Country"
+msgstr "Sales per Country"
+
+msgctxt "model:ir.action,name:act_reporting_customer"
+msgid "Sales per Customer"
+msgstr "Sales per Customer"
+
+msgctxt "model:ir.action,name:act_reporting_customer_time_series"
+msgid "Sales per Customer"
+msgstr "Sales per Customer"
+
+msgctxt "model:ir.action,name:act_reporting_product"
+msgid "Sales per Product"
+msgstr "Sales per Product"
+
+msgctxt "model:ir.action,name:act_reporting_product_time_series"
+msgid "Sales per Product"
+msgstr "Sales per Product"
+
+msgctxt "model:ir.action,name:act_reporting_region"
+msgid "Sales per Region"
+msgstr "Sales per Region"
+
+msgctxt "model:ir.action,name:act_return_form"
+msgid "Returns"
+msgstr "Resi"
+
+#, fuzzy
+msgctxt "model:ir.action,name:act_sale_configuration_form"
+msgid "Configuration"
+msgstr "Configurazione"
+
+#, fuzzy
+msgctxt "model:ir.action,name:act_sale_form"
+msgid "Sales"
+msgstr "Sales"
+
+#, fuzzy
+msgctxt "model:ir.action,name:act_sale_form2"
+msgid "Sales"
+msgstr "Sales"
+
+#, fuzzy
+msgctxt "model:ir.action,name:act_sale_invoice_relate"
+msgid "Sales"
+msgstr "Sales"
+
+#, fuzzy
+msgctxt "model:ir.action,name:act_sale_move_relate"
+msgid "Moves"
+msgstr "Movimenti"
+
+msgctxt "model:ir.action,name:act_sale_shipment_returns_relate"
+msgid "Sales"
+msgstr "Sales"
+
+#, fuzzy
+msgctxt "model:ir.action,name:act_sale_shipments_relate"
+msgid "Sales"
+msgstr "Sales"
+
+msgctxt "model:ir.action,name:act_shipment_form"
+msgid "Shipments"
+msgstr "Spedizioni"
+
+#, fuzzy
+msgctxt "model:ir.action,name:report_sale"
+msgid "Sale"
+msgstr "Sale"
+
+#, fuzzy
+msgctxt "model:ir.action,name:wizard_invoice_handle_exception"
+msgid "Handle Invoice Exception"
+msgstr "Handle Invoice Exception"
+
+msgctxt "model:ir.action,name:wizard_modify_header"
+msgid "Modify Header"
+msgstr "Modify Header"
+
+msgctxt "model:ir.action,name:wizard_reporting_region_open"
+msgid "Open Region"
+msgstr "Open Region"
+
+#, fuzzy
+msgctxt "model:ir.action,name:wizard_return_sale"
+msgid "Return Sale"
+msgstr "Return Sale"
+
+#, fuzzy
+msgctxt "model:ir.action,name:wizard_shipment_handle_exception"
+msgid "Handle Shipment Exception"
+msgstr "Handle Shipment Exception"
+
+#, fuzzy
+msgctxt "model:ir.action.act_window.domain,name:act_sale_form_domain_all"
+msgid "All"
+msgstr "All"
+
+#, fuzzy
+msgctxt ""
+"model:ir.action.act_window.domain,name:act_sale_form_domain_confirmed"
+msgid "Confirmed"
+msgstr "Confirmed"
+
+#, fuzzy
+msgctxt "model:ir.action.act_window.domain,name:act_sale_form_domain_draft"
+msgid "Draft"
+msgstr "Draft"
+
+#, fuzzy
+msgctxt ""
+"model:ir.action.act_window.domain,name:act_sale_form_domain_exception"
+msgid "Exception"
+msgstr "Eccezione"
+
+#, fuzzy
+msgctxt ""
+"model:ir.action.act_window.domain,name:act_sale_form_domain_processing"
+msgid "Processing"
+msgstr "Processing"
+
+#, fuzzy
+msgctxt ""
+"model:ir.action.act_window.domain,name:act_sale_form_domain_quotation"
+msgid "Quotation"
+msgstr "Quotation"
+
+msgctxt "model:ir.message,text:msg_erase_party_pending_sale"
+msgid ""
+"You cannot erase party \"%(party)s\" while they have pending sales with "
+"company \"%(company)s\"."
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_sale_customer_location_required"
+msgid ""
+"To process sale \"%(sale)s\" you must set a customer location on party "
+"\"%(party)s\"."
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_sale_delete_cancel"
+msgid "To delete sale \"%(sale)s\" you must cancel it."
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_sale_invalid_method"
+msgid ""
+"You cannot use together invoice \"%(invoice_method)s\" and shipment "
+"\"%(shipment_method)s\" on sale \"%(sale)s\"."
+msgstr ""
+
+msgctxt ""
+"model:ir.message,text:msg_sale_invoice_address_required_for_quotation"
+msgid "To get a quote for sale \"%(sale)s\" you must enter an invoice address."
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_sale_invoice_reset_draft"
+msgid ""
+"You cannot reset invoice \"%(invoice)s\" to draft because it was generated "
+"by a sale."
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_sale_line_delete_cancel_draft"
+msgid ""
+"To delete line \"%(line)s\" you must cancel or reset to draft sale "
+"\"%(sale)s\"."
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_sale_missing_account_revenue"
+msgid "To invoice sale \"%(sale)s\" you must configure a default account revenue."
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_sale_modify_header_draft"
+msgid "To modify the header of sale \"%(sale)s\", it must be in \"draft\" state."
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_sale_move_reset_draft"
+msgid ""
+"You cannot reset move \"%(move)s\" to draft because it was generated by a "
+"sale."
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_sale_product_missing_account_revenue"
+msgid ""
+"To invoice sale \"%(sale)s\" you must define an account revenue for product "
+"\"%(product)s\"."
+msgstr ""
+
+#, fuzzy
+msgctxt "model:ir.message,text:msg_sale_reporting_company"
+msgid "Company"
+msgstr "Azienda"
+
+#, fuzzy
+msgctxt "model:ir.message,text:msg_sale_reporting_currency"
+msgid "Currency"
+msgstr "Valuta"
+
+#, fuzzy
+msgctxt "model:ir.message,text:msg_sale_reporting_currency_digits"
+msgid "Currency Digits"
+msgstr "posizioni valuta"
+
+#, fuzzy
+msgctxt "model:ir.message,text:msg_sale_reporting_number"
+msgid "#"
+msgstr "#"
+
+msgctxt "model:ir.message,text:msg_sale_reporting_number_help"
+msgid "Number of sales"
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_sale_reporting_revenue"
+msgid "Revenue"
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_sale_reporting_revenue_trend"
+msgid "Revenue Trend"
+msgstr ""
+
+msgctxt ""
+"model:ir.message,text:msg_sale_shipment_address_required_for_quotation"
+msgid "To get a quote for sale \"%(sale)s\" you must enter a shipment address."
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_sale_warehouse_required_for_quotation"
+msgid "To get a quote for sale \"%(sale)s\" you must enter a warehouse."
+msgstr ""
+
+msgctxt "model:ir.model.button,string:sale_cancel_button"
+msgid "Cancel"
+msgstr "Annulla"
+
+msgctxt "model:ir.model.button,string:sale_confirm_button"
+msgid "Confirm"
+msgstr "Confirm"
+
+msgctxt "model:ir.model.button,string:sale_draft_button"
+msgid "Draft"
+msgstr "Draft"
+
+msgctxt "model:ir.model.button,string:sale_handle_invoice_exception_button"
+msgid "Handle Invoice Exception"
+msgstr "Handle Invoice Exception"
+
+msgctxt "model:ir.model.button,string:sale_handle_shipment_exception_button"
+msgid "Handle Shipment Exception"
+msgstr "Handle Shipment Exception"
+
+msgctxt "model:ir.model.button,string:sale_modify_header_button"
+msgid "Modify Header"
+msgstr "Modify Header"
+
+msgctxt "model:ir.model.button,string:sale_process_button"
+msgid "Process"
+msgstr "Process"
+
+msgctxt "model:ir.model.button,string:sale_quote_button"
+msgid "Quote"
+msgstr "Quote"
+
+msgctxt "model:ir.rule.group,name:rule_group_reporting_category_companies"
+msgid "User in companies"
+msgstr ""
+
+msgctxt ""
+"model:ir.rule.group,name:rule_group_reporting_category_time_series_companies"
+msgid "User in companies"
+msgstr ""
+
+msgctxt ""
+"model:ir.rule.group,name:rule_group_reporting_country_subdivision_time_series_companies"
+msgid "User in companies"
+msgstr ""
+
+msgctxt ""
+"model:ir.rule.group,name:rule_group_reporting_country_time_series_companies"
+msgid "User in companies"
+msgstr ""
+
+msgctxt "model:ir.rule.group,name:rule_group_reporting_customer_companies"
+msgid "User in companies"
+msgstr ""
+
+msgctxt ""
+"model:ir.rule.group,name:rule_group_reporting_customer_time_series_companies"
+msgid "User in companies"
+msgstr ""
+
+msgctxt "model:ir.rule.group,name:rule_group_reporting_product_companies"
+msgid "User in companies"
+msgstr ""
+
+msgctxt ""
+"model:ir.rule.group,name:rule_group_reporting_product_time_series_companies"
+msgid "User in companies"
+msgstr ""
+
+msgctxt "model:ir.rule.group,name:rule_group_reporting_region_companies"
+msgid "User in companies"
+msgstr ""
+
+msgctxt "model:ir.rule.group,name:rule_group_sale_companies"
+msgid "User in companies"
+msgstr ""
+
+#, fuzzy
+msgctxt "model:ir.sequence,name:sequence_sale"
+msgid "Sale"
+msgstr "Sale"
+
+#, fuzzy
+msgctxt "model:ir.sequence.type,name:sequence_type_sale"
+msgid "Sale"
+msgstr "Sale"
+
+msgctxt "model:ir.ui.menu,name:menu_configuration"
+msgid "Configuration"
+msgstr "Configurazione"
+
+#, fuzzy
+msgctxt "model:ir.ui.menu,name:menu_customer"
+msgid "Associated to Sales"
+msgstr "Parties associated to Sales"
+
+#, fuzzy
+msgctxt "model:ir.ui.menu,name:menu_product"
+msgid "Products"
+msgstr "Prodotto"
+
+msgctxt "model:ir.ui.menu,name:menu_reporting"
+msgid "Reporting"
+msgstr "Reporting"
+
+msgctxt "model:ir.ui.menu,name:menu_reporting_sale"
+msgid "Sales"
+msgstr "Sales"
+
+#, fuzzy
+msgctxt "model:ir.ui.menu,name:menu_sale"
+msgid "Sales"
+msgstr "Sales"
+
+#, fuzzy
+msgctxt "model:ir.ui.menu,name:menu_sale_configuration"
+msgid "Configuration"
+msgstr "Configurazione"
+
+#, fuzzy
+msgctxt "model:ir.ui.menu,name:menu_sale_form"
+msgid "Sales"
+msgstr "Sales"
+
+msgctxt "model:product.configuration.default_lead_time,name:"
+msgid "Product Default Lead Time"
+msgstr ""
+
+msgctxt "model:product.sale.context,name:"
+msgid "Product Sale Context"
+msgstr ""
+
+#, fuzzy
+msgctxt "model:res.group,name:group_sale"
+msgid "Sales"
+msgstr "Sales"
+
+#, fuzzy
+msgctxt "model:res.group,name:group_sale_admin"
+msgid "Sales Administrator"
+msgstr "Sales Administrator"
+
+msgctxt "model:sale.configuration,name:"
+msgid "Sale Configuration"
+msgstr "Configurazione vendita"
+
+msgctxt "model:sale.configuration.sale_method,name:"
+msgid "Sale Configuration Sale Method"
+msgstr ""
+
+msgctxt "model:sale.configuration.sequence,name:"
+msgid "Sale Configuration Sequence"
+msgstr ""
+
+msgctxt "model:sale.handle.invoice.exception.ask,name:"
+msgid "Handle Invoice Exception"
+msgstr "gestione dell'eccezione in fattura"
+
+msgctxt "model:sale.handle.shipment.exception.ask,name:"
+msgid "Handle Shipment Exception"
+msgstr "gestione dell'eccezione di spedizione"
+
+msgctxt "model:sale.line,name:"
+msgid "Sale Line"
+msgstr "riga ordine"
+
+msgctxt "model:sale.line-account.tax,name:"
+msgid "Sale Line - Tax"
+msgstr "riga ordine - imposta"
+
+msgctxt "model:sale.line-ignored-stock.move,name:"
+msgid "Sale Line - Ignored Move"
+msgstr "Riga ordine - movimento non considerato"
+
+msgctxt "model:sale.line-recreated-stock.move,name:"
+msgid "Sale Line - Recreated Move"
+msgstr "riga ordine - movimento ricreato"
+
+msgctxt "model:sale.reporting.category,name:"
+msgid "Sale Reporting per Category"
+msgstr ""
+
+msgctxt "model:sale.reporting.category.time_series,name:"
+msgid "Sale Reporting per Category"
+msgstr ""
+
+msgctxt "model:sale.reporting.category.tree,name:"
+msgid "Sale Reporting per Category"
+msgstr ""
+
+msgctxt "model:sale.reporting.context,name:"
+msgid "Sale Reporting Context"
+msgstr ""
+
+msgctxt "model:sale.reporting.country,name:"
+msgid "Sale Reporting per Country"
+msgstr ""
+
+msgctxt "model:sale.reporting.country.subdivision,name:"
+msgid "Sale Reporting per Subdivision"
+msgstr ""
+
+msgctxt "model:sale.reporting.country.subdivision.time_series,name:"
+msgid "Sale Reporting per Subdivision"
+msgstr ""
+
+msgctxt "model:sale.reporting.country.time_series,name:"
+msgid "Sale Reporting per Country"
+msgstr ""
+
+msgctxt "model:sale.reporting.customer,name:"
+msgid "Sale Reporting per Customer"
+msgstr ""
+
+msgctxt "model:sale.reporting.customer.time_series,name:"
+msgid "Sale Reporting per Customer"
+msgstr ""
+
+msgctxt "model:sale.reporting.product,name:"
+msgid "Sale Reporting per Product"
+msgstr ""
+
+msgctxt "model:sale.reporting.product.time_series,name:"
+msgid "Sale Reporting per Product"
+msgstr ""
+
+msgctxt "model:sale.reporting.region,name:"
+msgid "Sale Reporting per Region"
+msgstr ""
+
+msgctxt "model:sale.return_sale.start,name:"
+msgid "Return Sale"
+msgstr "reso vendita"
+
+msgctxt "model:sale.sale,name:"
+msgid "Sale"
+msgstr "Vendita"
+
+msgctxt "model:sale.sale-ignored-account.invoice,name:"
+msgid "Sale - Ignored Invoice"
+msgstr "Vendita - fattura non considerata"
+
+msgctxt "model:sale.sale-recreated-account.invoice,name:"
+msgid "Sale - Recreated Invoice"
+msgstr "Vendita - fattura ricreata"
+
+msgctxt "report:sale.sale:"
+msgid ":"
+msgstr ":"
+
+msgctxt "report:sale.sale:"
+msgid "Amount"
+msgstr "Importo"
+
+msgctxt "report:sale.sale:"
+msgid "Date:"
+msgstr "Data:"
+
+msgctxt "report:sale.sale:"
+msgid "Description"
+msgstr "Descrizione"
+
+msgctxt "report:sale.sale:"
+msgid "Description:"
+msgstr "Descrizione:"
+
+msgctxt "report:sale.sale:"
+msgid "Draft Sale Order"
+msgstr "Bozza ordine di vendita"
+
+msgctxt "report:sale.sale:"
+msgid "Quantity"
+msgstr "Quantità"
+
+msgctxt "report:sale.sale:"
+msgid "Quotation N°:"
+msgstr "Preventivo N°:"
+
+msgctxt "report:sale.sale:"
+msgid "Reference:"
+msgstr "Riferimento:"
+
+msgctxt "report:sale.sale:"
+msgid "Sale Order N°:"
+msgstr "Ordine di vendita n."
+
+msgctxt "report:sale.sale:"
+msgid "Taxes"
+msgstr "Imposte"
+
+msgctxt "report:sale.sale:"
+msgid "Taxes:"
+msgstr "Imposte:"
+
+msgctxt "report:sale.sale:"
+msgid "Total (excl. taxes):"
+msgstr "Totale (escluse tasse):"
+
+msgctxt "report:sale.sale:"
+msgid "Total:"
+msgstr "Totale:"
+
+msgctxt "report:sale.sale:"
+msgid "Unit Price"
+msgstr "Prezzo unitario"
+
+msgctxt "selection:account.invoice,sale_exception_state:"
+msgid "Ignored"
+msgstr "non considerati"
+
+msgctxt "selection:account.invoice,sale_exception_state:"
+msgid "Recreated"
+msgstr "Ricreati"
+
+msgctxt "selection:sale.line,type:"
+msgid "Comment"
+msgstr "Commento"
+
+msgctxt "selection:sale.line,type:"
+msgid "Line"
+msgstr "Riga"
+
+msgctxt "selection:sale.line,type:"
+msgid "Subtotal"
+msgstr "Subtotale"
+
+msgctxt "selection:sale.line,type:"
+msgid "Title"
+msgstr "Titolo"
+
+msgctxt "selection:sale.reporting.context,period:"
+msgid "Day"
+msgstr ""
+
+msgctxt "selection:sale.reporting.context,period:"
+msgid "Month"
+msgstr ""
+
+msgctxt "selection:sale.reporting.context,period:"
+msgid "Year"
+msgstr ""
+
+msgctxt "selection:sale.sale,invoice_method:"
+msgid "Manual"
+msgstr "Manuale"
+
+msgctxt "selection:sale.sale,invoice_method:"
+msgid "On Order Processed"
+msgstr "Su ordine processato"
+
+msgctxt "selection:sale.sale,invoice_method:"
+msgid "On Shipment Sent"
+msgstr "Su spedizione"
+
+msgctxt "selection:sale.sale,invoice_state:"
+msgid "Exception"
+msgstr "Eccezione"
+
+msgctxt "selection:sale.sale,invoice_state:"
+msgid "None"
+msgstr "Nessuno"
+
+msgctxt "selection:sale.sale,invoice_state:"
+msgid "Paid"
+msgstr "Pagato"
+
+msgctxt "selection:sale.sale,invoice_state:"
+msgid "Waiting"
+msgstr "In attesa"
+
+msgctxt "selection:sale.sale,shipment_method:"
+msgid "Manual"
+msgstr "Manuale"
+
+msgctxt "selection:sale.sale,shipment_method:"
+msgid "On Invoice Paid"
+msgstr "Su fattura pagata"
+
+msgctxt "selection:sale.sale,shipment_method:"
+msgid "On Order Processed"
+msgstr "Su ordine processato"
+
+msgctxt "selection:sale.sale,shipment_state:"
+msgid "Exception"
+msgstr "Eccezione"
+
+msgctxt "selection:sale.sale,shipment_state:"
+msgid "None"
+msgstr "Nessuno"
+
+msgctxt "selection:sale.sale,shipment_state:"
+msgid "Sent"
+msgstr "Inviato"
+
+msgctxt "selection:sale.sale,shipment_state:"
+msgid "Waiting"
+msgstr "In attesa"
+
+#, fuzzy
+msgctxt "selection:sale.sale,state:"
+msgid "Cancelled"
+msgstr "Annullato"
+
+msgctxt "selection:sale.sale,state:"
+msgid "Confirmed"
+msgstr "Confermato"
+
+msgctxt "selection:sale.sale,state:"
+msgid "Done"
+msgstr "Eseguito"
+
+msgctxt "selection:sale.sale,state:"
+msgid "Draft"
+msgstr "Bozza"
+
+msgctxt "selection:sale.sale,state:"
+msgid "Processing"
+msgstr "In esecuzione"
+
+msgctxt "selection:sale.sale,state:"
+msgid "Quotation"
+msgstr "Preventivo"
+
+msgctxt "selection:stock.move,sale_exception_state:"
+msgid "Ignored"
+msgstr "Non considerati"
+
+msgctxt "selection:stock.move,sale_exception_state:"
+msgid "Recreated"
+msgstr "Ricreati"
+
+msgctxt "view:party.party:"
+msgid "Sale"
+msgstr "Vendita"
+
+msgctxt "view:product.template:"
+msgid "Customers"
+msgstr "Clienti"
+
+#, fuzzy
+msgctxt "view:sale.handle.invoice.exception.ask:"
+msgid "Choose invoices to recreate:"
+msgstr "Selezionare le fatture da ricreare"
+
+#, fuzzy
+msgctxt "view:sale.handle.shipment.exception.ask:"
+msgid "Choose move to recreate:"
+msgstr "Selezionare i movimenti da ricreare"
+
+msgctxt "view:sale.line:"
+msgid "General"
+msgstr "Generale"
+
+msgctxt "view:sale.line:"
+msgid "Notes"
+msgstr "Note"
+
+msgctxt "view:sale.line:"
+msgid "Taxes"
+msgstr "Imposte"
+
+#, fuzzy
+msgctxt "view:sale.return_sale.start:"
+msgid "Are you sure to return these/this sale(s)?"
+msgstr "Confermi il reso su queste/questa vendite/a?"
+
+msgctxt "view:sale.sale:"
+msgid "Other Info"
+msgstr "Altre informazioni"
+
+msgctxt "view:sale.sale:"
+msgid "Sale"
+msgstr "Vendita"
+
+msgctxt "wizard_button:sale.handle.invoice.exception,ask,end:"
+msgid "Cancel"
+msgstr "Annulla"
+
+msgctxt "wizard_button:sale.handle.invoice.exception,ask,handle:"
+msgid "OK"
+msgstr "OK"
+
+msgctxt "wizard_button:sale.handle.shipment.exception,ask,end:"
+msgid "Cancel"
+msgstr "Annulla"
+
+msgctxt "wizard_button:sale.handle.shipment.exception,ask,handle:"
+msgid "OK"
+msgstr "OK"
+
+msgctxt "wizard_button:sale.modify_header,start,end:"
+msgid "Cancel"
+msgstr "Annulla"
+
+msgctxt "wizard_button:sale.modify_header,start,modify:"
+msgid "Modify"
+msgstr ""
+
+msgctxt "wizard_button:sale.return_sale,start,end:"
+msgid "Cancel"
+msgstr "Annulla"
+
+msgctxt "wizard_button:sale.return_sale,start,return_:"
+msgid "Return"
+msgstr "Reso"
diff --git a/modules/sale/locale/lo.po b/modules/sale/locale/lo.po
new file mode 100644
index 0000000000..a5dedcbb0a
--- /dev/null
+++ b/modules/sale/locale/lo.po
@@ -0,0 +1,1483 @@
+#
+msgid ""
+msgstr "Content-Type: text/plain; charset=utf-8\n"
+
+#, fuzzy
+msgctxt "field:account.invoice,sale_exception_state:"
+msgid "Exception State"
+msgstr "ສະຖານະຍົກເວັ້ນ"
+
+#, fuzzy
+msgctxt "field:account.invoice,sales:"
+msgid "Sales"
+msgstr "ຂາຍ"
+
+msgctxt "field:product.configuration,default_lead_time:"
+msgid "Default Lead Time"
+msgstr ""
+
+#, fuzzy
+msgctxt "field:product.configuration.default_lead_time,company:"
+msgid "Company"
+msgstr "ຫ້ອງການ/ສຳນັກງານ"
+
+msgctxt "field:product.configuration.default_lead_time,default_lead_time:"
+msgid "Default Lead Time"
+msgstr ""
+
+msgctxt "field:product.product,lead_time:"
+msgid "Lead Time"
+msgstr ""
+
+msgctxt "field:product.product,salable:"
+msgid "Salable"
+msgstr ""
+
+msgctxt "field:product.product,sale_price_uom:"
+msgid "Sale Price"
+msgstr ""
+
+msgctxt "field:product.product,sale_uom:"
+msgid "Sale UOM"
+msgstr ""
+
+#, fuzzy
+msgctxt "field:product.sale.context,company:"
+msgid "Company"
+msgstr "ຫ້ອງການ/ສຳນັກງານ"
+
+#, fuzzy
+msgctxt "field:product.sale.context,currency:"
+msgid "Currency"
+msgstr "ສະກຸນເງິນ"
+
+#, fuzzy
+msgctxt "field:product.sale.context,customer:"
+msgid "Customer"
+msgstr "Sales per Customer"
+
+msgctxt "field:product.sale.context,locations:"
+msgid "Warehouses"
+msgstr ""
+
+#, fuzzy
+msgctxt "field:product.sale.context,quantity:"
+msgid "Quantity"
+msgstr "ຈຳນວນ"
+
+#, fuzzy
+msgctxt "field:product.sale.context,sale_date:"
+msgid "Sale Date"
+msgstr "ວັນທີບັນທຶກ"
+
+msgctxt "field:product.sale.context,stock_date_end:"
+msgid "Stock End Date"
+msgstr ""
+
+msgctxt "field:product.template,lead_time:"
+msgid "Lead Time"
+msgstr ""
+
+msgctxt "field:product.template,salable:"
+msgid "Salable"
+msgstr ""
+
+msgctxt "field:product.template,sale_uom:"
+msgid "Sale UOM"
+msgstr ""
+
+msgctxt "field:sale.configuration,sale_invoice_method:"
+msgid "Sale Invoice Method"
+msgstr ""
+
+msgctxt "field:sale.configuration,sale_process_after:"
+msgid "Process Sale after"
+msgstr ""
+
+msgctxt "field:sale.configuration,sale_sequence:"
+msgid "Sale Sequence"
+msgstr ""
+
+msgctxt "field:sale.configuration,sale_shipment_method:"
+msgid "Sale Shipment Method"
+msgstr ""
+
+msgctxt "field:sale.configuration.sale_method,sale_invoice_method:"
+msgid "Sale Invoice Method"
+msgstr ""
+
+msgctxt "field:sale.configuration.sale_method,sale_shipment_method:"
+msgid "Sale Shipment Method"
+msgstr ""
+
+#, fuzzy
+msgctxt "field:sale.configuration.sequence,company:"
+msgid "Company"
+msgstr "ຫ້ອງການ/ສຳນັກງານ"
+
+msgctxt "field:sale.configuration.sequence,sale_sequence:"
+msgid "Sale Sequence"
+msgstr ""
+
+msgctxt "field:sale.handle.invoice.exception.ask,domain_invoices:"
+msgid "Domain Invoices"
+msgstr ""
+
+msgctxt "field:sale.handle.invoice.exception.ask,recreate_invoices:"
+msgid "Recreate Invoices"
+msgstr ""
+
+msgctxt "field:sale.handle.shipment.exception.ask,domain_moves:"
+msgid "Domain Moves"
+msgstr ""
+
+msgctxt "field:sale.handle.shipment.exception.ask,recreate_moves:"
+msgid "Recreate Moves"
+msgstr ""
+
+#, fuzzy
+msgctxt "field:sale.line,actual_quantity:"
+msgid "Actual Quantity"
+msgstr "ຈຳນວນ"
+
+#, fuzzy
+msgctxt "field:sale.line,amount:"
+msgid "Amount"
+msgstr "ມູນຄ່າ"
+
+#, fuzzy
+msgctxt "field:sale.line,company:"
+msgid "Company"
+msgstr "ຫ້ອງການ/ສຳນັກງານ"
+
+#, fuzzy
+msgctxt "field:sale.line,currency:"
+msgid "Currency"
+msgstr "ສະກຸນເງິນ"
+
+#, fuzzy
+msgctxt "field:sale.line,description:"
+msgid "Description"
+msgstr "ເນື້ອໃນລາຍການ"
+
+msgctxt "field:sale.line,from_location:"
+msgid "From Location"
+msgstr ""
+
+#, fuzzy
+msgctxt "field:sale.line,invoice_lines:"
+msgid "Invoice Lines"
+msgstr "ລາຍການເກັບເງິນ"
+
+msgctxt "field:sale.line,move_done:"
+msgid "Moves Done"
+msgstr ""
+
+msgctxt "field:sale.line,move_exception:"
+msgid "Moves Exception"
+msgstr ""
+
+#, fuzzy
+msgctxt "field:sale.line,moves:"
+msgid "Moves"
+msgstr "ຕັດບັນຊີສາງ"
+
+msgctxt "field:sale.line,moves_ignored:"
+msgid "Ignored Moves"
+msgstr ""
+
+msgctxt "field:sale.line,moves_recreated:"
+msgid "Recreated Moves"
+msgstr ""
+
+#, fuzzy
+msgctxt "field:sale.line,note:"
+msgid "Note"
+msgstr "ໝາຍເຫດ"
+
+#, fuzzy
+msgctxt "field:sale.line,product:"
+msgid "Product"
+msgstr "ຜະລິດຕະພັນ"
+
+msgctxt "field:sale.line,product_uom_category:"
+msgid "Product Uom Category"
+msgstr ""
+
+#, fuzzy
+msgctxt "field:sale.line,quantity:"
+msgid "Quantity"
+msgstr "ຈຳນວນ"
+
+#, fuzzy
+msgctxt "field:sale.line,sale:"
+msgid "Sale"
+msgstr "ຂາຍ"
+
+msgctxt "field:sale.line,sale_state:"
+msgid "Sale State"
+msgstr ""
+
+msgctxt "field:sale.line,shipping_date:"
+msgid "Shipping Date"
+msgstr ""
+
+msgctxt "field:sale.line,summary:"
+msgid "Summary"
+msgstr ""
+
+#, fuzzy
+msgctxt "field:sale.line,taxes:"
+msgid "Taxes"
+msgstr "ອາກອນ"
+
+msgctxt "field:sale.line,to_location:"
+msgid "To Location"
+msgstr ""
+
+#, fuzzy
+msgctxt "field:sale.line,type:"
+msgid "Type"
+msgstr "ຮູບແບບ"
+
+#, fuzzy
+msgctxt "field:sale.line,unit:"
+msgid "Unit"
+msgstr "ໜ່ວຍ"
+
+#, fuzzy
+msgctxt "field:sale.line,unit_digits:"
+msgid "Unit Digits"
+msgstr "ຫົວໜ່ວຍເສດ"
+
+#, fuzzy
+msgctxt "field:sale.line,unit_price:"
+msgid "Unit Price"
+msgstr "ລາຄາຫົວໜ່ວຍ"
+
+msgctxt "field:sale.line,warehouse:"
+msgid "Warehouse"
+msgstr ""
+
+msgctxt "field:sale.line-account.tax,line:"
+msgid "Sale Line"
+msgstr ""
+
+#, fuzzy
+msgctxt "field:sale.line-account.tax,tax:"
+msgid "Tax"
+msgstr "ອາກອນ"
+
+#, fuzzy
+msgctxt "field:sale.line-ignored-stock.move,move:"
+msgid "Move"
+msgstr "ເຄື່ອນໄຫວ"
+
+msgctxt "field:sale.line-ignored-stock.move,sale_line:"
+msgid "Sale Line"
+msgstr ""
+
+#, fuzzy
+msgctxt "field:sale.line-recreated-stock.move,move:"
+msgid "Move"
+msgstr "ເຄື່ອນໄຫວ"
+
+msgctxt "field:sale.line-recreated-stock.move,sale_line:"
+msgid "Sale Line"
+msgstr ""
+
+msgctxt "field:sale.reporting.category,category:"
+msgid "Category"
+msgstr ""
+
+msgctxt "field:sale.reporting.category,time_series:"
+msgid "Time Series"
+msgstr ""
+
+msgctxt "field:sale.reporting.category.time_series,category:"
+msgid "Category"
+msgstr ""
+
+#, fuzzy
+msgctxt "field:sale.reporting.category.time_series,date:"
+msgid "Date"
+msgstr "ວັນທີ:"
+
+msgctxt "field:sale.reporting.category.tree,children:"
+msgid "Children"
+msgstr ""
+
+#, fuzzy
+msgctxt "field:sale.reporting.category.tree,currency_digits:"
+msgid "Currency Digits"
+msgstr "ໂຕເລກສະກຸນເງິນ"
+
+#, fuzzy
+msgctxt "field:sale.reporting.category.tree,name:"
+msgid "Name"
+msgstr "ຊື່"
+
+msgctxt "field:sale.reporting.category.tree,parent:"
+msgid "Parent"
+msgstr ""
+
+msgctxt "field:sale.reporting.category.tree,revenue:"
+msgid "Revenue"
+msgstr ""
+
+#, fuzzy
+msgctxt "field:sale.reporting.context,company:"
+msgid "Company"
+msgstr "ຫ້ອງການ/ສຳນັກງານ"
+
+msgctxt "field:sale.reporting.context,from_date:"
+msgid "From Date"
+msgstr ""
+
+msgctxt "field:sale.reporting.context,period:"
+msgid "Period"
+msgstr ""
+
+msgctxt "field:sale.reporting.context,to_date:"
+msgid "To Date"
+msgstr ""
+
+msgctxt "field:sale.reporting.context,warehouse:"
+msgid "Warehouse"
+msgstr ""
+
+msgctxt "field:sale.reporting.country,country:"
+msgid "Country"
+msgstr ""
+
+msgctxt "field:sale.reporting.country,time_series:"
+msgid "Time Series"
+msgstr ""
+
+msgctxt "field:sale.reporting.country.subdivision,country:"
+msgid "Country"
+msgstr ""
+
+msgctxt "field:sale.reporting.country.subdivision,subdivision:"
+msgid "Subdivision"
+msgstr ""
+
+msgctxt "field:sale.reporting.country.subdivision,time_series:"
+msgid "Time Series"
+msgstr ""
+
+msgctxt "field:sale.reporting.country.subdivision.time_series,country:"
+msgid "Country"
+msgstr ""
+
+#, fuzzy
+msgctxt "field:sale.reporting.country.subdivision.time_series,date:"
+msgid "Date"
+msgstr "ວັນທີ:"
+
+msgctxt "field:sale.reporting.country.subdivision.time_series,subdivision:"
+msgid "Subdivision"
+msgstr ""
+
+msgctxt "field:sale.reporting.country.time_series,country:"
+msgid "Country"
+msgstr ""
+
+#, fuzzy
+msgctxt "field:sale.reporting.country.time_series,date:"
+msgid "Date"
+msgstr "ວັນທີ:"
+
+msgctxt "field:sale.reporting.customer,customer:"
+msgid "Customer"
+msgstr ""
+
+msgctxt "field:sale.reporting.customer,time_series:"
+msgid "Time Series"
+msgstr ""
+
+msgctxt "field:sale.reporting.customer.time_series,customer:"
+msgid "Customer"
+msgstr ""
+
+#, fuzzy
+msgctxt "field:sale.reporting.customer.time_series,date:"
+msgid "Date"
+msgstr "ວັນທີ:"
+
+#, fuzzy
+msgctxt "field:sale.reporting.product,product:"
+msgid "Product"
+msgstr "ຜະລິດຕະພັນ"
+
+msgctxt "field:sale.reporting.product,time_series:"
+msgid "Time Series"
+msgstr ""
+
+#, fuzzy
+msgctxt "field:sale.reporting.product.time_series,date:"
+msgid "Date"
+msgstr "ວັນທີ:"
+
+#, fuzzy
+msgctxt "field:sale.reporting.product.time_series,product:"
+msgid "Product"
+msgstr "ຜະລິດຕະພັນ"
+
+msgctxt "field:sale.reporting.region,children:"
+msgid "Children"
+msgstr ""
+
+msgctxt "field:sale.reporting.region,parent:"
+msgid "Parent"
+msgstr ""
+
+msgctxt "field:sale.reporting.region,region:"
+msgid "Region"
+msgstr ""
+
+#, fuzzy
+msgctxt "field:sale.sale,comment:"
+msgid "Comment"
+msgstr "ຄໍາເຫັນ"
+
+#, fuzzy
+msgctxt "field:sale.sale,company:"
+msgid "Company"
+msgstr "ຫ້ອງການ/ສຳນັກງານ"
+
+#, fuzzy
+msgctxt "field:sale.sale,confirmed_by:"
+msgid "Confirmed By"
+msgstr "Confirmed"
+
+msgctxt "field:sale.sale,contact:"
+msgid "Contact"
+msgstr ""
+
+#, fuzzy
+msgctxt "field:sale.sale,currency:"
+msgid "Currency"
+msgstr "ສະກຸນເງິນ"
+
+#, fuzzy
+msgctxt "field:sale.sale,currency_digits:"
+msgid "Currency Digits"
+msgstr "ໂຕເລກສະກຸນເງິນ"
+
+#, fuzzy
+msgctxt "field:sale.sale,description:"
+msgid "Description"
+msgstr "ເນື້ອໃນລາຍການ"
+
+#, fuzzy
+msgctxt "field:sale.sale,invoice_address:"
+msgid "Invoice Address"
+msgstr "ທີ່ຢູ່"
+
+msgctxt "field:sale.sale,invoice_method:"
+msgid "Invoice Method"
+msgstr ""
+
+#, fuzzy
+msgctxt "field:sale.sale,invoice_party:"
+msgid "Invoice Party"
+msgstr "ໃບເກັບເງິນພາສີທີ່ດິນ"
+
+msgctxt "field:sale.sale,invoice_state:"
+msgid "Invoice State"
+msgstr ""
+
+#, fuzzy
+msgctxt "field:sale.sale,invoices:"
+msgid "Invoices"
+msgstr "ໃບເກັບເງິນ"
+
+msgctxt "field:sale.sale,invoices_ignored:"
+msgid "Ignored Invoices"
+msgstr ""
+
+msgctxt "field:sale.sale,invoices_recreated:"
+msgid "Recreated Invoices"
+msgstr ""
+
+#, fuzzy
+msgctxt "field:sale.sale,lines:"
+msgid "Lines"
+msgstr "ຮ່ວງ"
+
+#, fuzzy
+msgctxt "field:sale.sale,moves:"
+msgid "Moves"
+msgstr "ຕັດບັນຊີສາງ"
+
+#, fuzzy
+msgctxt "field:sale.sale,number:"
+msgid "Number"
+msgstr "ເລກທີ"
+
+#, fuzzy
+msgctxt "field:sale.sale,origin:"
+msgid "Origin"
+msgstr "ລາຍການຂັ້ນຕົ້ນ"
+
+#, fuzzy
+msgctxt "field:sale.sale,party:"
+msgid "Party"
+msgstr "ພາກສ່ວນ"
+
+#, fuzzy
+msgctxt "field:sale.sale,party_lang:"
+msgid "Party Language"
+msgstr "ພາສາ"
+
+#, fuzzy
+msgctxt "field:sale.sale,payment_term:"
+msgid "Payment Term"
+msgstr "ໄລຍະຊໍາລະ"
+
+#, fuzzy
+msgctxt "field:sale.sale,quoted_by:"
+msgid "Quoted By"
+msgstr "Quote"
+
+#, fuzzy
+msgctxt "field:sale.sale,reference:"
+msgid "Reference"
+msgstr "ເອກະສານອ້າງອີງ"
+
+msgctxt "field:sale.sale,sale_date:"
+msgid "Sale Date"
+msgstr ""
+
+msgctxt "field:sale.sale,shipment_address:"
+msgid "Shipment Address"
+msgstr ""
+
+msgctxt "field:sale.sale,shipment_method:"
+msgid "Shipment Method"
+msgstr ""
+
+msgctxt "field:sale.sale,shipment_party:"
+msgid "Shipment Party"
+msgstr ""
+
+msgctxt "field:sale.sale,shipment_returns:"
+msgid "Shipment Returns"
+msgstr ""
+
+msgctxt "field:sale.sale,shipment_state:"
+msgid "Shipment State"
+msgstr ""
+
+#, fuzzy
+msgctxt "field:sale.sale,shipments:"
+msgid "Shipments"
+msgstr "Shipments"
+
+msgctxt "field:sale.sale,shipping_date:"
+msgid "Shipping Date"
+msgstr ""
+
+#, fuzzy
+msgctxt "field:sale.sale,state:"
+msgid "State"
+msgstr "ສະຖານະ"
+
+#, fuzzy
+msgctxt "field:sale.sale,tax_amount:"
+msgid "Tax"
+msgstr "ອາກອນ"
+
+msgctxt "field:sale.sale,tax_amount_cache:"
+msgid "Tax Cache"
+msgstr ""
+
+#, fuzzy
+msgctxt "field:sale.sale,total_amount:"
+msgid "Total"
+msgstr "ລວມທັງໝົດ"
+
+#, fuzzy
+msgctxt "field:sale.sale,total_amount_cache:"
+msgid "Total Cache"
+msgstr "ລວມທັງໝົດ"
+
+#, fuzzy
+msgctxt "field:sale.sale,untaxed_amount:"
+msgid "Untaxed"
+msgstr "ມູນຄ່າບໍ່ລວມອາກອນ"
+
+msgctxt "field:sale.sale,untaxed_amount_cache:"
+msgid "Untaxed Cache"
+msgstr ""
+
+msgctxt "field:sale.sale,warehouse:"
+msgid "Warehouse"
+msgstr ""
+
+#, fuzzy
+msgctxt "field:sale.sale-ignored-account.invoice,invoice:"
+msgid "Invoice"
+msgstr "ໃບເກັບເງິນພາສີທີ່ດິນ"
+
+#, fuzzy
+msgctxt "field:sale.sale-ignored-account.invoice,sale:"
+msgid "Sale"
+msgstr "ຂາຍ"
+
+#, fuzzy
+msgctxt "field:sale.sale-recreated-account.invoice,invoice:"
+msgid "Invoice"
+msgstr "ໃບເກັບເງິນພາສີທີ່ດິນ"
+
+#, fuzzy
+msgctxt "field:sale.sale-recreated-account.invoice,sale:"
+msgid "Sale"
+msgstr "ຂາຍ"
+
+#, fuzzy
+msgctxt "field:stock.move,sale:"
+msgid "Sale"
+msgstr "ຂາຍ"
+
+#, fuzzy
+msgctxt "field:stock.move,sale_exception_state:"
+msgid "Exception State"
+msgstr "ສະຖານະຍົກເວັ້ນ"
+
+msgctxt "help:product.configuration,default_lead_time:"
+msgid ""
+"The time from confirming the sales order to sending the products.\n"
+"Used for products without a lead time."
+msgstr ""
+
+msgctxt "help:product.product,lead_time:"
+msgid ""
+"The time from confirming the sales order to sending the products.\n"
+"If empty the default lead time from the configuration is used."
+msgstr ""
+
+msgctxt "help:product.template,lead_time:"
+msgid ""
+"The time from confirming the sales order to sending the products.\n"
+"If empty the default lead time from the configuration is used."
+msgstr ""
+
+msgctxt "help:sale.configuration,sale_process_after:"
+msgid ""
+"The grace period during which confirmed sale can still be reset to draft.\n"
+"Applied if a worker queue is activated."
+msgstr ""
+
+msgctxt "help:sale.handle.invoice.exception.ask,recreate_invoices:"
+msgid ""
+"The selected invoices will be recreated. The other ones will be ignored."
+msgstr ""
+
+msgctxt "help:sale.sale,shipping_date:"
+msgid "When the shipping of goods should start."
+msgstr ""
+
+#, fuzzy
+msgctxt "model:ir.action,name:act_invoice_form"
+msgid "Invoices"
+msgstr "ໃບເກັບເງິນ"
+
+msgctxt "model:ir.action,name:act_open_customer"
+msgid "Parties associated to Sales"
+msgstr "Parties associated to Sales"
+
+#, fuzzy
+msgctxt "model:ir.action,name:act_product"
+msgid "Products"
+msgstr "ຜະລິດຕະພັນ"
+
+msgctxt "model:ir.action,name:act_reporting_category"
+msgid "Sales per Category"
+msgstr "Sales per Category"
+
+msgctxt "model:ir.action,name:act_reporting_category_time_series"
+msgid "Sales per Category"
+msgstr "Sales per Category"
+
+msgctxt "model:ir.action,name:act_reporting_category_tree"
+msgid "Sales per Category"
+msgstr "Sales per Category"
+
+msgctxt "model:ir.action,name:act_reporting_country_subdivision_time_series"
+msgid "Sales per Subdivision"
+msgstr "Sales per Subdivision"
+
+msgctxt "model:ir.action,name:act_reporting_country_time_series"
+msgid "Sales per Country"
+msgstr "Sales per Country"
+
+msgctxt "model:ir.action,name:act_reporting_customer"
+msgid "Sales per Customer"
+msgstr "Sales per Customer"
+
+msgctxt "model:ir.action,name:act_reporting_customer_time_series"
+msgid "Sales per Customer"
+msgstr "Sales per Customer"
+
+msgctxt "model:ir.action,name:act_reporting_product"
+msgid "Sales per Product"
+msgstr "Sales per Product"
+
+msgctxt "model:ir.action,name:act_reporting_product_time_series"
+msgid "Sales per Product"
+msgstr "Sales per Product"
+
+msgctxt "model:ir.action,name:act_reporting_region"
+msgid "Sales per Region"
+msgstr "Sales per Region"
+
+msgctxt "model:ir.action,name:act_return_form"
+msgid "Returns"
+msgstr "Returns"
+
+#, fuzzy
+msgctxt "model:ir.action,name:act_sale_configuration_form"
+msgid "Configuration"
+msgstr "ການຕັ້ງຄ່າ"
+
+#, fuzzy
+msgctxt "model:ir.action,name:act_sale_form"
+msgid "Sales"
+msgstr "ຂາຍ"
+
+#, fuzzy
+msgctxt "model:ir.action,name:act_sale_form2"
+msgid "Sales"
+msgstr "ຂາຍ"
+
+#, fuzzy
+msgctxt "model:ir.action,name:act_sale_invoice_relate"
+msgid "Sales"
+msgstr "ຂາຍ"
+
+#, fuzzy
+msgctxt "model:ir.action,name:act_sale_move_relate"
+msgid "Moves"
+msgstr "ຕັດບັນຊີສາງ"
+
+msgctxt "model:ir.action,name:act_sale_shipment_returns_relate"
+msgid "Sales"
+msgstr "Sales"
+
+#, fuzzy
+msgctxt "model:ir.action,name:act_sale_shipments_relate"
+msgid "Sales"
+msgstr "ຂາຍ"
+
+msgctxt "model:ir.action,name:act_shipment_form"
+msgid "Shipments"
+msgstr "Shipments"
+
+#, fuzzy
+msgctxt "model:ir.action,name:report_sale"
+msgid "Sale"
+msgstr "ຂາຍ"
+
+msgctxt "model:ir.action,name:wizard_invoice_handle_exception"
+msgid "Handle Invoice Exception"
+msgstr "Handle Invoice Exception"
+
+msgctxt "model:ir.action,name:wizard_modify_header"
+msgid "Modify Header"
+msgstr "Modify Header"
+
+msgctxt "model:ir.action,name:wizard_reporting_region_open"
+msgid "Open Region"
+msgstr "Open Region"
+
+msgctxt "model:ir.action,name:wizard_return_sale"
+msgid "Return Sale"
+msgstr "Return Sale"
+
+msgctxt "model:ir.action,name:wizard_shipment_handle_exception"
+msgid "Handle Shipment Exception"
+msgstr "Handle Shipment Exception"
+
+#, fuzzy
+msgctxt "model:ir.action.act_window.domain,name:act_sale_form_domain_all"
+msgid "All"
+msgstr "ທັງໝົດ"
+
+#, fuzzy
+msgctxt ""
+"model:ir.action.act_window.domain,name:act_sale_form_domain_confirmed"
+msgid "Confirmed"
+msgstr "Confirmed"
+
+#, fuzzy
+msgctxt "model:ir.action.act_window.domain,name:act_sale_form_domain_draft"
+msgid "Draft"
+msgstr "ຮ່າງກຽມ"
+
+#, fuzzy
+msgctxt ""
+"model:ir.action.act_window.domain,name:act_sale_form_domain_exception"
+msgid "Exception"
+msgstr "ສະຖານະຍົກເວັ້ນ"
+
+#, fuzzy
+msgctxt ""
+"model:ir.action.act_window.domain,name:act_sale_form_domain_processing"
+msgid "Processing"
+msgstr "ກຳລັງດຳເນີນການ"
+
+msgctxt ""
+"model:ir.action.act_window.domain,name:act_sale_form_domain_quotation"
+msgid "Quotation"
+msgstr "Quotation"
+
+msgctxt "model:ir.message,text:msg_erase_party_pending_sale"
+msgid ""
+"You cannot erase party \"%(party)s\" while they have pending sales with "
+"company \"%(company)s\"."
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_sale_customer_location_required"
+msgid ""
+"To process sale \"%(sale)s\" you must set a customer location on party "
+"\"%(party)s\"."
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_sale_delete_cancel"
+msgid "To delete sale \"%(sale)s\" you must cancel it."
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_sale_invalid_method"
+msgid ""
+"You cannot use together invoice \"%(invoice_method)s\" and shipment "
+"\"%(shipment_method)s\" on sale \"%(sale)s\"."
+msgstr ""
+
+msgctxt ""
+"model:ir.message,text:msg_sale_invoice_address_required_for_quotation"
+msgid "To get a quote for sale \"%(sale)s\" you must enter an invoice address."
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_sale_invoice_reset_draft"
+msgid ""
+"You cannot reset invoice \"%(invoice)s\" to draft because it was generated "
+"by a sale."
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_sale_line_delete_cancel_draft"
+msgid ""
+"To delete line \"%(line)s\" you must cancel or reset to draft sale "
+"\"%(sale)s\"."
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_sale_missing_account_revenue"
+msgid "To invoice sale \"%(sale)s\" you must configure a default account revenue."
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_sale_modify_header_draft"
+msgid "To modify the header of sale \"%(sale)s\", it must be in \"draft\" state."
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_sale_move_reset_draft"
+msgid ""
+"You cannot reset move \"%(move)s\" to draft because it was generated by a "
+"sale."
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_sale_product_missing_account_revenue"
+msgid ""
+"To invoice sale \"%(sale)s\" you must define an account revenue for product "
+"\"%(product)s\"."
+msgstr ""
+
+#, fuzzy
+msgctxt "model:ir.message,text:msg_sale_reporting_company"
+msgid "Company"
+msgstr "ຫ້ອງການ/ສຳນັກງານ"
+
+#, fuzzy
+msgctxt "model:ir.message,text:msg_sale_reporting_currency"
+msgid "Currency"
+msgstr "ສະກຸນເງິນ"
+
+#, fuzzy
+msgctxt "model:ir.message,text:msg_sale_reporting_currency_digits"
+msgid "Currency Digits"
+msgstr "ໂຕເລກສະກຸນເງິນ"
+
+#, fuzzy
+msgctxt "model:ir.message,text:msg_sale_reporting_number"
+msgid "#"
+msgstr "#"
+
+msgctxt "model:ir.message,text:msg_sale_reporting_number_help"
+msgid "Number of sales"
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_sale_reporting_revenue"
+msgid "Revenue"
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_sale_reporting_revenue_trend"
+msgid "Revenue Trend"
+msgstr ""
+
+msgctxt ""
+"model:ir.message,text:msg_sale_shipment_address_required_for_quotation"
+msgid "To get a quote for sale \"%(sale)s\" you must enter a shipment address."
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_sale_warehouse_required_for_quotation"
+msgid "To get a quote for sale \"%(sale)s\" you must enter a warehouse."
+msgstr ""
+
+msgctxt "model:ir.model.button,string:sale_cancel_button"
+msgid "Cancel"
+msgstr "Cancel"
+
+msgctxt "model:ir.model.button,string:sale_confirm_button"
+msgid "Confirm"
+msgstr "Confirm"
+
+msgctxt "model:ir.model.button,string:sale_draft_button"
+msgid "Draft"
+msgstr "Draft"
+
+msgctxt "model:ir.model.button,string:sale_handle_invoice_exception_button"
+msgid "Handle Invoice Exception"
+msgstr "Handle Invoice Exception"
+
+msgctxt "model:ir.model.button,string:sale_handle_shipment_exception_button"
+msgid "Handle Shipment Exception"
+msgstr "Handle Shipment Exception"
+
+msgctxt "model:ir.model.button,string:sale_modify_header_button"
+msgid "Modify Header"
+msgstr "Modify Header"
+
+msgctxt "model:ir.model.button,string:sale_process_button"
+msgid "Process"
+msgstr "Process"
+
+msgctxt "model:ir.model.button,string:sale_quote_button"
+msgid "Quote"
+msgstr "Quote"
+
+msgctxt "model:ir.rule.group,name:rule_group_reporting_category_companies"
+msgid "User in companies"
+msgstr ""
+
+msgctxt ""
+"model:ir.rule.group,name:rule_group_reporting_category_time_series_companies"
+msgid "User in companies"
+msgstr ""
+
+msgctxt ""
+"model:ir.rule.group,name:rule_group_reporting_country_subdivision_time_series_companies"
+msgid "User in companies"
+msgstr ""
+
+msgctxt ""
+"model:ir.rule.group,name:rule_group_reporting_country_time_series_companies"
+msgid "User in companies"
+msgstr ""
+
+msgctxt "model:ir.rule.group,name:rule_group_reporting_customer_companies"
+msgid "User in companies"
+msgstr ""
+
+msgctxt ""
+"model:ir.rule.group,name:rule_group_reporting_customer_time_series_companies"
+msgid "User in companies"
+msgstr ""
+
+msgctxt "model:ir.rule.group,name:rule_group_reporting_product_companies"
+msgid "User in companies"
+msgstr ""
+
+msgctxt ""
+"model:ir.rule.group,name:rule_group_reporting_product_time_series_companies"
+msgid "User in companies"
+msgstr ""
+
+msgctxt "model:ir.rule.group,name:rule_group_reporting_region_companies"
+msgid "User in companies"
+msgstr ""
+
+msgctxt "model:ir.rule.group,name:rule_group_sale_companies"
+msgid "User in companies"
+msgstr ""
+
+#, fuzzy
+msgctxt "model:ir.sequence,name:sequence_sale"
+msgid "Sale"
+msgstr "ຂາຍ"
+
+#, fuzzy
+msgctxt "model:ir.sequence.type,name:sequence_type_sale"
+msgid "Sale"
+msgstr "ຂາຍ"
+
+#, fuzzy
+msgctxt "model:ir.ui.menu,name:menu_configuration"
+msgid "Configuration"
+msgstr "ການຕັ້ງຄ່າ"
+
+#, fuzzy
+msgctxt "model:ir.ui.menu,name:menu_customer"
+msgid "Associated to Sales"
+msgstr "Parties associated to Sales"
+
+#, fuzzy
+msgctxt "model:ir.ui.menu,name:menu_product"
+msgid "Products"
+msgstr "ຜະລິດຕະພັນ"
+
+msgctxt "model:ir.ui.menu,name:menu_reporting"
+msgid "Reporting"
+msgstr "Reporting"
+
+msgctxt "model:ir.ui.menu,name:menu_reporting_sale"
+msgid "Sales"
+msgstr "Sales"
+
+#, fuzzy
+msgctxt "model:ir.ui.menu,name:menu_sale"
+msgid "Sales"
+msgstr "ຂາຍ"
+
+#, fuzzy
+msgctxt "model:ir.ui.menu,name:menu_sale_configuration"
+msgid "Configuration"
+msgstr "ການຕັ້ງຄ່າ"
+
+#, fuzzy
+msgctxt "model:ir.ui.menu,name:menu_sale_form"
+msgid "Sales"
+msgstr "ຂາຍ"
+
+msgctxt "model:product.configuration.default_lead_time,name:"
+msgid "Product Default Lead Time"
+msgstr ""
+
+msgctxt "model:product.sale.context,name:"
+msgid "Product Sale Context"
+msgstr ""
+
+#, fuzzy
+msgctxt "model:res.group,name:group_sale"
+msgid "Sales"
+msgstr "ຂາຍ"
+
+msgctxt "model:res.group,name:group_sale_admin"
+msgid "Sales Administrator"
+msgstr "Sales Administrator"
+
+#, fuzzy
+msgctxt "model:sale.configuration,name:"
+msgid "Sale Configuration"
+msgstr "Sales Configuration"
+
+msgctxt "model:sale.configuration.sale_method,name:"
+msgid "Sale Configuration Sale Method"
+msgstr ""
+
+msgctxt "model:sale.configuration.sequence,name:"
+msgid "Sale Configuration Sequence"
+msgstr ""
+
+#, fuzzy
+msgctxt "model:sale.handle.invoice.exception.ask,name:"
+msgid "Handle Invoice Exception"
+msgstr "Handle Invoice Exception"
+
+#, fuzzy
+msgctxt "model:sale.handle.shipment.exception.ask,name:"
+msgid "Handle Shipment Exception"
+msgstr "Handle Shipment Exception"
+
+msgctxt "model:sale.line,name:"
+msgid "Sale Line"
+msgstr ""
+
+msgctxt "model:sale.line-account.tax,name:"
+msgid "Sale Line - Tax"
+msgstr ""
+
+msgctxt "model:sale.line-ignored-stock.move,name:"
+msgid "Sale Line - Ignored Move"
+msgstr ""
+
+msgctxt "model:sale.line-recreated-stock.move,name:"
+msgid "Sale Line - Recreated Move"
+msgstr ""
+
+msgctxt "model:sale.reporting.category,name:"
+msgid "Sale Reporting per Category"
+msgstr ""
+
+msgctxt "model:sale.reporting.category.time_series,name:"
+msgid "Sale Reporting per Category"
+msgstr ""
+
+msgctxt "model:sale.reporting.category.tree,name:"
+msgid "Sale Reporting per Category"
+msgstr ""
+
+msgctxt "model:sale.reporting.context,name:"
+msgid "Sale Reporting Context"
+msgstr ""
+
+msgctxt "model:sale.reporting.country,name:"
+msgid "Sale Reporting per Country"
+msgstr ""
+
+msgctxt "model:sale.reporting.country.subdivision,name:"
+msgid "Sale Reporting per Subdivision"
+msgstr ""
+
+msgctxt "model:sale.reporting.country.subdivision.time_series,name:"
+msgid "Sale Reporting per Subdivision"
+msgstr ""
+
+msgctxt "model:sale.reporting.country.time_series,name:"
+msgid "Sale Reporting per Country"
+msgstr ""
+
+msgctxt "model:sale.reporting.customer,name:"
+msgid "Sale Reporting per Customer"
+msgstr ""
+
+msgctxt "model:sale.reporting.customer.time_series,name:"
+msgid "Sale Reporting per Customer"
+msgstr ""
+
+msgctxt "model:sale.reporting.product,name:"
+msgid "Sale Reporting per Product"
+msgstr ""
+
+msgctxt "model:sale.reporting.product.time_series,name:"
+msgid "Sale Reporting per Product"
+msgstr ""
+
+msgctxt "model:sale.reporting.region,name:"
+msgid "Sale Reporting per Region"
+msgstr ""
+
+#, fuzzy
+msgctxt "model:sale.return_sale.start,name:"
+msgid "Return Sale"
+msgstr "Return Sale"
+
+#, fuzzy
+msgctxt "model:sale.sale,name:"
+msgid "Sale"
+msgstr "ຂາຍ"
+
+msgctxt "model:sale.sale-ignored-account.invoice,name:"
+msgid "Sale - Ignored Invoice"
+msgstr ""
+
+msgctxt "model:sale.sale-recreated-account.invoice,name:"
+msgid "Sale - Recreated Invoice"
+msgstr ""
+
+#, fuzzy
+msgctxt "report:sale.sale:"
+msgid ":"
+msgstr ":"
+
+#, fuzzy
+msgctxt "report:sale.sale:"
+msgid "Amount"
+msgstr "ມູນຄ່າ"
+
+#, fuzzy
+msgctxt "report:sale.sale:"
+msgid "Date:"
+msgstr "ວັນທີ:"
+
+#, fuzzy
+msgctxt "report:sale.sale:"
+msgid "Description"
+msgstr "ເນື້ອໃນລາຍການ"
+
+#, fuzzy
+msgctxt "report:sale.sale:"
+msgid "Description:"
+msgstr "ເນື້ອໃນລາຍການ"
+
+msgctxt "report:sale.sale:"
+msgid "Draft Sale Order"
+msgstr ""
+
+#, fuzzy
+msgctxt "report:sale.sale:"
+msgid "Quantity"
+msgstr "ຈຳນວນ"
+
+msgctxt "report:sale.sale:"
+msgid "Quotation N°:"
+msgstr ""
+
+#, fuzzy
+msgctxt "report:sale.sale:"
+msgid "Reference:"
+msgstr "ເອກະສານອ້າງອີງ"
+
+msgctxt "report:sale.sale:"
+msgid "Sale Order N°:"
+msgstr ""
+
+#, fuzzy
+msgctxt "report:sale.sale:"
+msgid "Taxes"
+msgstr "ອາກອນ"
+
+#, fuzzy
+msgctxt "report:sale.sale:"
+msgid "Taxes:"
+msgstr "ອາກອນ:"
+
+#, fuzzy
+msgctxt "report:sale.sale:"
+msgid "Total (excl. taxes):"
+msgstr "ລວມເງິນ (ບໍ່ລວມອາກອນ):"
+
+#, fuzzy
+msgctxt "report:sale.sale:"
+msgid "Total:"
+msgstr "ລວມເງິນ:"
+
+#, fuzzy
+msgctxt "report:sale.sale:"
+msgid "Unit Price"
+msgstr "ລາຄາຫົວໜ່ວຍ"
+
+#, fuzzy
+msgctxt "selection:account.invoice,sale_exception_state:"
+msgid "Ignored"
+msgstr "ບໍ່ແຕະຕ້ອງ"
+
+#, fuzzy
+msgctxt "selection:account.invoice,sale_exception_state:"
+msgid "Recreated"
+msgstr "ສ້າງຂຶ້ນໃໝ່"
+
+#, fuzzy
+msgctxt "selection:sale.line,type:"
+msgid "Comment"
+msgstr "ຄໍາເຫັນ"
+
+#, fuzzy
+msgctxt "selection:sale.line,type:"
+msgid "Line"
+msgstr "ຮ່ວງ"
+
+msgctxt "selection:sale.line,type:"
+msgid "Subtotal"
+msgstr ""
+
+msgctxt "selection:sale.line,type:"
+msgid "Title"
+msgstr ""
+
+msgctxt "selection:sale.reporting.context,period:"
+msgid "Day"
+msgstr ""
+
+msgctxt "selection:sale.reporting.context,period:"
+msgid "Month"
+msgstr ""
+
+msgctxt "selection:sale.reporting.context,period:"
+msgid "Year"
+msgstr ""
+
+#, fuzzy
+msgctxt "selection:sale.sale,invoice_method:"
+msgid "Manual"
+msgstr "ໃສ່ເອົາເອງ"
+
+msgctxt "selection:sale.sale,invoice_method:"
+msgid "On Order Processed"
+msgstr ""
+
+msgctxt "selection:sale.sale,invoice_method:"
+msgid "On Shipment Sent"
+msgstr ""
+
+msgctxt "selection:sale.sale,invoice_state:"
+msgid "Exception"
+msgstr ""
+
+#, fuzzy
+msgctxt "selection:sale.sale,invoice_state:"
+msgid "None"
+msgstr "ບໍ່ມີ"
+
+#, fuzzy
+msgctxt "selection:sale.sale,invoice_state:"
+msgid "Paid"
+msgstr "ຈ່າຍແລ້ວ"
+
+msgctxt "selection:sale.sale,invoice_state:"
+msgid "Waiting"
+msgstr ""
+
+#, fuzzy
+msgctxt "selection:sale.sale,shipment_method:"
+msgid "Manual"
+msgstr "ໃສ່ເອົາເອງ"
+
+msgctxt "selection:sale.sale,shipment_method:"
+msgid "On Invoice Paid"
+msgstr ""
+
+msgctxt "selection:sale.sale,shipment_method:"
+msgid "On Order Processed"
+msgstr ""
+
+msgctxt "selection:sale.sale,shipment_state:"
+msgid "Exception"
+msgstr ""
+
+#, fuzzy
+msgctxt "selection:sale.sale,shipment_state:"
+msgid "None"
+msgstr "ບໍ່ມີ"
+
+msgctxt "selection:sale.sale,shipment_state:"
+msgid "Sent"
+msgstr ""
+
+msgctxt "selection:sale.sale,shipment_state:"
+msgid "Waiting"
+msgstr ""
+
+#, fuzzy
+msgctxt "selection:sale.sale,state:"
+msgid "Cancelled"
+msgstr "ຍົກເລີກແລ້ວ"
+
+#, fuzzy
+msgctxt "selection:sale.sale,state:"
+msgid "Confirmed"
+msgstr "Confirm"
+
+#, fuzzy
+msgctxt "selection:sale.sale,state:"
+msgid "Done"
+msgstr "ແລ້ວໆ"
+
+#, fuzzy
+msgctxt "selection:sale.sale,state:"
+msgid "Draft"
+msgstr "ຮ່າງກຽມ"
+
+#, fuzzy
+msgctxt "selection:sale.sale,state:"
+msgid "Processing"
+msgstr "ກຳລັງດຳເນີນການ"
+
+#, fuzzy
+msgctxt "selection:sale.sale,state:"
+msgid "Quotation"
+msgstr "Quotation"
+
+#, fuzzy
+msgctxt "selection:stock.move,sale_exception_state:"
+msgid "Ignored"
+msgstr "ບໍ່ແຕະຕ້ອງ"
+
+#, fuzzy
+msgctxt "selection:stock.move,sale_exception_state:"
+msgid "Recreated"
+msgstr "ສ້າງຂຶ້ນໃໝ່"
+
+#, fuzzy
+msgctxt "view:party.party:"
+msgid "Sale"
+msgstr "ຂາຍ"
+
+msgctxt "view:product.template:"
+msgid "Customers"
+msgstr ""
+
+msgctxt "view:sale.handle.invoice.exception.ask:"
+msgid "Choose invoices to recreate:"
+msgstr ""
+
+msgctxt "view:sale.handle.shipment.exception.ask:"
+msgid "Choose move to recreate:"
+msgstr ""
+
+#, fuzzy
+msgctxt "view:sale.line:"
+msgid "General"
+msgstr "ທົ່ວໄປ"
+
+#, fuzzy
+msgctxt "view:sale.line:"
+msgid "Notes"
+msgstr "ໝາຍເຫດ"
+
+#, fuzzy
+msgctxt "view:sale.line:"
+msgid "Taxes"
+msgstr "ອາກອນ"
+
+msgctxt "view:sale.return_sale.start:"
+msgid "Are you sure to return these/this sale(s)?"
+msgstr ""
+
+#, fuzzy
+msgctxt "view:sale.sale:"
+msgid "Other Info"
+msgstr "ຂໍ້ມູນອື່ນໆ"
+
+#, fuzzy
+msgctxt "view:sale.sale:"
+msgid "Sale"
+msgstr "ຂາຍ"
+
+#, fuzzy
+msgctxt "wizard_button:sale.handle.invoice.exception,ask,end:"
+msgid "Cancel"
+msgstr "ຍົກເລີກ"
+
+#, fuzzy
+msgctxt "wizard_button:sale.handle.invoice.exception,ask,handle:"
+msgid "OK"
+msgstr "ຕົກລົງ"
+
+#, fuzzy
+msgctxt "wizard_button:sale.handle.shipment.exception,ask,end:"
+msgid "Cancel"
+msgstr "ຍົກເລີກ"
+
+#, fuzzy
+msgctxt "wizard_button:sale.handle.shipment.exception,ask,handle:"
+msgid "OK"
+msgstr "ຕົກລົງ"
+
+#, fuzzy
+msgctxt "wizard_button:sale.modify_header,start,end:"
+msgid "Cancel"
+msgstr "ຍົກເລີກ"
+
+msgctxt "wizard_button:sale.modify_header,start,modify:"
+msgid "Modify"
+msgstr ""
+
+#, fuzzy
+msgctxt "wizard_button:sale.return_sale,start,end:"
+msgid "Cancel"
+msgstr "ຍົກເລີກ"
+
+#, fuzzy
+msgctxt "wizard_button:sale.return_sale,start,return_:"
+msgid "Return"
+msgstr "Returns"
diff --git a/modules/sale/locale/lt.po b/modules/sale/locale/lt.po
new file mode 100644
index 0000000000..6727110714
--- /dev/null
+++ b/modules/sale/locale/lt.po
@@ -0,0 +1,1387 @@
+#
+msgid ""
+msgstr "Content-Type: text/plain; charset=utf-8\n"
+
+msgctxt "field:account.invoice,sale_exception_state:"
+msgid "Exception State"
+msgstr "Išimtinė būsena"
+
+msgctxt "field:account.invoice,sales:"
+msgid "Sales"
+msgstr "Pardavimai"
+
+#, fuzzy
+msgctxt "field:product.configuration,default_lead_time:"
+msgid "Default Lead Time"
+msgstr "Tiekimo laikas"
+
+#, fuzzy
+msgctxt "field:product.configuration.default_lead_time,company:"
+msgid "Company"
+msgstr "Organizacija"
+
+#, fuzzy
+msgctxt "field:product.configuration.default_lead_time,default_lead_time:"
+msgid "Default Lead Time"
+msgstr "Tiekimo laikas"
+
+msgctxt "field:product.product,lead_time:"
+msgid "Lead Time"
+msgstr "Tiekimo laikas"
+
+msgctxt "field:product.product,salable:"
+msgid "Salable"
+msgstr "Parduodama"
+
+msgctxt "field:product.product,sale_price_uom:"
+msgid "Sale Price"
+msgstr "Pardavimo kaina"
+
+msgctxt "field:product.product,sale_uom:"
+msgid "Sale UOM"
+msgstr "Mato vienetas parduodant"
+
+#, fuzzy
+msgctxt "field:product.sale.context,company:"
+msgid "Company"
+msgstr "Organizacija"
+
+#, fuzzy
+msgctxt "field:product.sale.context,currency:"
+msgid "Currency"
+msgstr "Valiuta"
+
+#, fuzzy
+msgctxt "field:product.sale.context,customer:"
+msgid "Customer"
+msgstr "Pirkėjas"
+
+#, fuzzy
+msgctxt "field:product.sale.context,locations:"
+msgid "Warehouses"
+msgstr "Sandėlys"
+
+#, fuzzy
+msgctxt "field:product.sale.context,quantity:"
+msgid "Quantity"
+msgstr "Kiekis"
+
+#, fuzzy
+msgctxt "field:product.sale.context,sale_date:"
+msgid "Sale Date"
+msgstr "Pardavimo data"
+
+msgctxt "field:product.sale.context,stock_date_end:"
+msgid "Stock End Date"
+msgstr ""
+
+msgctxt "field:product.template,lead_time:"
+msgid "Lead Time"
+msgstr "Tiekimo laikas"
+
+msgctxt "field:product.template,salable:"
+msgid "Salable"
+msgstr "Parduodama"
+
+msgctxt "field:product.template,sale_uom:"
+msgid "Sale UOM"
+msgstr "Mato vienetas parduodant"
+
+msgctxt "field:sale.configuration,sale_invoice_method:"
+msgid "Sale Invoice Method"
+msgstr "Pardavimo sąskaitų faktūrų išrašymo būdas"
+
+msgctxt "field:sale.configuration,sale_process_after:"
+msgid "Process Sale after"
+msgstr "Pauzė prieš parduodant"
+
+msgctxt "field:sale.configuration,sale_sequence:"
+msgid "Sale Sequence"
+msgstr "Pardavimų numeruotė"
+
+msgctxt "field:sale.configuration,sale_shipment_method:"
+msgid "Sale Shipment Method"
+msgstr "Siuntimo parduodant būdas"
+
+msgctxt "field:sale.configuration.sale_method,sale_invoice_method:"
+msgid "Sale Invoice Method"
+msgstr "Pardavimo sąskaitų faktūrų išrašymo būdas"
+
+msgctxt "field:sale.configuration.sale_method,sale_shipment_method:"
+msgid "Sale Shipment Method"
+msgstr "Siuntimo parduodant būdas"
+
+msgctxt "field:sale.configuration.sequence,company:"
+msgid "Company"
+msgstr "Organizacija"
+
+msgctxt "field:sale.configuration.sequence,sale_sequence:"
+msgid "Sale Sequence"
+msgstr "Pardavimų numeruotė"
+
+msgctxt "field:sale.handle.invoice.exception.ask,domain_invoices:"
+msgid "Domain Invoices"
+msgstr "Sąskaitų faktūrų domenas"
+
+msgctxt "field:sale.handle.invoice.exception.ask,recreate_invoices:"
+msgid "Recreate Invoices"
+msgstr "Atkurtos sąskaitos faktūros"
+
+msgctxt "field:sale.handle.shipment.exception.ask,domain_moves:"
+msgid "Domain Moves"
+msgstr "Operacijų domenas"
+
+msgctxt "field:sale.handle.shipment.exception.ask,recreate_moves:"
+msgid "Recreate Moves"
+msgstr "Atkurti operacijos"
+
+#, fuzzy
+msgctxt "field:sale.line,actual_quantity:"
+msgid "Actual Quantity"
+msgstr "Kiekis"
+
+msgctxt "field:sale.line,amount:"
+msgid "Amount"
+msgstr "Suma"
+
+#, fuzzy
+msgctxt "field:sale.line,company:"
+msgid "Company"
+msgstr "Organizacija"
+
+#, fuzzy
+msgctxt "field:sale.line,currency:"
+msgid "Currency"
+msgstr "Valiuta"
+
+msgctxt "field:sale.line,description:"
+msgid "Description"
+msgstr "Aprašymas"
+
+msgctxt "field:sale.line,from_location:"
+msgid "From Location"
+msgstr "Išsiuntimo vieta"
+
+msgctxt "field:sale.line,invoice_lines:"
+msgid "Invoice Lines"
+msgstr "Sąskaitos faktūros eilutės"
+
+msgctxt "field:sale.line,move_done:"
+msgid "Moves Done"
+msgstr "Atliktos operacijos"
+
+msgctxt "field:sale.line,move_exception:"
+msgid "Moves Exception"
+msgstr "Operacijų išimtys"
+
+msgctxt "field:sale.line,moves:"
+msgid "Moves"
+msgstr "Operacijos"
+
+msgctxt "field:sale.line,moves_ignored:"
+msgid "Ignored Moves"
+msgstr "Ignoruotos operacijos"
+
+msgctxt "field:sale.line,moves_recreated:"
+msgid "Recreated Moves"
+msgstr "Atkurtos operacijos"
+
+msgctxt "field:sale.line,note:"
+msgid "Note"
+msgstr "Pastaba"
+
+msgctxt "field:sale.line,product:"
+msgid "Product"
+msgstr "Prekė"
+
+msgctxt "field:sale.line,product_uom_category:"
+msgid "Product Uom Category"
+msgstr "Prekės mato vieneto kategorija"
+
+msgctxt "field:sale.line,quantity:"
+msgid "Quantity"
+msgstr "Kiekis"
+
+msgctxt "field:sale.line,sale:"
+msgid "Sale"
+msgstr "Pardavimas"
+
+msgctxt "field:sale.line,sale_state:"
+msgid "Sale State"
+msgstr "Pardavimo būsena"
+
+msgctxt "field:sale.line,shipping_date:"
+msgid "Shipping Date"
+msgstr "Išsiuntimo data"
+
+msgctxt "field:sale.line,summary:"
+msgid "Summary"
+msgstr ""
+
+msgctxt "field:sale.line,taxes:"
+msgid "Taxes"
+msgstr "Mokesčiai"
+
+msgctxt "field:sale.line,to_location:"
+msgid "To Location"
+msgstr "Gavimo vieta"
+
+msgctxt "field:sale.line,type:"
+msgid "Type"
+msgstr "Tipas"
+
+msgctxt "field:sale.line,unit:"
+msgid "Unit"
+msgstr "Mato vienetas"
+
+msgctxt "field:sale.line,unit_digits:"
+msgid "Unit Digits"
+msgstr "Mato vieneto skaitmenų po kablelio skaičius"
+
+msgctxt "field:sale.line,unit_price:"
+msgid "Unit Price"
+msgstr "Kaina"
+
+msgctxt "field:sale.line,warehouse:"
+msgid "Warehouse"
+msgstr "Sandėlys"
+
+msgctxt "field:sale.line-account.tax,line:"
+msgid "Sale Line"
+msgstr "Pardavimo eilutė"
+
+msgctxt "field:sale.line-account.tax,tax:"
+msgid "Tax"
+msgstr "PVM"
+
+msgctxt "field:sale.line-ignored-stock.move,move:"
+msgid "Move"
+msgstr "Operacija"
+
+msgctxt "field:sale.line-ignored-stock.move,sale_line:"
+msgid "Sale Line"
+msgstr "Pardavimo eilutė"
+
+msgctxt "field:sale.line-recreated-stock.move,move:"
+msgid "Move"
+msgstr "Operacija"
+
+msgctxt "field:sale.line-recreated-stock.move,sale_line:"
+msgid "Sale Line"
+msgstr "Pardavimo eilutė"
+
+msgctxt "field:sale.reporting.category,category:"
+msgid "Category"
+msgstr "Kategorija"
+
+msgctxt "field:sale.reporting.category,time_series:"
+msgid "Time Series"
+msgstr "Laiko serijos"
+
+msgctxt "field:sale.reporting.category.time_series,category:"
+msgid "Category"
+msgstr "Kategorija"
+
+msgctxt "field:sale.reporting.category.time_series,date:"
+msgid "Date"
+msgstr "Data"
+
+msgctxt "field:sale.reporting.category.tree,children:"
+msgid "Children"
+msgstr "Dukterinės"
+
+msgctxt "field:sale.reporting.category.tree,currency_digits:"
+msgid "Currency Digits"
+msgstr "Valiutos skaitmenų po kablelio skaičius"
+
+msgctxt "field:sale.reporting.category.tree,name:"
+msgid "Name"
+msgstr "Pavadinimas"
+
+msgctxt "field:sale.reporting.category.tree,parent:"
+msgid "Parent"
+msgstr "Motininė"
+
+msgctxt "field:sale.reporting.category.tree,revenue:"
+msgid "Revenue"
+msgstr "Pajamos"
+
+msgctxt "field:sale.reporting.context,company:"
+msgid "Company"
+msgstr "Organizacija"
+
+msgctxt "field:sale.reporting.context,from_date:"
+msgid "From Date"
+msgstr "Pradinė data"
+
+msgctxt "field:sale.reporting.context,period:"
+msgid "Period"
+msgstr "Periodas"
+
+msgctxt "field:sale.reporting.context,to_date:"
+msgid "To Date"
+msgstr "Pabaigos data"
+
+msgctxt "field:sale.reporting.context,warehouse:"
+msgid "Warehouse"
+msgstr "Sandėlys"
+
+msgctxt "field:sale.reporting.country,country:"
+msgid "Country"
+msgstr "Šalis"
+
+msgctxt "field:sale.reporting.country,time_series:"
+msgid "Time Series"
+msgstr "Laiko serijos"
+
+msgctxt "field:sale.reporting.country.subdivision,country:"
+msgid "Country"
+msgstr "Šalis"
+
+msgctxt "field:sale.reporting.country.subdivision,subdivision:"
+msgid "Subdivision"
+msgstr "Regionas"
+
+msgctxt "field:sale.reporting.country.subdivision,time_series:"
+msgid "Time Series"
+msgstr "Laiko serijos"
+
+msgctxt "field:sale.reporting.country.subdivision.time_series,country:"
+msgid "Country"
+msgstr "Šalis"
+
+msgctxt "field:sale.reporting.country.subdivision.time_series,date:"
+msgid "Date"
+msgstr "Data"
+
+msgctxt "field:sale.reporting.country.subdivision.time_series,subdivision:"
+msgid "Subdivision"
+msgstr "Regionas"
+
+msgctxt "field:sale.reporting.country.time_series,country:"
+msgid "Country"
+msgstr "Šalis"
+
+msgctxt "field:sale.reporting.country.time_series,date:"
+msgid "Date"
+msgstr "Data"
+
+msgctxt "field:sale.reporting.customer,customer:"
+msgid "Customer"
+msgstr "Pirkėjas"
+
+msgctxt "field:sale.reporting.customer,time_series:"
+msgid "Time Series"
+msgstr "Laiko serijos"
+
+msgctxt "field:sale.reporting.customer.time_series,customer:"
+msgid "Customer"
+msgstr "Pirkėjas"
+
+msgctxt "field:sale.reporting.customer.time_series,date:"
+msgid "Date"
+msgstr "Data"
+
+msgctxt "field:sale.reporting.product,product:"
+msgid "Product"
+msgstr "Prekė"
+
+msgctxt "field:sale.reporting.product,time_series:"
+msgid "Time Series"
+msgstr "Laiko serijos"
+
+msgctxt "field:sale.reporting.product.time_series,date:"
+msgid "Date"
+msgstr "Data"
+
+msgctxt "field:sale.reporting.product.time_series,product:"
+msgid "Product"
+msgstr "Prekė"
+
+msgctxt "field:sale.reporting.region,children:"
+msgid "Children"
+msgstr "Dukteriniai"
+
+msgctxt "field:sale.reporting.region,parent:"
+msgid "Parent"
+msgstr "Motininis"
+
+msgctxt "field:sale.reporting.region,region:"
+msgid "Region"
+msgstr "Regionas"
+
+msgctxt "field:sale.sale,comment:"
+msgid "Comment"
+msgstr "Komentaras"
+
+msgctxt "field:sale.sale,company:"
+msgid "Company"
+msgstr "Organizacija"
+
+#, fuzzy
+msgctxt "field:sale.sale,confirmed_by:"
+msgid "Confirmed By"
+msgstr "Patvirtinti"
+
+msgctxt "field:sale.sale,contact:"
+msgid "Contact"
+msgstr ""
+
+msgctxt "field:sale.sale,currency:"
+msgid "Currency"
+msgstr "Valiuta"
+
+msgctxt "field:sale.sale,currency_digits:"
+msgid "Currency Digits"
+msgstr "Valiutos skaitmenų po kablelio skaičius"
+
+msgctxt "field:sale.sale,description:"
+msgid "Description"
+msgstr "Aprašymas"
+
+msgctxt "field:sale.sale,invoice_address:"
+msgid "Invoice Address"
+msgstr "Juridinis adresas"
+
+msgctxt "field:sale.sale,invoice_method:"
+msgid "Invoice Method"
+msgstr "Sąskaita faktūra išrašoma"
+
+#, fuzzy
+msgctxt "field:sale.sale,invoice_party:"
+msgid "Invoice Party"
+msgstr "Sąskaitos faktūros būsena"
+
+msgctxt "field:sale.sale,invoice_state:"
+msgid "Invoice State"
+msgstr "Sąskaitos faktūros būsena"
+
+msgctxt "field:sale.sale,invoices:"
+msgid "Invoices"
+msgstr "Sąskaitos faktūros"
+
+msgctxt "field:sale.sale,invoices_ignored:"
+msgid "Ignored Invoices"
+msgstr "Ignoruotos sąskaitos faktūros"
+
+msgctxt "field:sale.sale,invoices_recreated:"
+msgid "Recreated Invoices"
+msgstr "Atkurtos sąskaitos faktūros"
+
+msgctxt "field:sale.sale,lines:"
+msgid "Lines"
+msgstr "Eilutės"
+
+msgctxt "field:sale.sale,moves:"
+msgid "Moves"
+msgstr "Operacijos"
+
+msgctxt "field:sale.sale,number:"
+msgid "Number"
+msgstr "Numeris"
+
+msgctxt "field:sale.sale,origin:"
+msgid "Origin"
+msgstr "Šaltinis"
+
+msgctxt "field:sale.sale,party:"
+msgid "Party"
+msgstr "Kontrahentas"
+
+msgctxt "field:sale.sale,party_lang:"
+msgid "Party Language"
+msgstr "Kontrahento kalba"
+
+msgctxt "field:sale.sale,payment_term:"
+msgid "Payment Term"
+msgstr "Mokėjimo sąlyga"
+
+#, fuzzy
+msgctxt "field:sale.sale,quoted_by:"
+msgid "Quoted By"
+msgstr "Pasiūlymas"
+
+msgctxt "field:sale.sale,reference:"
+msgid "Reference"
+msgstr "Nuoroda"
+
+msgctxt "field:sale.sale,sale_date:"
+msgid "Sale Date"
+msgstr "Pardavimo data"
+
+msgctxt "field:sale.sale,shipment_address:"
+msgid "Shipment Address"
+msgstr "Siuntimo adresas"
+
+msgctxt "field:sale.sale,shipment_method:"
+msgid "Shipment Method"
+msgstr "Siuntimo būdas"
+
+msgctxt "field:sale.sale,shipment_party:"
+msgid "Shipment Party"
+msgstr "Gavėjas"
+
+msgctxt "field:sale.sale,shipment_returns:"
+msgid "Shipment Returns"
+msgstr "Grąžinimas"
+
+msgctxt "field:sale.sale,shipment_state:"
+msgid "Shipment State"
+msgstr "Siuntimo būsena"
+
+msgctxt "field:sale.sale,shipments:"
+msgid "Shipments"
+msgstr "Siuntimai"
+
+#, fuzzy
+msgctxt "field:sale.sale,shipping_date:"
+msgid "Shipping Date"
+msgstr "Išsiuntimo data"
+
+msgctxt "field:sale.sale,state:"
+msgid "State"
+msgstr "Būsena"
+
+msgctxt "field:sale.sale,tax_amount:"
+msgid "Tax"
+msgstr "PVM"
+
+msgctxt "field:sale.sale,tax_amount_cache:"
+msgid "Tax Cache"
+msgstr "Išsaugota PVM vertė"
+
+msgctxt "field:sale.sale,total_amount:"
+msgid "Total"
+msgstr "Viso su PVM"
+
+#, fuzzy
+msgctxt "field:sale.sale,total_amount_cache:"
+msgid "Total Cache"
+msgstr "Išsaugota PVM vertė"
+
+msgctxt "field:sale.sale,untaxed_amount:"
+msgid "Untaxed"
+msgstr "Viso"
+
+msgctxt "field:sale.sale,untaxed_amount_cache:"
+msgid "Untaxed Cache"
+msgstr "Išsaugota bendra suma be PVM"
+
+msgctxt "field:sale.sale,warehouse:"
+msgid "Warehouse"
+msgstr "Sandėlys"
+
+msgctxt "field:sale.sale-ignored-account.invoice,invoice:"
+msgid "Invoice"
+msgstr "Sąskaita faktūra"
+
+msgctxt "field:sale.sale-ignored-account.invoice,sale:"
+msgid "Sale"
+msgstr "Pardavimas"
+
+msgctxt "field:sale.sale-recreated-account.invoice,invoice:"
+msgid "Invoice"
+msgstr "Sąskaita faktūra"
+
+msgctxt "field:sale.sale-recreated-account.invoice,sale:"
+msgid "Sale"
+msgstr "Pardavimas"
+
+msgctxt "field:stock.move,sale:"
+msgid "Sale"
+msgstr "Pardavimas"
+
+msgctxt "field:stock.move,sale_exception_state:"
+msgid "Exception State"
+msgstr "Išimtinė būsena"
+
+msgctxt "help:product.configuration,default_lead_time:"
+msgid ""
+"The time from confirming the sales order to sending the products.\n"
+"Used for products without a lead time."
+msgstr ""
+
+msgctxt "help:product.product,lead_time:"
+msgid ""
+"The time from confirming the sales order to sending the products.\n"
+"If empty the default lead time from the configuration is used."
+msgstr ""
+
+msgctxt "help:product.template,lead_time:"
+msgid ""
+"The time from confirming the sales order to sending the products.\n"
+"If empty the default lead time from the configuration is used."
+msgstr ""
+
+msgctxt "help:sale.configuration,sale_process_after:"
+msgid ""
+"The grace period during which confirmed sale can still be reset to draft.\n"
+"Applied if a worker queue is activated."
+msgstr ""
+
+msgctxt "help:sale.handle.invoice.exception.ask,recreate_invoices:"
+msgid ""
+"The selected invoices will be recreated. The other ones will be ignored."
+msgstr ""
+
+msgctxt "help:sale.sale,shipping_date:"
+msgid "When the shipping of goods should start."
+msgstr ""
+
+#, fuzzy
+msgctxt "model:ir.action,name:act_invoice_form"
+msgid "Invoices"
+msgstr "Sąskaitos faktūros"
+
+msgctxt "model:ir.action,name:act_open_customer"
+msgid "Parties associated to Sales"
+msgstr "Su pardavimais susieti kontrahentai"
+
+#, fuzzy
+msgctxt "model:ir.action,name:act_product"
+msgid "Products"
+msgstr "Prekė"
+
+msgctxt "model:ir.action,name:act_reporting_category"
+msgid "Sales per Category"
+msgstr "Pardavimai pagal kategoriją"
+
+msgctxt "model:ir.action,name:act_reporting_category_time_series"
+msgid "Sales per Category"
+msgstr "Pardavimai pagal kategoriją"
+
+msgctxt "model:ir.action,name:act_reporting_category_tree"
+msgid "Sales per Category"
+msgstr "Pardavimai pagal kategoriją"
+
+msgctxt "model:ir.action,name:act_reporting_country_subdivision_time_series"
+msgid "Sales per Subdivision"
+msgstr "Pardavimai pagal regioną"
+
+msgctxt "model:ir.action,name:act_reporting_country_time_series"
+msgid "Sales per Country"
+msgstr "Pardavimai pagal šalį"
+
+msgctxt "model:ir.action,name:act_reporting_customer"
+msgid "Sales per Customer"
+msgstr "Pardavimai pagal pirkėją"
+
+msgctxt "model:ir.action,name:act_reporting_customer_time_series"
+msgid "Sales per Customer"
+msgstr "Pardavimai pagal pirkėją"
+
+msgctxt "model:ir.action,name:act_reporting_product"
+msgid "Sales per Product"
+msgstr "Pardavimai pagal prekę"
+
+msgctxt "model:ir.action,name:act_reporting_product_time_series"
+msgid "Sales per Product"
+msgstr "Pardavimai pagal prekę"
+
+msgctxt "model:ir.action,name:act_reporting_region"
+msgid "Sales per Region"
+msgstr "Pardavimai pagal regioną"
+
+msgctxt "model:ir.action,name:act_return_form"
+msgid "Returns"
+msgstr "Grąžinimai"
+
+#, fuzzy
+msgctxt "model:ir.action,name:act_sale_configuration_form"
+msgid "Configuration"
+msgstr "Nuostatos"
+
+msgctxt "model:ir.action,name:act_sale_form"
+msgid "Sales"
+msgstr "Pardavimai"
+
+msgctxt "model:ir.action,name:act_sale_form2"
+msgid "Sales"
+msgstr "Pardavimai"
+
+msgctxt "model:ir.action,name:act_sale_invoice_relate"
+msgid "Sales"
+msgstr "Pardavimai"
+
+#, fuzzy
+msgctxt "model:ir.action,name:act_sale_move_relate"
+msgid "Moves"
+msgstr "Operacijos"
+
+msgctxt "model:ir.action,name:act_sale_shipment_returns_relate"
+msgid "Sales"
+msgstr "Pardavimai"
+
+msgctxt "model:ir.action,name:act_sale_shipments_relate"
+msgid "Sales"
+msgstr "Pardavimai"
+
+msgctxt "model:ir.action,name:act_shipment_form"
+msgid "Shipments"
+msgstr "Siuntimai"
+
+msgctxt "model:ir.action,name:report_sale"
+msgid "Sale"
+msgstr "Pardavimas"
+
+msgctxt "model:ir.action,name:wizard_invoice_handle_exception"
+msgid "Handle Invoice Exception"
+msgstr "Tvarkyti sąskaitos faktūros išimtinę situaciją"
+
+msgctxt "model:ir.action,name:wizard_modify_header"
+msgid "Modify Header"
+msgstr "Taisyti antraštės duomenis"
+
+msgctxt "model:ir.action,name:wizard_reporting_region_open"
+msgid "Open Region"
+msgstr "Atverti regioną"
+
+msgctxt "model:ir.action,name:wizard_return_sale"
+msgid "Return Sale"
+msgstr "Pardavimo grąžinimas"
+
+msgctxt "model:ir.action,name:wizard_shipment_handle_exception"
+msgid "Handle Shipment Exception"
+msgstr "Tvarkyti siuntimo išimtinę situaciją"
+
+msgctxt "model:ir.action.act_window.domain,name:act_sale_form_domain_all"
+msgid "All"
+msgstr "Visi"
+
+msgctxt ""
+"model:ir.action.act_window.domain,name:act_sale_form_domain_confirmed"
+msgid "Confirmed"
+msgstr "Patvirtinti"
+
+msgctxt "model:ir.action.act_window.domain,name:act_sale_form_domain_draft"
+msgid "Draft"
+msgstr "Juodraštis"
+
+#, fuzzy
+msgctxt ""
+"model:ir.action.act_window.domain,name:act_sale_form_domain_exception"
+msgid "Exception"
+msgstr "Išimtis"
+
+msgctxt ""
+"model:ir.action.act_window.domain,name:act_sale_form_domain_processing"
+msgid "Processing"
+msgstr "Vykdomi"
+
+msgctxt ""
+"model:ir.action.act_window.domain,name:act_sale_form_domain_quotation"
+msgid "Quotation"
+msgstr "Pasiūlymai"
+
+msgctxt "model:ir.message,text:msg_erase_party_pending_sale"
+msgid ""
+"You cannot erase party \"%(party)s\" while they have pending sales with "
+"company \"%(company)s\"."
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_sale_customer_location_required"
+msgid ""
+"To process sale \"%(sale)s\" you must set a customer location on party "
+"\"%(party)s\"."
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_sale_delete_cancel"
+msgid "To delete sale \"%(sale)s\" you must cancel it."
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_sale_invalid_method"
+msgid ""
+"You cannot use together invoice \"%(invoice_method)s\" and shipment "
+"\"%(shipment_method)s\" on sale \"%(sale)s\"."
+msgstr ""
+
+msgctxt ""
+"model:ir.message,text:msg_sale_invoice_address_required_for_quotation"
+msgid "To get a quote for sale \"%(sale)s\" you must enter an invoice address."
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_sale_invoice_reset_draft"
+msgid ""
+"You cannot reset invoice \"%(invoice)s\" to draft because it was generated "
+"by a sale."
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_sale_line_delete_cancel_draft"
+msgid ""
+"To delete line \"%(line)s\" you must cancel or reset to draft sale "
+"\"%(sale)s\"."
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_sale_missing_account_revenue"
+msgid "To invoice sale \"%(sale)s\" you must configure a default account revenue."
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_sale_modify_header_draft"
+msgid "To modify the header of sale \"%(sale)s\", it must be in \"draft\" state."
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_sale_move_reset_draft"
+msgid ""
+"You cannot reset move \"%(move)s\" to draft because it was generated by a "
+"sale."
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_sale_product_missing_account_revenue"
+msgid ""
+"To invoice sale \"%(sale)s\" you must define an account revenue for product "
+"\"%(product)s\"."
+msgstr ""
+
+#, fuzzy
+msgctxt "model:ir.message,text:msg_sale_reporting_company"
+msgid "Company"
+msgstr "Organizacija"
+
+#, fuzzy
+msgctxt "model:ir.message,text:msg_sale_reporting_currency"
+msgid "Currency"
+msgstr "Valiuta"
+
+#, fuzzy
+msgctxt "model:ir.message,text:msg_sale_reporting_currency_digits"
+msgid "Currency Digits"
+msgstr "Valiutos skaitmenų po kablelio skaičius"
+
+#, fuzzy
+msgctxt "model:ir.message,text:msg_sale_reporting_number"
+msgid "#"
+msgstr "#"
+
+#, fuzzy
+msgctxt "model:ir.message,text:msg_sale_reporting_number_help"
+msgid "Number of sales"
+msgstr "Pardavimų kiekis"
+
+#, fuzzy
+msgctxt "model:ir.message,text:msg_sale_reporting_revenue"
+msgid "Revenue"
+msgstr "Pajamos"
+
+#, fuzzy
+msgctxt "model:ir.message,text:msg_sale_reporting_revenue_trend"
+msgid "Revenue Trend"
+msgstr "Pajamų tendencija"
+
+msgctxt ""
+"model:ir.message,text:msg_sale_shipment_address_required_for_quotation"
+msgid "To get a quote for sale \"%(sale)s\" you must enter a shipment address."
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_sale_warehouse_required_for_quotation"
+msgid "To get a quote for sale \"%(sale)s\" you must enter a warehouse."
+msgstr ""
+
+msgctxt "model:ir.model.button,string:sale_cancel_button"
+msgid "Cancel"
+msgstr "Anuliuoti"
+
+msgctxt "model:ir.model.button,string:sale_confirm_button"
+msgid "Confirm"
+msgstr "Patvirtinti"
+
+msgctxt "model:ir.model.button,string:sale_draft_button"
+msgid "Draft"
+msgstr "Taisyti"
+
+msgctxt "model:ir.model.button,string:sale_handle_invoice_exception_button"
+msgid "Handle Invoice Exception"
+msgstr "Tvarkyti sąskaitos faktūros išimtinę situaciją"
+
+msgctxt "model:ir.model.button,string:sale_handle_shipment_exception_button"
+msgid "Handle Shipment Exception"
+msgstr "Tvarkyti siuntimo išimtinę situaciją"
+
+msgctxt "model:ir.model.button,string:sale_modify_header_button"
+msgid "Modify Header"
+msgstr "Taisyti antraštės duomenis"
+
+msgctxt "model:ir.model.button,string:sale_process_button"
+msgid "Process"
+msgstr "Vykdyti"
+
+msgctxt "model:ir.model.button,string:sale_quote_button"
+msgid "Quote"
+msgstr "Pasiūlymas"
+
+#, fuzzy
+msgctxt "model:ir.rule.group,name:rule_group_reporting_category_companies"
+msgid "User in companies"
+msgstr "Organizacijos naudotojas"
+
+#, fuzzy
+msgctxt ""
+"model:ir.rule.group,name:rule_group_reporting_category_time_series_companies"
+msgid "User in companies"
+msgstr "Organizacijos naudotojas"
+
+#, fuzzy
+msgctxt ""
+"model:ir.rule.group,name:rule_group_reporting_country_subdivision_time_series_companies"
+msgid "User in companies"
+msgstr "Organizacijos naudotojas"
+
+#, fuzzy
+msgctxt ""
+"model:ir.rule.group,name:rule_group_reporting_country_time_series_companies"
+msgid "User in companies"
+msgstr "Organizacijos naudotojas"
+
+#, fuzzy
+msgctxt "model:ir.rule.group,name:rule_group_reporting_customer_companies"
+msgid "User in companies"
+msgstr "Organizacijos naudotojas"
+
+#, fuzzy
+msgctxt ""
+"model:ir.rule.group,name:rule_group_reporting_customer_time_series_companies"
+msgid "User in companies"
+msgstr "Organizacijos naudotojas"
+
+#, fuzzy
+msgctxt "model:ir.rule.group,name:rule_group_reporting_product_companies"
+msgid "User in companies"
+msgstr "Organizacijos naudotojas"
+
+#, fuzzy
+msgctxt ""
+"model:ir.rule.group,name:rule_group_reporting_product_time_series_companies"
+msgid "User in companies"
+msgstr "Organizacijos naudotojas"
+
+#, fuzzy
+msgctxt "model:ir.rule.group,name:rule_group_reporting_region_companies"
+msgid "User in companies"
+msgstr "Organizacijos naudotojas"
+
+#, fuzzy
+msgctxt "model:ir.rule.group,name:rule_group_sale_companies"
+msgid "User in companies"
+msgstr "Organizacijos naudotojas"
+
+msgctxt "model:ir.sequence,name:sequence_sale"
+msgid "Sale"
+msgstr "Pardavimas"
+
+msgctxt "model:ir.sequence.type,name:sequence_type_sale"
+msgid "Sale"
+msgstr "Pardavimas"
+
+msgctxt "model:ir.ui.menu,name:menu_configuration"
+msgid "Configuration"
+msgstr "Nuostatos"
+
+#, fuzzy
+msgctxt "model:ir.ui.menu,name:menu_customer"
+msgid "Associated to Sales"
+msgstr "Su pardavimais susieti kontrahentai"
+
+#, fuzzy
+msgctxt "model:ir.ui.menu,name:menu_product"
+msgid "Products"
+msgstr "Prekė"
+
+msgctxt "model:ir.ui.menu,name:menu_reporting"
+msgid "Reporting"
+msgstr "Ataskaitos"
+
+msgctxt "model:ir.ui.menu,name:menu_reporting_sale"
+msgid "Sales"
+msgstr "Pardavimai"
+
+msgctxt "model:ir.ui.menu,name:menu_sale"
+msgid "Sales"
+msgstr "Pardavimai"
+
+#, fuzzy
+msgctxt "model:ir.ui.menu,name:menu_sale_configuration"
+msgid "Configuration"
+msgstr "Nuostatos"
+
+msgctxt "model:ir.ui.menu,name:menu_sale_form"
+msgid "Sales"
+msgstr "Pardavimai"
+
+msgctxt "model:product.configuration.default_lead_time,name:"
+msgid "Product Default Lead Time"
+msgstr ""
+
+#, fuzzy
+msgctxt "model:product.sale.context,name:"
+msgid "Product Sale Context"
+msgstr "Pauzė prieš parduodant"
+
+msgctxt "model:res.group,name:group_sale"
+msgid "Sales"
+msgstr "Pardavimai"
+
+msgctxt "model:res.group,name:group_sale_admin"
+msgid "Sales Administrator"
+msgstr "Pardavimų valdymas"
+
+msgctxt "model:sale.configuration,name:"
+msgid "Sale Configuration"
+msgstr "Pardavimo nuostatos"
+
+msgctxt "model:sale.configuration.sale_method,name:"
+msgid "Sale Configuration Sale Method"
+msgstr "Pardavimo metodas"
+
+msgctxt "model:sale.configuration.sequence,name:"
+msgid "Sale Configuration Sequence"
+msgstr "Pardavimo numeruotė"
+
+msgctxt "model:sale.handle.invoice.exception.ask,name:"
+msgid "Handle Invoice Exception"
+msgstr "Tvarkyti sąskaitos faktūros išimtinę situaciją"
+
+msgctxt "model:sale.handle.shipment.exception.ask,name:"
+msgid "Handle Shipment Exception"
+msgstr "Tvarkyti siuntimo išimtinę situaciją"
+
+msgctxt "model:sale.line,name:"
+msgid "Sale Line"
+msgstr "Pardavimo eilutė"
+
+msgctxt "model:sale.line-account.tax,name:"
+msgid "Sale Line - Tax"
+msgstr "Pardavimo eilutė - PVM"
+
+msgctxt "model:sale.line-ignored-stock.move,name:"
+msgid "Sale Line - Ignored Move"
+msgstr "Pardavimo eilutė - ignoruota operacija"
+
+msgctxt "model:sale.line-recreated-stock.move,name:"
+msgid "Sale Line - Recreated Move"
+msgstr "Pardavimo eilutė - atkurta operacija"
+
+msgctxt "model:sale.reporting.category,name:"
+msgid "Sale Reporting per Category"
+msgstr "Pardavimo ataskaita pagal kategoriją"
+
+msgctxt "model:sale.reporting.category.time_series,name:"
+msgid "Sale Reporting per Category"
+msgstr "Pardavimo ataskaita pagal kategoriją"
+
+msgctxt "model:sale.reporting.category.tree,name:"
+msgid "Sale Reporting per Category"
+msgstr "Pardavimo ataskaita pagal kategoriją"
+
+msgctxt "model:sale.reporting.context,name:"
+msgid "Sale Reporting Context"
+msgstr "Pardavimo ataskaitos kontekstas"
+
+msgctxt "model:sale.reporting.country,name:"
+msgid "Sale Reporting per Country"
+msgstr "Pardavimo ataskaita pagal šalį"
+
+msgctxt "model:sale.reporting.country.subdivision,name:"
+msgid "Sale Reporting per Subdivision"
+msgstr "Pardavimo ataskaita pagal regioną"
+
+msgctxt "model:sale.reporting.country.subdivision.time_series,name:"
+msgid "Sale Reporting per Subdivision"
+msgstr "Pardavimo ataskaita pagal regioną"
+
+msgctxt "model:sale.reporting.country.time_series,name:"
+msgid "Sale Reporting per Country"
+msgstr "Pardavimo ataskaita pagal šalį"
+
+msgctxt "model:sale.reporting.customer,name:"
+msgid "Sale Reporting per Customer"
+msgstr "Pardavimo ataskaita pagal pirkėją"
+
+msgctxt "model:sale.reporting.customer.time_series,name:"
+msgid "Sale Reporting per Customer"
+msgstr "Pardavimo ataskaita pagal pirkėją"
+
+msgctxt "model:sale.reporting.product,name:"
+msgid "Sale Reporting per Product"
+msgstr "Pardavimo ataskaita pagal prekę"
+
+msgctxt "model:sale.reporting.product.time_series,name:"
+msgid "Sale Reporting per Product"
+msgstr "Pardavimo ataskaita pagal prekę"
+
+msgctxt "model:sale.reporting.region,name:"
+msgid "Sale Reporting per Region"
+msgstr "Pardavimo ataskaita pagal regioną"
+
+msgctxt "model:sale.return_sale.start,name:"
+msgid "Return Sale"
+msgstr "Pardavimo grąžinimas"
+
+msgctxt "model:sale.sale,name:"
+msgid "Sale"
+msgstr "Pardavimas"
+
+msgctxt "model:sale.sale-ignored-account.invoice,name:"
+msgid "Sale - Ignored Invoice"
+msgstr "Pardavimas - ignoruotos sąskaitos faktūros"
+
+msgctxt "model:sale.sale-recreated-account.invoice,name:"
+msgid "Sale - Recreated Invoice"
+msgstr "Pardavimas - atkurtos sąskaitos faktūros"
+
+msgctxt "report:sale.sale:"
+msgid ":"
+msgstr ":"
+
+msgctxt "report:sale.sale:"
+msgid "Amount"
+msgstr "Suma"
+
+msgctxt "report:sale.sale:"
+msgid "Date:"
+msgstr "Data:"
+
+msgctxt "report:sale.sale:"
+msgid "Description"
+msgstr "Aprašymas"
+
+msgctxt "report:sale.sale:"
+msgid "Description:"
+msgstr "Aprašymas:"
+
+msgctxt "report:sale.sale:"
+msgid "Draft Sale Order"
+msgstr "Pardavimo juodraštis"
+
+msgctxt "report:sale.sale:"
+msgid "Quantity"
+msgstr "Kiekis"
+
+msgctxt "report:sale.sale:"
+msgid "Quotation N°:"
+msgstr "Pasiūlymas Nr.:"
+
+msgctxt "report:sale.sale:"
+msgid "Reference:"
+msgstr "Nuoroda:"
+
+msgctxt "report:sale.sale:"
+msgid "Sale Order N°:"
+msgstr "Sąskaita išankstiniam mokėjimui Nr.:"
+
+msgctxt "report:sale.sale:"
+msgid "Taxes"
+msgstr "PVM"
+
+msgctxt "report:sale.sale:"
+msgid "Taxes:"
+msgstr "PVM:"
+
+msgctxt "report:sale.sale:"
+msgid "Total (excl. taxes):"
+msgstr "Viso:"
+
+msgctxt "report:sale.sale:"
+msgid "Total:"
+msgstr "Viso su PVM:"
+
+msgctxt "report:sale.sale:"
+msgid "Unit Price"
+msgstr "Kaina"
+
+msgctxt "selection:account.invoice,sale_exception_state:"
+msgid "Ignored"
+msgstr "Ignoruota"
+
+msgctxt "selection:account.invoice,sale_exception_state:"
+msgid "Recreated"
+msgstr "Atkurta"
+
+msgctxt "selection:sale.line,type:"
+msgid "Comment"
+msgstr "Komentaras"
+
+msgctxt "selection:sale.line,type:"
+msgid "Line"
+msgstr "Eilutė"
+
+msgctxt "selection:sale.line,type:"
+msgid "Subtotal"
+msgstr "Tarpinė suma"
+
+msgctxt "selection:sale.line,type:"
+msgid "Title"
+msgstr "Antraštė"
+
+msgctxt "selection:sale.reporting.context,period:"
+msgid "Day"
+msgstr "Diena"
+
+msgctxt "selection:sale.reporting.context,period:"
+msgid "Month"
+msgstr "Mėnuo"
+
+msgctxt "selection:sale.reporting.context,period:"
+msgid "Year"
+msgstr "Metai"
+
+msgctxt "selection:sale.sale,invoice_method:"
+msgid "Manual"
+msgstr "Rankiniu būdu"
+
+msgctxt "selection:sale.sale,invoice_method:"
+msgid "On Order Processed"
+msgstr "Vykdant užsakymą"
+
+msgctxt "selection:sale.sale,invoice_method:"
+msgid "On Shipment Sent"
+msgstr "Išsiunčiant krovinį"
+
+msgctxt "selection:sale.sale,invoice_state:"
+msgid "Exception"
+msgstr "Išimtis"
+
+msgctxt "selection:sale.sale,invoice_state:"
+msgid "None"
+msgstr "Jokia"
+
+msgctxt "selection:sale.sale,invoice_state:"
+msgid "Paid"
+msgstr "Apmokėta"
+
+msgctxt "selection:sale.sale,invoice_state:"
+msgid "Waiting"
+msgstr "Laukianti apmokėjimo"
+
+msgctxt "selection:sale.sale,shipment_method:"
+msgid "Manual"
+msgstr "Rankiniu būdu"
+
+msgctxt "selection:sale.sale,shipment_method:"
+msgid "On Invoice Paid"
+msgstr "Apmokėjus sąskaitą faktūrą"
+
+msgctxt "selection:sale.sale,shipment_method:"
+msgid "On Order Processed"
+msgstr "Pradėjus vykdyti pardavimą"
+
+msgctxt "selection:sale.sale,shipment_state:"
+msgid "Exception"
+msgstr "Išimtis"
+
+msgctxt "selection:sale.sale,shipment_state:"
+msgid "None"
+msgstr "Jokia"
+
+msgctxt "selection:sale.sale,shipment_state:"
+msgid "Sent"
+msgstr "Išsiųsta"
+
+msgctxt "selection:sale.sale,shipment_state:"
+msgid "Waiting"
+msgstr "Laukiantis"
+
+#, fuzzy
+msgctxt "selection:sale.sale,state:"
+msgid "Cancelled"
+msgstr "Anuliuota"
+
+msgctxt "selection:sale.sale,state:"
+msgid "Confirmed"
+msgstr "Patvirtinta"
+
+msgctxt "selection:sale.sale,state:"
+msgid "Done"
+msgstr "Pabaigta"
+
+msgctxt "selection:sale.sale,state:"
+msgid "Draft"
+msgstr "Juodraštis"
+
+msgctxt "selection:sale.sale,state:"
+msgid "Processing"
+msgstr "Vykdoma"
+
+msgctxt "selection:sale.sale,state:"
+msgid "Quotation"
+msgstr "Pasiūlymas"
+
+msgctxt "selection:stock.move,sale_exception_state:"
+msgid "Ignored"
+msgstr "Ignoruota"
+
+msgctxt "selection:stock.move,sale_exception_state:"
+msgid "Recreated"
+msgstr "Atkurta"
+
+msgctxt "view:party.party:"
+msgid "Sale"
+msgstr "Pardavimas"
+
+msgctxt "view:product.template:"
+msgid "Customers"
+msgstr "Pirkėjai"
+
+#, fuzzy
+msgctxt "view:sale.handle.invoice.exception.ask:"
+msgid "Choose invoices to recreate:"
+msgstr "Pasirinkite sąskaitas faktūras atkūrimui"
+
+#, fuzzy
+msgctxt "view:sale.handle.shipment.exception.ask:"
+msgid "Choose move to recreate:"
+msgstr "Pasirinkite operacijas atkūrimui"
+
+msgctxt "view:sale.line:"
+msgid "General"
+msgstr "Pagrindinis"
+
+msgctxt "view:sale.line:"
+msgid "Notes"
+msgstr "Pastabos"
+
+msgctxt "view:sale.line:"
+msgid "Taxes"
+msgstr "Mokesčiai"
+
+msgctxt "view:sale.return_sale.start:"
+msgid "Are you sure to return these/this sale(s)?"
+msgstr ""
+
+msgctxt "view:sale.sale:"
+msgid "Other Info"
+msgstr "Kita informacija"
+
+msgctxt "view:sale.sale:"
+msgid "Sale"
+msgstr "Pardavimas"
+
+msgctxt "wizard_button:sale.handle.invoice.exception,ask,end:"
+msgid "Cancel"
+msgstr "Atsisakyti"
+
+msgctxt "wizard_button:sale.handle.invoice.exception,ask,handle:"
+msgid "OK"
+msgstr "Gerai"
+
+msgctxt "wizard_button:sale.handle.shipment.exception,ask,end:"
+msgid "Cancel"
+msgstr "Atsisakyti"
+
+msgctxt "wizard_button:sale.handle.shipment.exception,ask,handle:"
+msgid "OK"
+msgstr "Gerai"
+
+msgctxt "wizard_button:sale.modify_header,start,end:"
+msgid "Cancel"
+msgstr "Atsisakyti"
+
+msgctxt "wizard_button:sale.modify_header,start,modify:"
+msgid "Modify"
+msgstr "Taisyti"
+
+msgctxt "wizard_button:sale.return_sale,start,end:"
+msgid "Cancel"
+msgstr "Atsisakyti"
+
+msgctxt "wizard_button:sale.return_sale,start,return_:"
+msgid "Return"
+msgstr "Grąžinti"
diff --git a/modules/sale/locale/nl.po b/modules/sale/locale/nl.po
new file mode 100644
index 0000000000..f61b064114
--- /dev/null
+++ b/modules/sale/locale/nl.po
@@ -0,0 +1,1391 @@
+#
+msgid ""
+msgstr "Content-Type: text/plain; charset=utf-8\n"
+
+msgctxt "field:account.invoice,sale_exception_state:"
+msgid "Exception State"
+msgstr "Uitzonderingstoestand"
+
+msgctxt "field:account.invoice,sales:"
+msgid "Sales"
+msgstr "verkoop"
+
+msgctxt "field:product.configuration,default_lead_time:"
+msgid "Default Lead Time"
+msgstr "Standaard doorlooptijd"
+
+msgctxt "field:product.configuration.default_lead_time,company:"
+msgid "Company"
+msgstr "Bedrijf"
+
+msgctxt "field:product.configuration.default_lead_time,default_lead_time:"
+msgid "Default Lead Time"
+msgstr "Standaard doorlooptijd"
+
+msgctxt "field:product.product,lead_time:"
+msgid "Lead Time"
+msgstr "Doorlooptijd"
+
+msgctxt "field:product.product,salable:"
+msgid "Salable"
+msgstr "Verkoopbaar"
+
+msgctxt "field:product.product,sale_price_uom:"
+msgid "Sale Price"
+msgstr "Verkoopprijs"
+
+msgctxt "field:product.product,sale_uom:"
+msgid "Sale UOM"
+msgstr "Maateenheid verkoop"
+
+msgctxt "field:product.sale.context,company:"
+msgid "Company"
+msgstr "Bedrijf"
+
+msgctxt "field:product.sale.context,currency:"
+msgid "Currency"
+msgstr "Valuta"
+
+msgctxt "field:product.sale.context,customer:"
+msgid "Customer"
+msgstr "Klant"
+
+msgctxt "field:product.sale.context,locations:"
+msgid "Warehouses"
+msgstr "Magazijnen"
+
+msgctxt "field:product.sale.context,quantity:"
+msgid "Quantity"
+msgstr "Hoeveelheid"
+
+msgctxt "field:product.sale.context,sale_date:"
+msgid "Sale Date"
+msgstr "Verkoopsdatum"
+
+msgctxt "field:product.sale.context,stock_date_end:"
+msgid "Stock End Date"
+msgstr "Einddatum voorraad"
+
+msgctxt "field:product.template,lead_time:"
+msgid "Lead Time"
+msgstr "Doorlooptijd"
+
+msgctxt "field:product.template,salable:"
+msgid "Salable"
+msgstr "Verkoopbaar"
+
+msgctxt "field:product.template,sale_uom:"
+msgid "Sale UOM"
+msgstr "Maateenheid verkoop"
+
+msgctxt "field:sale.configuration,sale_invoice_method:"
+msgid "Sale Invoice Method"
+msgstr "Verkoopfactuurmethode"
+
+msgctxt "field:sale.configuration,sale_process_after:"
+msgid "Process Sale after"
+msgstr "Procesverkoop na"
+
+msgctxt "field:sale.configuration,sale_sequence:"
+msgid "Sale Sequence"
+msgstr "Verkoopvolgorde"
+
+msgctxt "field:sale.configuration,sale_shipment_method:"
+msgid "Sale Shipment Method"
+msgstr "Verkoop Verzendmethode"
+
+msgctxt "field:sale.configuration.sale_method,sale_invoice_method:"
+msgid "Sale Invoice Method"
+msgstr "Verkoopfactuurmethode"
+
+msgctxt "field:sale.configuration.sale_method,sale_shipment_method:"
+msgid "Sale Shipment Method"
+msgstr "Verkoop Verzendmethode"
+
+msgctxt "field:sale.configuration.sequence,company:"
+msgid "Company"
+msgstr "Bedrijf"
+
+msgctxt "field:sale.configuration.sequence,sale_sequence:"
+msgid "Sale Sequence"
+msgstr "Verkoopvolgorde"
+
+msgctxt "field:sale.handle.invoice.exception.ask,domain_invoices:"
+msgid "Domain Invoices"
+msgstr "Domein facturen"
+
+msgctxt "field:sale.handle.invoice.exception.ask,recreate_invoices:"
+msgid "Recreate Invoices"
+msgstr "Facturen opnieuw aanmaken"
+
+msgctxt "field:sale.handle.shipment.exception.ask,domain_moves:"
+msgid "Domain Moves"
+msgstr "Domein boekingen"
+
+msgctxt "field:sale.handle.shipment.exception.ask,recreate_moves:"
+msgid "Recreate Moves"
+msgstr "Boekingen opnieuw aanmaken"
+
+msgctxt "field:sale.line,actual_quantity:"
+msgid "Actual Quantity"
+msgstr "Werkelijke hoeveelheid"
+
+msgctxt "field:sale.line,amount:"
+msgid "Amount"
+msgstr "Bedrag"
+
+msgctxt "field:sale.line,company:"
+msgid "Company"
+msgstr "Bedrijf"
+
+msgctxt "field:sale.line,currency:"
+msgid "Currency"
+msgstr "Valuta"
+
+msgctxt "field:sale.line,description:"
+msgid "Description"
+msgstr "Specificatie"
+
+msgctxt "field:sale.line,from_location:"
+msgid "From Location"
+msgstr "Van locatie"
+
+msgctxt "field:sale.line,invoice_lines:"
+msgid "Invoice Lines"
+msgstr "Factuurregels"
+
+msgctxt "field:sale.line,move_done:"
+msgid "Moves Done"
+msgstr "Boekingen klaar"
+
+msgctxt "field:sale.line,move_exception:"
+msgid "Moves Exception"
+msgstr "Boekingen uitzondering"
+
+msgctxt "field:sale.line,moves:"
+msgid "Moves"
+msgstr "Boekingen"
+
+msgctxt "field:sale.line,moves_ignored:"
+msgid "Ignored Moves"
+msgstr "Genegeerde boekingen"
+
+msgctxt "field:sale.line,moves_recreated:"
+msgid "Recreated Moves"
+msgstr "Opnieuw aangemaakte boekingen"
+
+msgctxt "field:sale.line,note:"
+msgid "Note"
+msgstr "Aantekening"
+
+msgctxt "field:sale.line,product:"
+msgid "Product"
+msgstr "Product"
+
+msgctxt "field:sale.line,product_uom_category:"
+msgid "Product Uom Category"
+msgstr "Categorie eenheidsmaten (Catégorie d'unité de mesure)"
+
+msgctxt "field:sale.line,quantity:"
+msgid "Quantity"
+msgstr "Hoeveelheid"
+
+msgctxt "field:sale.line,sale:"
+msgid "Sale"
+msgstr "Verkoop"
+
+msgctxt "field:sale.line,sale_state:"
+msgid "Sale State"
+msgstr "Verkoop status"
+
+msgctxt "field:sale.line,shipping_date:"
+msgid "Shipping Date"
+msgstr "Verzendingsdatum"
+
+msgctxt "field:sale.line,summary:"
+msgid "Summary"
+msgstr "Samenvatting"
+
+msgctxt "field:sale.line,taxes:"
+msgid "Taxes"
+msgstr "Belastingen"
+
+msgctxt "field:sale.line,to_location:"
+msgid "To Location"
+msgstr "Naar locatie"
+
+msgctxt "field:sale.line,type:"
+msgid "Type"
+msgstr "Type"
+
+msgctxt "field:sale.line,unit:"
+msgid "Unit"
+msgstr "Eenheid"
+
+msgctxt "field:sale.line,unit_digits:"
+msgid "Unit Digits"
+msgstr "Decimalen eenheid"
+
+msgctxt "field:sale.line,unit_price:"
+msgid "Unit Price"
+msgstr "Eenheidsprijs"
+
+msgctxt "field:sale.line,warehouse:"
+msgid "Warehouse"
+msgstr "Magazijn"
+
+msgctxt "field:sale.line-account.tax,line:"
+msgid "Sale Line"
+msgstr "Offerteregel"
+
+msgctxt "field:sale.line-account.tax,tax:"
+msgid "Tax"
+msgstr "Belasting"
+
+msgctxt "field:sale.line-ignored-stock.move,move:"
+msgid "Move"
+msgstr "Boeking"
+
+msgctxt "field:sale.line-ignored-stock.move,sale_line:"
+msgid "Sale Line"
+msgstr "Offerteregel"
+
+msgctxt "field:sale.line-recreated-stock.move,move:"
+msgid "Move"
+msgstr "Boeking"
+
+msgctxt "field:sale.line-recreated-stock.move,sale_line:"
+msgid "Sale Line"
+msgstr "Offerteregel"
+
+msgctxt "field:sale.reporting.category,category:"
+msgid "Category"
+msgstr "Categorie"
+
+msgctxt "field:sale.reporting.category,time_series:"
+msgid "Time Series"
+msgstr "Tijdreeksen"
+
+msgctxt "field:sale.reporting.category.time_series,category:"
+msgid "Category"
+msgstr "Categorie"
+
+msgctxt "field:sale.reporting.category.time_series,date:"
+msgid "Date"
+msgstr "Datum"
+
+msgctxt "field:sale.reporting.category.tree,children:"
+msgid "Children"
+msgstr "Onderliggende niveaus"
+
+msgctxt "field:sale.reporting.category.tree,currency_digits:"
+msgid "Currency Digits"
+msgstr "Valuta decimalen"
+
+msgctxt "field:sale.reporting.category.tree,name:"
+msgid "Name"
+msgstr "Naam"
+
+msgctxt "field:sale.reporting.category.tree,parent:"
+msgid "Parent"
+msgstr "Bovenliggend niveau"
+
+msgctxt "field:sale.reporting.category.tree,revenue:"
+msgid "Revenue"
+msgstr "Omzet"
+
+msgctxt "field:sale.reporting.context,company:"
+msgid "Company"
+msgstr "Bedrijf"
+
+msgctxt "field:sale.reporting.context,from_date:"
+msgid "From Date"
+msgstr "Vanaf datum"
+
+msgctxt "field:sale.reporting.context,period:"
+msgid "Period"
+msgstr "Periode"
+
+msgctxt "field:sale.reporting.context,to_date:"
+msgid "To Date"
+msgstr "Einddatum"
+
+msgctxt "field:sale.reporting.context,warehouse:"
+msgid "Warehouse"
+msgstr "Magazijn"
+
+msgctxt "field:sale.reporting.country,country:"
+msgid "Country"
+msgstr "Land"
+
+msgctxt "field:sale.reporting.country,time_series:"
+msgid "Time Series"
+msgstr "Tijdreeksen"
+
+msgctxt "field:sale.reporting.country.subdivision,country:"
+msgid "Country"
+msgstr "Land"
+
+msgctxt "field:sale.reporting.country.subdivision,subdivision:"
+msgid "Subdivision"
+msgstr "Onderverdeling"
+
+msgctxt "field:sale.reporting.country.subdivision,time_series:"
+msgid "Time Series"
+msgstr "Tijdreeksen"
+
+msgctxt "field:sale.reporting.country.subdivision.time_series,country:"
+msgid "Country"
+msgstr "Land"
+
+msgctxt "field:sale.reporting.country.subdivision.time_series,date:"
+msgid "Date"
+msgstr "Datum"
+
+msgctxt "field:sale.reporting.country.subdivision.time_series,subdivision:"
+msgid "Subdivision"
+msgstr "Onderverdeling"
+
+msgctxt "field:sale.reporting.country.time_series,country:"
+msgid "Country"
+msgstr "Land"
+
+msgctxt "field:sale.reporting.country.time_series,date:"
+msgid "Date"
+msgstr "Datum"
+
+msgctxt "field:sale.reporting.customer,customer:"
+msgid "Customer"
+msgstr "Klanten"
+
+msgctxt "field:sale.reporting.customer,time_series:"
+msgid "Time Series"
+msgstr "Tijdreeksen"
+
+msgctxt "field:sale.reporting.customer.time_series,customer:"
+msgid "Customer"
+msgstr "Klant"
+
+msgctxt "field:sale.reporting.customer.time_series,date:"
+msgid "Date"
+msgstr "Datum"
+
+msgctxt "field:sale.reporting.product,product:"
+msgid "Product"
+msgstr "Product"
+
+msgctxt "field:sale.reporting.product,time_series:"
+msgid "Time Series"
+msgstr "Tijdreeksen"
+
+msgctxt "field:sale.reporting.product.time_series,date:"
+msgid "Date"
+msgstr "Datum"
+
+msgctxt "field:sale.reporting.product.time_series,product:"
+msgid "Product"
+msgstr "Product"
+
+msgctxt "field:sale.reporting.region,children:"
+msgid "Children"
+msgstr "Onderliggende niveaus"
+
+msgctxt "field:sale.reporting.region,parent:"
+msgid "Parent"
+msgstr "Bovenliggend niveau"
+
+msgctxt "field:sale.reporting.region,region:"
+msgid "Region"
+msgstr "Regio"
+
+msgctxt "field:sale.sale,comment:"
+msgid "Comment"
+msgstr "Opmerking"
+
+msgctxt "field:sale.sale,company:"
+msgid "Company"
+msgstr "Bedrijf"
+
+msgctxt "field:sale.sale,confirmed_by:"
+msgid "Confirmed By"
+msgstr "Bevestigd door"
+
+msgctxt "field:sale.sale,contact:"
+msgid "Contact"
+msgstr "Contact"
+
+msgctxt "field:sale.sale,currency:"
+msgid "Currency"
+msgstr "Valuta"
+
+msgctxt "field:sale.sale,currency_digits:"
+msgid "Currency Digits"
+msgstr "Valuta decimalen"
+
+msgctxt "field:sale.sale,description:"
+msgid "Description"
+msgstr "Specificatie"
+
+msgctxt "field:sale.sale,invoice_address:"
+msgid "Invoice Address"
+msgstr "Factuuradres"
+
+msgctxt "field:sale.sale,invoice_method:"
+msgid "Invoice Method"
+msgstr "Factuur afhandeling"
+
+msgctxt "field:sale.sale,invoice_party:"
+msgid "Invoice Party"
+msgstr "Factuur relatie (Invoice Party)"
+
+msgctxt "field:sale.sale,invoice_state:"
+msgid "Invoice State"
+msgstr "Factuur status"
+
+msgctxt "field:sale.sale,invoices:"
+msgid "Invoices"
+msgstr "Facturen"
+
+msgctxt "field:sale.sale,invoices_ignored:"
+msgid "Ignored Invoices"
+msgstr "Genegeerde facturen"
+
+msgctxt "field:sale.sale,invoices_recreated:"
+msgid "Recreated Invoices"
+msgstr "Opnieuw aangemaakte facturen"
+
+msgctxt "field:sale.sale,lines:"
+msgid "Lines"
+msgstr "Regels"
+
+msgctxt "field:sale.sale,moves:"
+msgid "Moves"
+msgstr "Boekingen"
+
+msgctxt "field:sale.sale,number:"
+msgid "Number"
+msgstr "Nummer"
+
+msgctxt "field:sale.sale,origin:"
+msgid "Origin"
+msgstr "Oorsprong"
+
+msgctxt "field:sale.sale,party:"
+msgid "Party"
+msgstr "Relatie"
+
+msgctxt "field:sale.sale,party_lang:"
+msgid "Party Language"
+msgstr "Taal relatie"
+
+msgctxt "field:sale.sale,payment_term:"
+msgid "Payment Term"
+msgstr "Betalingstermijn"
+
+msgctxt "field:sale.sale,quoted_by:"
+msgid "Quoted By"
+msgstr "Offerte gemaakt door"
+
+msgctxt "field:sale.sale,reference:"
+msgid "Reference"
+msgstr "Referentie"
+
+msgctxt "field:sale.sale,sale_date:"
+msgid "Sale Date"
+msgstr "Verkoopdatum"
+
+msgctxt "field:sale.sale,shipment_address:"
+msgid "Shipment Address"
+msgstr "Afleveradres"
+
+msgctxt "field:sale.sale,shipment_method:"
+msgid "Shipment Method"
+msgstr "Levering afhandeling"
+
+msgctxt "field:sale.sale,shipment_party:"
+msgid "Shipment Party"
+msgstr "courierdienst (shipment paty)"
+
+msgctxt "field:sale.sale,shipment_returns:"
+msgid "Shipment Returns"
+msgstr "Retourzendingen"
+
+msgctxt "field:sale.sale,shipment_state:"
+msgid "Shipment State"
+msgstr "Levering status"
+
+msgctxt "field:sale.sale,shipments:"
+msgid "Shipments"
+msgstr "Leveringen"
+
+msgctxt "field:sale.sale,shipping_date:"
+msgid "Shipping Date"
+msgstr "Verzendingsdatum"
+
+msgctxt "field:sale.sale,state:"
+msgid "State"
+msgstr "Status"
+
+msgctxt "field:sale.sale,tax_amount:"
+msgid "Tax"
+msgstr "Belasting"
+
+msgctxt "field:sale.sale,tax_amount_cache:"
+msgid "Tax Cache"
+msgstr "Belastingcache"
+
+msgctxt "field:sale.sale,total_amount:"
+msgid "Total"
+msgstr "Totaal"
+
+#, fuzzy
+msgctxt "field:sale.sale,total_amount_cache:"
+msgid "Total Cache"
+msgstr "Belastingcache"
+
+msgctxt "field:sale.sale,untaxed_amount:"
+msgid "Untaxed"
+msgstr "Onbelast"
+
+msgctxt "field:sale.sale,untaxed_amount_cache:"
+msgid "Untaxed Cache"
+msgstr "onbelaste contanten"
+
+msgctxt "field:sale.sale,warehouse:"
+msgid "Warehouse"
+msgstr "Magazijn"
+
+msgctxt "field:sale.sale-ignored-account.invoice,invoice:"
+msgid "Invoice"
+msgstr "Factuur"
+
+msgctxt "field:sale.sale-ignored-account.invoice,sale:"
+msgid "Sale"
+msgstr "Verkoop"
+
+msgctxt "field:sale.sale-recreated-account.invoice,invoice:"
+msgid "Invoice"
+msgstr "Factuur"
+
+msgctxt "field:sale.sale-recreated-account.invoice,sale:"
+msgid "Sale"
+msgstr "Verkoop"
+
+msgctxt "field:stock.move,sale:"
+msgid "Sale"
+msgstr "Verkoop"
+
+msgctxt "field:stock.move,sale_exception_state:"
+msgid "Exception State"
+msgstr "Uitzonderingstoestand"
+
+msgctxt "help:product.configuration,default_lead_time:"
+msgid ""
+"The time from confirming the sales order to sending the products.\n"
+"Used for products without a lead time."
+msgstr ""
+"De tijd tussen de bevestigung van het verkooporder en het verzenden van de producten.\n"
+"Gebruikt voor producten zonder doorlooptijd."
+
+msgctxt "help:product.product,lead_time:"
+msgid ""
+"The time from confirming the sales order to sending the products.\n"
+"If empty the default lead time from the configuration is used."
+msgstr ""
+"De tijd tussen de bevestiging van het verkooporder en het verzenden van de producten.\n"
+"Indien leeg wordt de standaard doorlooptijd uit de configuratie gebruikt."
+
+msgctxt "help:product.template,lead_time:"
+msgid ""
+"The time from confirming the sales order to sending the products.\n"
+"If empty the default lead time from the configuration is used."
+msgstr ""
+"De tijd tussen de bevestiging van het verkooporder en het verzenden van de producten.\n"
+"Indien leeg wordt de standaard doorlooptijd uit de configuratie gebruikt."
+
+msgctxt "help:sale.configuration,sale_process_after:"
+msgid ""
+"The grace period during which confirmed sale can still be reset to draft.\n"
+"Applied if a worker queue is activated."
+msgstr ""
+"De respijtperiode waarin bevestigde aankoop nog steeds kan worden gereset naar concept.\n"
+"Alleen toegepast als een wachtrij voor werknemers is geactiveerd."
+
+msgctxt "help:sale.handle.invoice.exception.ask,recreate_invoices:"
+msgid ""
+"The selected invoices will be recreated. The other ones will be ignored."
+msgstr ""
+"De geselecteerde facturen worden opnieuw aangemaakt. De rest wordt "
+"genegeerd."
+
+msgctxt "help:sale.sale,shipping_date:"
+msgid "When the shipping of goods should start."
+msgstr "Wanneer de verzending van goederen zou moet beginnen."
+
+msgctxt "model:ir.action,name:act_invoice_form"
+msgid "Invoices"
+msgstr "Facturen"
+
+msgctxt "model:ir.action,name:act_open_customer"
+msgid "Parties associated to Sales"
+msgstr "Relaties gekoppeld aan de verkoop"
+
+#, fuzzy
+msgctxt "model:ir.action,name:act_product"
+msgid "Products"
+msgstr "Product"
+
+msgctxt "model:ir.action,name:act_reporting_category"
+msgid "Sales per Category"
+msgstr "Verkoop per categorie"
+
+msgctxt "model:ir.action,name:act_reporting_category_time_series"
+msgid "Sales per Category"
+msgstr "Verkoop per categorie"
+
+msgctxt "model:ir.action,name:act_reporting_category_tree"
+msgid "Sales per Category"
+msgstr "Verkoop per categorie"
+
+msgctxt "model:ir.action,name:act_reporting_country_subdivision_time_series"
+msgid "Sales per Subdivision"
+msgstr "Verkoop per subdivisie"
+
+msgctxt "model:ir.action,name:act_reporting_country_time_series"
+msgid "Sales per Country"
+msgstr "Verkoop per land"
+
+msgctxt "model:ir.action,name:act_reporting_customer"
+msgid "Sales per Customer"
+msgstr "Verkoop per klant"
+
+msgctxt "model:ir.action,name:act_reporting_customer_time_series"
+msgid "Sales per Customer"
+msgstr "Verkoop per klant"
+
+msgctxt "model:ir.action,name:act_reporting_product"
+msgid "Sales per Product"
+msgstr "Verkoop per product"
+
+msgctxt "model:ir.action,name:act_reporting_product_time_series"
+msgid "Sales per Product"
+msgstr "Verkoop per product"
+
+msgctxt "model:ir.action,name:act_reporting_region"
+msgid "Sales per Region"
+msgstr "Verkoop per regio"
+
+msgctxt "model:ir.action,name:act_return_form"
+msgid "Returns"
+msgstr "Retours"
+
+#, fuzzy
+msgctxt "model:ir.action,name:act_sale_configuration_form"
+msgid "Configuration"
+msgstr "Instellingen"
+
+msgctxt "model:ir.action,name:act_sale_form"
+msgid "Sales"
+msgstr "Verkoop"
+
+msgctxt "model:ir.action,name:act_sale_form2"
+msgid "Sales"
+msgstr "Verkoop"
+
+msgctxt "model:ir.action,name:act_sale_invoice_relate"
+msgid "Sales"
+msgstr "Verkoop"
+
+msgctxt "model:ir.action,name:act_sale_move_relate"
+msgid "Moves"
+msgstr "Boekingen"
+
+msgctxt "model:ir.action,name:act_sale_shipment_returns_relate"
+msgid "Sales"
+msgstr "Verkoop"
+
+msgctxt "model:ir.action,name:act_sale_shipments_relate"
+msgid "Sales"
+msgstr "Verkoop"
+
+msgctxt "model:ir.action,name:act_shipment_form"
+msgid "Shipments"
+msgstr "Leveringen"
+
+msgctxt "model:ir.action,name:report_sale"
+msgid "Sale"
+msgstr "Verkoop"
+
+msgctxt "model:ir.action,name:wizard_invoice_handle_exception"
+msgid "Handle Invoice Exception"
+msgstr "Uitzondering factuur afhandeling"
+
+msgctxt "model:ir.action,name:wizard_modify_header"
+msgid "Modify Header"
+msgstr "Wijzig koptekst"
+
+msgctxt "model:ir.action,name:wizard_reporting_region_open"
+msgid "Open Region"
+msgstr "Open Region"
+
+msgctxt "model:ir.action,name:wizard_return_sale"
+msgid "Return Sale"
+msgstr "Terug te nemen (retour)"
+
+msgctxt "model:ir.action,name:wizard_shipment_handle_exception"
+msgid "Handle Shipment Exception"
+msgstr "uitzondering verzendings afhandeling"
+
+msgctxt "model:ir.action.act_window.domain,name:act_sale_form_domain_all"
+msgid "All"
+msgstr "Alle"
+
+msgctxt ""
+"model:ir.action.act_window.domain,name:act_sale_form_domain_confirmed"
+msgid "Confirmed"
+msgstr "Bevestigd"
+
+msgctxt "model:ir.action.act_window.domain,name:act_sale_form_domain_draft"
+msgid "Draft"
+msgstr "Concept"
+
+msgctxt ""
+"model:ir.action.act_window.domain,name:act_sale_form_domain_exception"
+msgid "Exception"
+msgstr "Uitzondering"
+
+msgctxt ""
+"model:ir.action.act_window.domain,name:act_sale_form_domain_processing"
+msgid "Processing"
+msgstr "Verwerking"
+
+msgctxt ""
+"model:ir.action.act_window.domain,name:act_sale_form_domain_quotation"
+msgid "Quotation"
+msgstr "Offerte"
+
+msgctxt "model:ir.message,text:msg_erase_party_pending_sale"
+msgid ""
+"You cannot erase party \"%(party)s\" while they have pending sales with "
+"company \"%(company)s\"."
+msgstr ""
+"U kunt de relatie \"% (party) s\" niet verwijderen terwijl ze facturen in "
+"behandeling hebben bij bedrijf \"%(company)s\"."
+
+msgctxt "model:ir.message,text:msg_sale_customer_location_required"
+msgid ""
+"To process sale \"%(sale)s\" you must set a customer location on party "
+"\"%(party)s\"."
+msgstr ""
+"Om verkoop \"%(sale)s\" te verwerken, moet u een klantlocatie instellen op "
+"relatie\"% \"%(party)s\"."
+
+msgctxt "model:ir.message,text:msg_sale_delete_cancel"
+msgid "To delete sale \"%(sale)s\" you must cancel it."
+msgstr "Om de verkoop \"%(sale)s\" te verwijderen, moet u deze annuleren."
+
+msgctxt "model:ir.message,text:msg_sale_invalid_method"
+msgid ""
+"You cannot use together invoice \"%(invoice_method)s\" and shipment "
+"\"%(shipment_method)s\" on sale \"%(sale)s\"."
+msgstr ""
+"U kunt factuur \"%(invoice_method)s\" en zending \"%(invoice_method)s\" op "
+"de verkoop \"%(sale)s\" niet samen gebruiken."
+
+msgctxt ""
+"model:ir.message,text:msg_sale_invoice_address_required_for_quotation"
+msgid "To get a quote for sale \"%(sale)s\" you must enter an invoice address."
+msgstr ""
+"Om een offerte voor verkoop \"%(sale)s\" te krijgen, moet u een factuuradres"
+" invoeren."
+
+msgctxt "model:ir.message,text:msg_sale_invoice_reset_draft"
+msgid ""
+"You cannot reset invoice \"%(invoice)s\" to draft because it was generated "
+"by a sale."
+msgstr ""
+"U kunt de factuur \"%(invoice)s\" niet opnieuw instellen omdat ze is "
+"gegenereerd door een verkoop."
+
+msgctxt "model:ir.message,text:msg_sale_line_delete_cancel_draft"
+msgid ""
+"To delete line \"%(line)s\" you must cancel or reset to draft sale "
+"\"%(sale)s\"."
+msgstr ""
+"Om lijn \"%(line)s\" te verwijderen, moet u deze annuleren of terug zetten "
+"naar concept verkoop \"%(sale)s\"."
+
+msgctxt "model:ir.message,text:msg_sale_missing_account_revenue"
+msgid "To invoice sale \"%(sale)s\" you must configure a default account revenue."
+msgstr ""
+"Om verkoop \"%(sale)s\"\" te factureren, moet u een "
+"standaardopbrengstrekening configureren."
+
+msgctxt "model:ir.message,text:msg_sale_modify_header_draft"
+msgid "To modify the header of sale \"%(sale)s\", it must be in \"draft\" state."
+msgstr ""
+"Om de hoofding van de verkoop \"%(sale)s\" te wijzigen, moet deze in de "
+"\"ontwerp\" -modus staan."
+
+msgctxt "model:ir.message,text:msg_sale_move_reset_draft"
+msgid ""
+"You cannot reset move \"%(move)s\" to draft because it was generated by a "
+"sale."
+msgstr ""
+"U kunt boeking \"%(move)s\" niet terug zetten naar concept omdat deze is "
+"gegenereerd door een verkoop."
+
+msgctxt "model:ir.message,text:msg_sale_product_missing_account_revenue"
+msgid ""
+"To invoice sale \"%(sale)s\" you must define an account revenue for product "
+"\"%(product)s\"."
+msgstr ""
+"Om de factuur voor de verkoop \"%(sale)s\" te genereren, moet u eerst een "
+"omzetaccount configureren voor het artikel \"%(product)s\"."
+
+msgctxt "model:ir.message,text:msg_sale_reporting_company"
+msgid "Company"
+msgstr "Bedrijf"
+
+msgctxt "model:ir.message,text:msg_sale_reporting_currency"
+msgid "Currency"
+msgstr "Valuta"
+
+msgctxt "model:ir.message,text:msg_sale_reporting_currency_digits"
+msgid "Currency Digits"
+msgstr "Valuta decimalen"
+
+msgctxt "model:ir.message,text:msg_sale_reporting_number"
+msgid "#"
+msgstr "#"
+
+msgctxt "model:ir.message,text:msg_sale_reporting_number_help"
+msgid "Number of sales"
+msgstr "Aantal verkopen"
+
+msgctxt "model:ir.message,text:msg_sale_reporting_revenue"
+msgid "Revenue"
+msgstr "Omzet"
+
+msgctxt "model:ir.message,text:msg_sale_reporting_revenue_trend"
+msgid "Revenue Trend"
+msgstr "Inkomsten trend"
+
+msgctxt ""
+"model:ir.message,text:msg_sale_shipment_address_required_for_quotation"
+msgid "To get a quote for sale \"%(sale)s\" you must enter a shipment address."
+msgstr ""
+"Om een offerte voor verkoop \"%(sale)s\" te krijgen, moet u een verzendadres"
+" invoeren."
+
+msgctxt "model:ir.message,text:msg_sale_warehouse_required_for_quotation"
+msgid "To get a quote for sale \"%(sale)s\" you must enter a warehouse."
+msgstr ""
+"Om een offerte voor verkoop \"%(sale)s\" te krijgen, moet u een magazijn "
+"invoeren."
+
+msgctxt "model:ir.model.button,string:sale_cancel_button"
+msgid "Cancel"
+msgstr "Annuleren"
+
+msgctxt "model:ir.model.button,string:sale_confirm_button"
+msgid "Confirm"
+msgstr "Bevestigen"
+
+msgctxt "model:ir.model.button,string:sale_draft_button"
+msgid "Draft"
+msgstr "Concept"
+
+msgctxt "model:ir.model.button,string:sale_handle_invoice_exception_button"
+msgid "Handle Invoice Exception"
+msgstr "Uitzondering factuur afhandeling"
+
+msgctxt "model:ir.model.button,string:sale_handle_shipment_exception_button"
+msgid "Handle Shipment Exception"
+msgstr "uitzondering verzendings afhandeling"
+
+msgctxt "model:ir.model.button,string:sale_modify_header_button"
+msgid "Modify Header"
+msgstr "Wijzig koptekst"
+
+msgctxt "model:ir.model.button,string:sale_process_button"
+msgid "Process"
+msgstr "Process"
+
+msgctxt "model:ir.model.button,string:sale_quote_button"
+msgid "Quote"
+msgstr "offerte"
+
+#, fuzzy
+msgctxt "model:ir.rule.group,name:rule_group_reporting_category_companies"
+msgid "User in companies"
+msgstr "Gebruiker in het bedrijf"
+
+#, fuzzy
+msgctxt ""
+"model:ir.rule.group,name:rule_group_reporting_category_time_series_companies"
+msgid "User in companies"
+msgstr "Gebruiker in het bedrijf"
+
+#, fuzzy
+msgctxt ""
+"model:ir.rule.group,name:rule_group_reporting_country_subdivision_time_series_companies"
+msgid "User in companies"
+msgstr "Gebruiker in het bedrijf"
+
+#, fuzzy
+msgctxt ""
+"model:ir.rule.group,name:rule_group_reporting_country_time_series_companies"
+msgid "User in companies"
+msgstr "Gebruiker in het bedrijf"
+
+#, fuzzy
+msgctxt "model:ir.rule.group,name:rule_group_reporting_customer_companies"
+msgid "User in companies"
+msgstr "Gebruiker in het bedrijf"
+
+#, fuzzy
+msgctxt ""
+"model:ir.rule.group,name:rule_group_reporting_customer_time_series_companies"
+msgid "User in companies"
+msgstr "Gebruiker in het bedrijf"
+
+#, fuzzy
+msgctxt "model:ir.rule.group,name:rule_group_reporting_product_companies"
+msgid "User in companies"
+msgstr "Gebruiker in het bedrijf"
+
+#, fuzzy
+msgctxt ""
+"model:ir.rule.group,name:rule_group_reporting_product_time_series_companies"
+msgid "User in companies"
+msgstr "Gebruiker in het bedrijf"
+
+#, fuzzy
+msgctxt "model:ir.rule.group,name:rule_group_reporting_region_companies"
+msgid "User in companies"
+msgstr "Gebruiker in het bedrijf"
+
+#, fuzzy
+msgctxt "model:ir.rule.group,name:rule_group_sale_companies"
+msgid "User in companies"
+msgstr "Gebruiker in het bedrijf"
+
+msgctxt "model:ir.sequence,name:sequence_sale"
+msgid "Sale"
+msgstr "Verkoop"
+
+msgctxt "model:ir.sequence.type,name:sequence_type_sale"
+msgid "Sale"
+msgstr "Verkoop"
+
+msgctxt "model:ir.ui.menu,name:menu_configuration"
+msgid "Configuration"
+msgstr "Instellingen"
+
+#, fuzzy
+msgctxt "model:ir.ui.menu,name:menu_customer"
+msgid "Associated to Sales"
+msgstr "Relaties gekoppeld aan verkoop"
+
+#, fuzzy
+msgctxt "model:ir.ui.menu,name:menu_product"
+msgid "Products"
+msgstr "Product"
+
+msgctxt "model:ir.ui.menu,name:menu_reporting"
+msgid "Reporting"
+msgstr "Rapporten"
+
+msgctxt "model:ir.ui.menu,name:menu_reporting_sale"
+msgid "Sales"
+msgstr "Verkoop"
+
+msgctxt "model:ir.ui.menu,name:menu_sale"
+msgid "Sales"
+msgstr "Verkopen"
+
+#, fuzzy
+msgctxt "model:ir.ui.menu,name:menu_sale_configuration"
+msgid "Configuration"
+msgstr "Instellingen"
+
+msgctxt "model:ir.ui.menu,name:menu_sale_form"
+msgid "Sales"
+msgstr "Verkopen"
+
+msgctxt "model:product.configuration.default_lead_time,name:"
+msgid "Product Default Lead Time"
+msgstr "Product standaard levertijd"
+
+msgctxt "model:product.sale.context,name:"
+msgid "Product Sale Context"
+msgstr "Productverkoopcontext"
+
+msgctxt "model:res.group,name:group_sale"
+msgid "Sales"
+msgstr "Verkopen"
+
+msgctxt "model:res.group,name:group_sale_admin"
+msgid "Sales Administrator"
+msgstr "Verkoop beheerder"
+
+msgctxt "model:sale.configuration,name:"
+msgid "Sale Configuration"
+msgstr "Verkoop instellingen"
+
+msgctxt "model:sale.configuration.sale_method,name:"
+msgid "Sale Configuration Sale Method"
+msgstr "Verkoopconfiguratie verkoopmethode"
+
+msgctxt "model:sale.configuration.sequence,name:"
+msgid "Sale Configuration Sequence"
+msgstr "Volgorde verkoopconfiguratie"
+
+msgctxt "model:sale.handle.invoice.exception.ask,name:"
+msgid "Handle Invoice Exception"
+msgstr "Factuur uitzondering vragen"
+
+msgctxt "model:sale.handle.shipment.exception.ask,name:"
+msgid "Handle Shipment Exception"
+msgstr "Afleveren uitzondering vragen"
+
+msgctxt "model:sale.line,name:"
+msgid "Sale Line"
+msgstr "Offerteregel"
+
+msgctxt "model:sale.line-account.tax,name:"
+msgid "Sale Line - Tax"
+msgstr "Offerteregel - belasting"
+
+msgctxt "model:sale.line-ignored-stock.move,name:"
+msgid "Sale Line - Ignored Move"
+msgstr "Offerteregel - genegeerde boeking"
+
+msgctxt "model:sale.line-recreated-stock.move,name:"
+msgid "Sale Line - Recreated Move"
+msgstr "Offerteregel - boeking opnieuw aanmaken"
+
+msgctxt "model:sale.reporting.category,name:"
+msgid "Sale Reporting per Category"
+msgstr "Verkooprapportage per categorie"
+
+msgctxt "model:sale.reporting.category.time_series,name:"
+msgid "Sale Reporting per Category"
+msgstr "Verkooprapportage per categorie"
+
+msgctxt "model:sale.reporting.category.tree,name:"
+msgid "Sale Reporting per Category"
+msgstr "Verkooprapportage per categorie"
+
+msgctxt "model:sale.reporting.context,name:"
+msgid "Sale Reporting Context"
+msgstr "Verkooprapportagecontext"
+
+msgctxt "model:sale.reporting.country,name:"
+msgid "Sale Reporting per Country"
+msgstr "Verkooprapportage per land"
+
+msgctxt "model:sale.reporting.country.subdivision,name:"
+msgid "Sale Reporting per Subdivision"
+msgstr "Verkooprapportage per subdivisie"
+
+msgctxt "model:sale.reporting.country.subdivision.time_series,name:"
+msgid "Sale Reporting per Subdivision"
+msgstr "Verkooprapportage per subdivisie"
+
+msgctxt "model:sale.reporting.country.time_series,name:"
+msgid "Sale Reporting per Country"
+msgstr "Verkooprapportage per land"
+
+msgctxt "model:sale.reporting.customer,name:"
+msgid "Sale Reporting per Customer"
+msgstr "Verkooprapportage per klant"
+
+msgctxt "model:sale.reporting.customer.time_series,name:"
+msgid "Sale Reporting per Customer"
+msgstr "Verkooprapportage per klant"
+
+msgctxt "model:sale.reporting.product,name:"
+msgid "Sale Reporting per Product"
+msgstr "Verkooprapportage per product"
+
+msgctxt "model:sale.reporting.product.time_series,name:"
+msgid "Sale Reporting per Product"
+msgstr "Verkooprapportage per product"
+
+msgctxt "model:sale.reporting.region,name:"
+msgid "Sale Reporting per Region"
+msgstr "Verkooprapportage per regio"
+
+msgctxt "model:sale.return_sale.start,name:"
+msgid "Return Sale"
+msgstr "Terug te nemen (retour)"
+
+msgctxt "model:sale.sale,name:"
+msgid "Sale"
+msgstr "Verkoop"
+
+msgctxt "model:sale.sale-ignored-account.invoice,name:"
+msgid "Sale - Ignored Invoice"
+msgstr "Verkoop - genereerde factuur"
+
+msgctxt "model:sale.sale-recreated-account.invoice,name:"
+msgid "Sale - Recreated Invoice"
+msgstr "Verkoop - factuur opnieuw aanmaken"
+
+msgctxt "report:sale.sale:"
+msgid ":"
+msgstr ":"
+
+msgctxt "report:sale.sale:"
+msgid "Amount"
+msgstr "Bedrag"
+
+msgctxt "report:sale.sale:"
+msgid "Date:"
+msgstr "Datum:"
+
+msgctxt "report:sale.sale:"
+msgid "Description"
+msgstr "Omschrijving"
+
+msgctxt "report:sale.sale:"
+msgid "Description:"
+msgstr "Omschrijving:"
+
+msgctxt "report:sale.sale:"
+msgid "Draft Sale Order"
+msgstr "Ontwerp verkooporder"
+
+msgctxt "report:sale.sale:"
+msgid "Quantity"
+msgstr "Hoeveelheid"
+
+msgctxt "report:sale.sale:"
+msgid "Quotation N°:"
+msgstr "Offerte N °:"
+
+msgctxt "report:sale.sale:"
+msgid "Reference:"
+msgstr "Referentie:"
+
+msgctxt "report:sale.sale:"
+msgid "Sale Order N°:"
+msgstr "Verkooporder nr:"
+
+msgctxt "report:sale.sale:"
+msgid "Taxes"
+msgstr "Belastingen"
+
+msgctxt "report:sale.sale:"
+msgid "Taxes:"
+msgstr "Belastingen:"
+
+msgctxt "report:sale.sale:"
+msgid "Total (excl. taxes):"
+msgstr "Totaal (excl. belasting):"
+
+msgctxt "report:sale.sale:"
+msgid "Total:"
+msgstr "Totaal:"
+
+msgctxt "report:sale.sale:"
+msgid "Unit Price"
+msgstr "Eenheidsprijs"
+
+msgctxt "selection:account.invoice,sale_exception_state:"
+msgid "Ignored"
+msgstr "Genegeerd"
+
+msgctxt "selection:account.invoice,sale_exception_state:"
+msgid "Recreated"
+msgstr "Opnieuw aangemaakt"
+
+msgctxt "selection:sale.line,type:"
+msgid "Comment"
+msgstr "Opmerking"
+
+msgctxt "selection:sale.line,type:"
+msgid "Line"
+msgstr "Regel"
+
+msgctxt "selection:sale.line,type:"
+msgid "Subtotal"
+msgstr "Subtotaal"
+
+msgctxt "selection:sale.line,type:"
+msgid "Title"
+msgstr "Titel"
+
+msgctxt "selection:sale.reporting.context,period:"
+msgid "Day"
+msgstr "Dag"
+
+msgctxt "selection:sale.reporting.context,period:"
+msgid "Month"
+msgstr "Maand"
+
+msgctxt "selection:sale.reporting.context,period:"
+msgid "Year"
+msgstr "Jaar"
+
+msgctxt "selection:sale.sale,invoice_method:"
+msgid "Manual"
+msgstr "Handmatig"
+
+msgctxt "selection:sale.sale,invoice_method:"
+msgid "On Order Processed"
+msgstr "Op bestelling verwerkt(On Order Processed)"
+
+msgctxt "selection:sale.sale,invoice_method:"
+msgid "On Shipment Sent"
+msgstr "Na verzending"
+
+msgctxt "selection:sale.sale,invoice_state:"
+msgid "Exception"
+msgstr "Uitzondering"
+
+msgctxt "selection:sale.sale,invoice_state:"
+msgid "None"
+msgstr "Geen"
+
+msgctxt "selection:sale.sale,invoice_state:"
+msgid "Paid"
+msgstr "Betaald"
+
+msgctxt "selection:sale.sale,invoice_state:"
+msgid "Waiting"
+msgstr "In afwachting"
+
+msgctxt "selection:sale.sale,shipment_method:"
+msgid "Manual"
+msgstr "Handmatig"
+
+msgctxt "selection:sale.sale,shipment_method:"
+msgid "On Invoice Paid"
+msgstr "Na factuur betaald"
+
+msgctxt "selection:sale.sale,shipment_method:"
+msgid "On Order Processed"
+msgstr "Op bestelling verwerkt(On Order Processed)"
+
+msgctxt "selection:sale.sale,shipment_state:"
+msgid "Exception"
+msgstr "Uitzondering"
+
+msgctxt "selection:sale.sale,shipment_state:"
+msgid "None"
+msgstr "Geen"
+
+msgctxt "selection:sale.sale,shipment_state:"
+msgid "Sent"
+msgstr "Verzonden"
+
+msgctxt "selection:sale.sale,shipment_state:"
+msgid "Waiting"
+msgstr "In afwachting"
+
+msgctxt "selection:sale.sale,state:"
+msgid "Cancelled"
+msgstr "Geannuleerd"
+
+msgctxt "selection:sale.sale,state:"
+msgid "Confirmed"
+msgstr "Bevestigd"
+
+msgctxt "selection:sale.sale,state:"
+msgid "Done"
+msgstr "Klaar"
+
+msgctxt "selection:sale.sale,state:"
+msgid "Draft"
+msgstr "Concept"
+
+msgctxt "selection:sale.sale,state:"
+msgid "Processing"
+msgstr "Verwerking"
+
+msgctxt "selection:sale.sale,state:"
+msgid "Quotation"
+msgstr "Offerte"
+
+msgctxt "selection:stock.move,sale_exception_state:"
+msgid "Ignored"
+msgstr "Genegeerd"
+
+msgctxt "selection:stock.move,sale_exception_state:"
+msgid "Recreated"
+msgstr "Opnieuw aangemaakt"
+
+msgctxt "view:party.party:"
+msgid "Sale"
+msgstr "Verkoop"
+
+msgctxt "view:product.template:"
+msgid "Customers"
+msgstr "Klanten"
+
+msgctxt "view:sale.handle.invoice.exception.ask:"
+msgid "Choose invoices to recreate:"
+msgstr "Kies facturen om opnieuw aan te maken:"
+
+msgctxt "view:sale.handle.shipment.exception.ask:"
+msgid "Choose move to recreate:"
+msgstr "Kies boeking om opnieuw aan te maken:"
+
+msgctxt "view:sale.line:"
+msgid "General"
+msgstr "Algemeen"
+
+msgctxt "view:sale.line:"
+msgid "Notes"
+msgstr "Aantekeningen"
+
+msgctxt "view:sale.line:"
+msgid "Taxes"
+msgstr "Belastingen"
+
+msgctxt "view:sale.return_sale.start:"
+msgid "Are you sure to return these/this sale(s)?"
+msgstr "Weet u zeker dat u deze verko(o)p(en) retourneert?"
+
+msgctxt "view:sale.sale:"
+msgid "Other Info"
+msgstr "Aanvullende informatie"
+
+msgctxt "view:sale.sale:"
+msgid "Sale"
+msgstr "Verkoop"
+
+msgctxt "wizard_button:sale.handle.invoice.exception,ask,end:"
+msgid "Cancel"
+msgstr "Annuleren"
+
+msgctxt "wizard_button:sale.handle.invoice.exception,ask,handle:"
+msgid "OK"
+msgstr "Ok"
+
+msgctxt "wizard_button:sale.handle.shipment.exception,ask,end:"
+msgid "Cancel"
+msgstr "Annuleren"
+
+msgctxt "wizard_button:sale.handle.shipment.exception,ask,handle:"
+msgid "OK"
+msgstr "Ok"
+
+msgctxt "wizard_button:sale.modify_header,start,end:"
+msgid "Cancel"
+msgstr "Annuleren"
+
+msgctxt "wizard_button:sale.modify_header,start,modify:"
+msgid "Modify"
+msgstr "Wijzigen"
+
+msgctxt "wizard_button:sale.return_sale,start,end:"
+msgid "Cancel"
+msgstr "Annuleren"
+
+msgctxt "wizard_button:sale.return_sale,start,return_:"
+msgid "Return"
+msgstr "Retours"
diff --git a/modules/sale/locale/pl.po b/modules/sale/locale/pl.po
new file mode 100644
index 0000000000..5c8702d8b4
--- /dev/null
+++ b/modules/sale/locale/pl.po
@@ -0,0 +1,1407 @@
+#
+msgid ""
+msgstr "Content-Type: text/plain; charset=utf-8\n"
+
+msgctxt "field:account.invoice,sale_exception_state:"
+msgid "Exception State"
+msgstr ""
+
+msgctxt "field:account.invoice,sales:"
+msgid "Sales"
+msgstr "Sprzedaż"
+
+msgctxt "field:product.configuration,default_lead_time:"
+msgid "Default Lead Time"
+msgstr ""
+
+#, fuzzy
+msgctxt "field:product.configuration.default_lead_time,company:"
+msgid "Company"
+msgstr "Firma"
+
+msgctxt "field:product.configuration.default_lead_time,default_lead_time:"
+msgid "Default Lead Time"
+msgstr ""
+
+msgctxt "field:product.product,lead_time:"
+msgid "Lead Time"
+msgstr ""
+
+msgctxt "field:product.product,salable:"
+msgid "Salable"
+msgstr ""
+
+msgctxt "field:product.product,sale_price_uom:"
+msgid "Sale Price"
+msgstr "Cena sprzedaży"
+
+msgctxt "field:product.product,sale_uom:"
+msgid "Sale UOM"
+msgstr "Jm sprzedaży"
+
+#, fuzzy
+msgctxt "field:product.sale.context,company:"
+msgid "Company"
+msgstr "Firma"
+
+#, fuzzy
+msgctxt "field:product.sale.context,currency:"
+msgid "Currency"
+msgstr "Waluta"
+
+#, fuzzy
+msgctxt "field:product.sale.context,customer:"
+msgid "Customer"
+msgstr "Odbiorcy"
+
+#, fuzzy
+msgctxt "field:product.sale.context,locations:"
+msgid "Warehouses"
+msgstr "Magazyn"
+
+#, fuzzy
+msgctxt "field:product.sale.context,quantity:"
+msgid "Quantity"
+msgstr "Ilość"
+
+#, fuzzy
+msgctxt "field:product.sale.context,sale_date:"
+msgid "Sale Date"
+msgstr "Data sprzedaży"
+
+msgctxt "field:product.sale.context,stock_date_end:"
+msgid "Stock End Date"
+msgstr ""
+
+msgctxt "field:product.template,lead_time:"
+msgid "Lead Time"
+msgstr ""
+
+msgctxt "field:product.template,salable:"
+msgid "Salable"
+msgstr ""
+
+msgctxt "field:product.template,sale_uom:"
+msgid "Sale UOM"
+msgstr "Jm sprzedaży"
+
+msgctxt "field:sale.configuration,sale_invoice_method:"
+msgid "Sale Invoice Method"
+msgstr ""
+
+msgctxt "field:sale.configuration,sale_process_after:"
+msgid "Process Sale after"
+msgstr ""
+
+msgctxt "field:sale.configuration,sale_sequence:"
+msgid "Sale Sequence"
+msgstr "Sekwencja sprzedaży"
+
+msgctxt "field:sale.configuration,sale_shipment_method:"
+msgid "Sale Shipment Method"
+msgstr "Metoda wysyłki sprzedaży"
+
+msgctxt "field:sale.configuration.sale_method,sale_invoice_method:"
+msgid "Sale Invoice Method"
+msgstr ""
+
+msgctxt "field:sale.configuration.sale_method,sale_shipment_method:"
+msgid "Sale Shipment Method"
+msgstr "Metoda wysyłki sprzedaży"
+
+msgctxt "field:sale.configuration.sequence,company:"
+msgid "Company"
+msgstr "Firma"
+
+msgctxt "field:sale.configuration.sequence,sale_sequence:"
+msgid "Sale Sequence"
+msgstr "Sekwencja sprzedaży"
+
+msgctxt "field:sale.handle.invoice.exception.ask,domain_invoices:"
+msgid "Domain Invoices"
+msgstr ""
+
+msgctxt "field:sale.handle.invoice.exception.ask,recreate_invoices:"
+msgid "Recreate Invoices"
+msgstr ""
+
+msgctxt "field:sale.handle.shipment.exception.ask,domain_moves:"
+msgid "Domain Moves"
+msgstr ""
+
+msgctxt "field:sale.handle.shipment.exception.ask,recreate_moves:"
+msgid "Recreate Moves"
+msgstr ""
+
+#, fuzzy
+msgctxt "field:sale.line,actual_quantity:"
+msgid "Actual Quantity"
+msgstr "Ilość"
+
+msgctxt "field:sale.line,amount:"
+msgid "Amount"
+msgstr ""
+
+#, fuzzy
+msgctxt "field:sale.line,company:"
+msgid "Company"
+msgstr "Firma"
+
+#, fuzzy
+msgctxt "field:sale.line,currency:"
+msgid "Currency"
+msgstr "Waluta"
+
+msgctxt "field:sale.line,description:"
+msgid "Description"
+msgstr "Opis"
+
+msgctxt "field:sale.line,from_location:"
+msgid "From Location"
+msgstr "Z lokalizacji"
+
+msgctxt "field:sale.line,invoice_lines:"
+msgid "Invoice Lines"
+msgstr "Wiersze faktury"
+
+msgctxt "field:sale.line,move_done:"
+msgid "Moves Done"
+msgstr "Wykonane ruchy"
+
+msgctxt "field:sale.line,move_exception:"
+msgid "Moves Exception"
+msgstr ""
+
+msgctxt "field:sale.line,moves:"
+msgid "Moves"
+msgstr "Ruchy"
+
+msgctxt "field:sale.line,moves_ignored:"
+msgid "Ignored Moves"
+msgstr "Zignorowane ruchy"
+
+msgctxt "field:sale.line,moves_recreated:"
+msgid "Recreated Moves"
+msgstr ""
+
+msgctxt "field:sale.line,note:"
+msgid "Note"
+msgstr "Notatka"
+
+msgctxt "field:sale.line,product:"
+msgid "Product"
+msgstr "Produkt"
+
+msgctxt "field:sale.line,product_uom_category:"
+msgid "Product Uom Category"
+msgstr "Kategoria jm produktu"
+
+msgctxt "field:sale.line,quantity:"
+msgid "Quantity"
+msgstr "Ilość"
+
+msgctxt "field:sale.line,sale:"
+msgid "Sale"
+msgstr "Sprzedaż"
+
+msgctxt "field:sale.line,sale_state:"
+msgid "Sale State"
+msgstr "Stan sprzedaży"
+
+msgctxt "field:sale.line,shipping_date:"
+msgid "Shipping Date"
+msgstr "Data wysyłki"
+
+msgctxt "field:sale.line,summary:"
+msgid "Summary"
+msgstr ""
+
+msgctxt "field:sale.line,taxes:"
+msgid "Taxes"
+msgstr "Podatki"
+
+msgctxt "field:sale.line,to_location:"
+msgid "To Location"
+msgstr "Do lokalizacji"
+
+msgctxt "field:sale.line,type:"
+msgid "Type"
+msgstr "Typ"
+
+msgctxt "field:sale.line,unit:"
+msgid "Unit"
+msgstr "Jednostka"
+
+msgctxt "field:sale.line,unit_digits:"
+msgid "Unit Digits"
+msgstr "Cyfry jednostki"
+
+msgctxt "field:sale.line,unit_price:"
+msgid "Unit Price"
+msgstr "Cena jednostkowa"
+
+msgctxt "field:sale.line,warehouse:"
+msgid "Warehouse"
+msgstr "Magazyn"
+
+msgctxt "field:sale.line-account.tax,line:"
+msgid "Sale Line"
+msgstr "Wiersz sprzedaży"
+
+msgctxt "field:sale.line-account.tax,tax:"
+msgid "Tax"
+msgstr "Podatek"
+
+msgctxt "field:sale.line-ignored-stock.move,move:"
+msgid "Move"
+msgstr "Ruch"
+
+msgctxt "field:sale.line-ignored-stock.move,sale_line:"
+msgid "Sale Line"
+msgstr "Wiersz sprzedaży"
+
+msgctxt "field:sale.line-recreated-stock.move,move:"
+msgid "Move"
+msgstr "Ruch"
+
+msgctxt "field:sale.line-recreated-stock.move,sale_line:"
+msgid "Sale Line"
+msgstr "Wiersz sprzedaży"
+
+msgctxt "field:sale.reporting.category,category:"
+msgid "Category"
+msgstr ""
+
+msgctxt "field:sale.reporting.category,time_series:"
+msgid "Time Series"
+msgstr ""
+
+msgctxt "field:sale.reporting.category.time_series,category:"
+msgid "Category"
+msgstr ""
+
+#, fuzzy
+msgctxt "field:sale.reporting.category.time_series,date:"
+msgid "Date"
+msgstr "Data:"
+
+msgctxt "field:sale.reporting.category.tree,children:"
+msgid "Children"
+msgstr ""
+
+#, fuzzy
+msgctxt "field:sale.reporting.category.tree,currency_digits:"
+msgid "Currency Digits"
+msgstr "Cyfry waluty"
+
+msgctxt "field:sale.reporting.category.tree,name:"
+msgid "Name"
+msgstr ""
+
+msgctxt "field:sale.reporting.category.tree,parent:"
+msgid "Parent"
+msgstr ""
+
+msgctxt "field:sale.reporting.category.tree,revenue:"
+msgid "Revenue"
+msgstr ""
+
+#, fuzzy
+msgctxt "field:sale.reporting.context,company:"
+msgid "Company"
+msgstr "Firma"
+
+msgctxt "field:sale.reporting.context,from_date:"
+msgid "From Date"
+msgstr ""
+
+msgctxt "field:sale.reporting.context,period:"
+msgid "Period"
+msgstr ""
+
+msgctxt "field:sale.reporting.context,to_date:"
+msgid "To Date"
+msgstr ""
+
+#, fuzzy
+msgctxt "field:sale.reporting.context,warehouse:"
+msgid "Warehouse"
+msgstr "Magazyn"
+
+msgctxt "field:sale.reporting.country,country:"
+msgid "Country"
+msgstr ""
+
+msgctxt "field:sale.reporting.country,time_series:"
+msgid "Time Series"
+msgstr ""
+
+msgctxt "field:sale.reporting.country.subdivision,country:"
+msgid "Country"
+msgstr ""
+
+msgctxt "field:sale.reporting.country.subdivision,subdivision:"
+msgid "Subdivision"
+msgstr ""
+
+msgctxt "field:sale.reporting.country.subdivision,time_series:"
+msgid "Time Series"
+msgstr ""
+
+msgctxt "field:sale.reporting.country.subdivision.time_series,country:"
+msgid "Country"
+msgstr ""
+
+#, fuzzy
+msgctxt "field:sale.reporting.country.subdivision.time_series,date:"
+msgid "Date"
+msgstr "Data:"
+
+msgctxt "field:sale.reporting.country.subdivision.time_series,subdivision:"
+msgid "Subdivision"
+msgstr ""
+
+msgctxt "field:sale.reporting.country.time_series,country:"
+msgid "Country"
+msgstr ""
+
+#, fuzzy
+msgctxt "field:sale.reporting.country.time_series,date:"
+msgid "Date"
+msgstr "Data:"
+
+#, fuzzy
+msgctxt "field:sale.reporting.customer,customer:"
+msgid "Customer"
+msgstr "Odbiorcy"
+
+msgctxt "field:sale.reporting.customer,time_series:"
+msgid "Time Series"
+msgstr ""
+
+#, fuzzy
+msgctxt "field:sale.reporting.customer.time_series,customer:"
+msgid "Customer"
+msgstr "Odbiorcy"
+
+#, fuzzy
+msgctxt "field:sale.reporting.customer.time_series,date:"
+msgid "Date"
+msgstr "Data:"
+
+#, fuzzy
+msgctxt "field:sale.reporting.product,product:"
+msgid "Product"
+msgstr "Produkt"
+
+msgctxt "field:sale.reporting.product,time_series:"
+msgid "Time Series"
+msgstr ""
+
+#, fuzzy
+msgctxt "field:sale.reporting.product.time_series,date:"
+msgid "Date"
+msgstr "Data:"
+
+#, fuzzy
+msgctxt "field:sale.reporting.product.time_series,product:"
+msgid "Product"
+msgstr "Produkt"
+
+msgctxt "field:sale.reporting.region,children:"
+msgid "Children"
+msgstr ""
+
+msgctxt "field:sale.reporting.region,parent:"
+msgid "Parent"
+msgstr ""
+
+msgctxt "field:sale.reporting.region,region:"
+msgid "Region"
+msgstr ""
+
+msgctxt "field:sale.sale,comment:"
+msgid "Comment"
+msgstr "Komentarz"
+
+msgctxt "field:sale.sale,company:"
+msgid "Company"
+msgstr "Firma"
+
+#, fuzzy
+msgctxt "field:sale.sale,confirmed_by:"
+msgid "Confirmed By"
+msgstr "Confirmed"
+
+msgctxt "field:sale.sale,contact:"
+msgid "Contact"
+msgstr ""
+
+msgctxt "field:sale.sale,currency:"
+msgid "Currency"
+msgstr "Waluta"
+
+msgctxt "field:sale.sale,currency_digits:"
+msgid "Currency Digits"
+msgstr "Cyfry waluty"
+
+msgctxt "field:sale.sale,description:"
+msgid "Description"
+msgstr "Opis"
+
+msgctxt "field:sale.sale,invoice_address:"
+msgid "Invoice Address"
+msgstr "Adres faktury"
+
+msgctxt "field:sale.sale,invoice_method:"
+msgid "Invoice Method"
+msgstr "Metoda faktury"
+
+#, fuzzy
+msgctxt "field:sale.sale,invoice_party:"
+msgid "Invoice Party"
+msgstr "Stan faktury"
+
+msgctxt "field:sale.sale,invoice_state:"
+msgid "Invoice State"
+msgstr "Stan faktury"
+
+msgctxt "field:sale.sale,invoices:"
+msgid "Invoices"
+msgstr "Faktury"
+
+msgctxt "field:sale.sale,invoices_ignored:"
+msgid "Ignored Invoices"
+msgstr "Zignorowane faktury"
+
+msgctxt "field:sale.sale,invoices_recreated:"
+msgid "Recreated Invoices"
+msgstr ""
+
+msgctxt "field:sale.sale,lines:"
+msgid "Lines"
+msgstr "Wiersze"
+
+msgctxt "field:sale.sale,moves:"
+msgid "Moves"
+msgstr "Ruchy"
+
+msgctxt "field:sale.sale,number:"
+msgid "Number"
+msgstr "Numer"
+
+msgctxt "field:sale.sale,origin:"
+msgid "Origin"
+msgstr "Źródło"
+
+msgctxt "field:sale.sale,party:"
+msgid "Party"
+msgstr "Strona"
+
+msgctxt "field:sale.sale,party_lang:"
+msgid "Party Language"
+msgstr "Język strony"
+
+msgctxt "field:sale.sale,payment_term:"
+msgid "Payment Term"
+msgstr "Termin płatności"
+
+#, fuzzy
+msgctxt "field:sale.sale,quoted_by:"
+msgid "Quoted By"
+msgstr "Quote"
+
+msgctxt "field:sale.sale,reference:"
+msgid "Reference"
+msgstr "Referencja"
+
+msgctxt "field:sale.sale,sale_date:"
+msgid "Sale Date"
+msgstr "Data sprzedaży"
+
+msgctxt "field:sale.sale,shipment_address:"
+msgid "Shipment Address"
+msgstr "Adres wysyłki"
+
+msgctxt "field:sale.sale,shipment_method:"
+msgid "Shipment Method"
+msgstr "Metoda wysyłki"
+
+msgctxt "field:sale.sale,shipment_party:"
+msgid "Shipment Party"
+msgstr "Strona wysyłki"
+
+msgctxt "field:sale.sale,shipment_returns:"
+msgid "Shipment Returns"
+msgstr "Zwroty wysyłki"
+
+msgctxt "field:sale.sale,shipment_state:"
+msgid "Shipment State"
+msgstr "Stan wysyłki"
+
+msgctxt "field:sale.sale,shipments:"
+msgid "Shipments"
+msgstr "Wysyłki"
+
+#, fuzzy
+msgctxt "field:sale.sale,shipping_date:"
+msgid "Shipping Date"
+msgstr "Data wysyłki"
+
+msgctxt "field:sale.sale,state:"
+msgid "State"
+msgstr "Stan"
+
+msgctxt "field:sale.sale,tax_amount:"
+msgid "Tax"
+msgstr "Podatek"
+
+msgctxt "field:sale.sale,tax_amount_cache:"
+msgid "Tax Cache"
+msgstr ""
+
+msgctxt "field:sale.sale,total_amount:"
+msgid "Total"
+msgstr "Razem"
+
+#, fuzzy
+msgctxt "field:sale.sale,total_amount_cache:"
+msgid "Total Cache"
+msgstr "Podatek razem"
+
+msgctxt "field:sale.sale,untaxed_amount:"
+msgid "Untaxed"
+msgstr ""
+
+msgctxt "field:sale.sale,untaxed_amount_cache:"
+msgid "Untaxed Cache"
+msgstr ""
+
+msgctxt "field:sale.sale,warehouse:"
+msgid "Warehouse"
+msgstr "Magazyn"
+
+msgctxt "field:sale.sale-ignored-account.invoice,invoice:"
+msgid "Invoice"
+msgstr "Faktura"
+
+msgctxt "field:sale.sale-ignored-account.invoice,sale:"
+msgid "Sale"
+msgstr "Sprzedaż"
+
+msgctxt "field:sale.sale-recreated-account.invoice,invoice:"
+msgid "Invoice"
+msgstr "Faktura"
+
+msgctxt "field:sale.sale-recreated-account.invoice,sale:"
+msgid "Sale"
+msgstr "Sprzedaż"
+
+msgctxt "field:stock.move,sale:"
+msgid "Sale"
+msgstr "Sprzedaż"
+
+msgctxt "field:stock.move,sale_exception_state:"
+msgid "Exception State"
+msgstr ""
+
+msgctxt "help:product.configuration,default_lead_time:"
+msgid ""
+"The time from confirming the sales order to sending the products.\n"
+"Used for products without a lead time."
+msgstr ""
+
+msgctxt "help:product.product,lead_time:"
+msgid ""
+"The time from confirming the sales order to sending the products.\n"
+"If empty the default lead time from the configuration is used."
+msgstr ""
+
+msgctxt "help:product.template,lead_time:"
+msgid ""
+"The time from confirming the sales order to sending the products.\n"
+"If empty the default lead time from the configuration is used."
+msgstr ""
+
+msgctxt "help:sale.configuration,sale_process_after:"
+msgid ""
+"The grace period during which confirmed sale can still be reset to draft.\n"
+"Applied if a worker queue is activated."
+msgstr ""
+
+msgctxt "help:sale.handle.invoice.exception.ask,recreate_invoices:"
+msgid ""
+"The selected invoices will be recreated. The other ones will be ignored."
+msgstr ""
+
+msgctxt "help:sale.sale,shipping_date:"
+msgid "When the shipping of goods should start."
+msgstr ""
+
+#, fuzzy
+msgctxt "model:ir.action,name:act_invoice_form"
+msgid "Invoices"
+msgstr "Invoices"
+
+msgctxt "model:ir.action,name:act_open_customer"
+msgid "Parties associated to Sales"
+msgstr "Parties associated to Sales"
+
+#, fuzzy
+msgctxt "model:ir.action,name:act_product"
+msgid "Products"
+msgstr "Produkt"
+
+msgctxt "model:ir.action,name:act_reporting_category"
+msgid "Sales per Category"
+msgstr "Sales per Category"
+
+msgctxt "model:ir.action,name:act_reporting_category_time_series"
+msgid "Sales per Category"
+msgstr "Sales per Category"
+
+msgctxt "model:ir.action,name:act_reporting_category_tree"
+msgid "Sales per Category"
+msgstr "Sales per Category"
+
+msgctxt "model:ir.action,name:act_reporting_country_subdivision_time_series"
+msgid "Sales per Subdivision"
+msgstr "Sales per Subdivision"
+
+msgctxt "model:ir.action,name:act_reporting_country_time_series"
+msgid "Sales per Country"
+msgstr "Sales per Country"
+
+msgctxt "model:ir.action,name:act_reporting_customer"
+msgid "Sales per Customer"
+msgstr "Sales per Customer"
+
+msgctxt "model:ir.action,name:act_reporting_customer_time_series"
+msgid "Sales per Customer"
+msgstr "Sales per Customer"
+
+msgctxt "model:ir.action,name:act_reporting_product"
+msgid "Sales per Product"
+msgstr "Sales per Product"
+
+msgctxt "model:ir.action,name:act_reporting_product_time_series"
+msgid "Sales per Product"
+msgstr "Sales per Product"
+
+msgctxt "model:ir.action,name:act_reporting_region"
+msgid "Sales per Region"
+msgstr "Sales per Region"
+
+#, fuzzy
+msgctxt "model:ir.action,name:act_return_form"
+msgid "Returns"
+msgstr "Returns"
+
+#, fuzzy
+msgctxt "model:ir.action,name:act_sale_configuration_form"
+msgid "Configuration"
+msgstr "Konfiguracja"
+
+#, fuzzy
+msgctxt "model:ir.action,name:act_sale_form"
+msgid "Sales"
+msgstr "Sales"
+
+#, fuzzy
+msgctxt "model:ir.action,name:act_sale_form2"
+msgid "Sales"
+msgstr "Sales"
+
+#, fuzzy
+msgctxt "model:ir.action,name:act_sale_invoice_relate"
+msgid "Sales"
+msgstr "Sales"
+
+#, fuzzy
+msgctxt "model:ir.action,name:act_sale_move_relate"
+msgid "Moves"
+msgstr "Ruchy"
+
+msgctxt "model:ir.action,name:act_sale_shipment_returns_relate"
+msgid "Sales"
+msgstr "Sales"
+
+#, fuzzy
+msgctxt "model:ir.action,name:act_sale_shipments_relate"
+msgid "Sales"
+msgstr "Sales"
+
+#, fuzzy
+msgctxt "model:ir.action,name:act_shipment_form"
+msgid "Shipments"
+msgstr "Shipments"
+
+#, fuzzy
+msgctxt "model:ir.action,name:report_sale"
+msgid "Sale"
+msgstr "Sale"
+
+msgctxt "model:ir.action,name:wizard_invoice_handle_exception"
+msgid "Handle Invoice Exception"
+msgstr "Handle Invoice Exception"
+
+msgctxt "model:ir.action,name:wizard_modify_header"
+msgid "Modify Header"
+msgstr "Modify Header"
+
+msgctxt "model:ir.action,name:wizard_reporting_region_open"
+msgid "Open Region"
+msgstr "Open Region"
+
+#, fuzzy
+msgctxt "model:ir.action,name:wizard_return_sale"
+msgid "Return Sale"
+msgstr "Return Sale"
+
+msgctxt "model:ir.action,name:wizard_shipment_handle_exception"
+msgid "Handle Shipment Exception"
+msgstr "Handle Shipment Exception"
+
+#, fuzzy
+msgctxt "model:ir.action.act_window.domain,name:act_sale_form_domain_all"
+msgid "All"
+msgstr "All"
+
+#, fuzzy
+msgctxt ""
+"model:ir.action.act_window.domain,name:act_sale_form_domain_confirmed"
+msgid "Confirmed"
+msgstr "Confirmed"
+
+#, fuzzy
+msgctxt "model:ir.action.act_window.domain,name:act_sale_form_domain_draft"
+msgid "Draft"
+msgstr "Draft"
+
+#, fuzzy
+msgctxt ""
+"model:ir.action.act_window.domain,name:act_sale_form_domain_exception"
+msgid "Exception"
+msgstr "Wyjątek"
+
+#, fuzzy
+msgctxt ""
+"model:ir.action.act_window.domain,name:act_sale_form_domain_processing"
+msgid "Processing"
+msgstr "Processing"
+
+#, fuzzy
+msgctxt ""
+"model:ir.action.act_window.domain,name:act_sale_form_domain_quotation"
+msgid "Quotation"
+msgstr "Quotation"
+
+msgctxt "model:ir.message,text:msg_erase_party_pending_sale"
+msgid ""
+"You cannot erase party \"%(party)s\" while they have pending sales with "
+"company \"%(company)s\"."
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_sale_customer_location_required"
+msgid ""
+"To process sale \"%(sale)s\" you must set a customer location on party "
+"\"%(party)s\"."
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_sale_delete_cancel"
+msgid "To delete sale \"%(sale)s\" you must cancel it."
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_sale_invalid_method"
+msgid ""
+"You cannot use together invoice \"%(invoice_method)s\" and shipment "
+"\"%(shipment_method)s\" on sale \"%(sale)s\"."
+msgstr ""
+
+msgctxt ""
+"model:ir.message,text:msg_sale_invoice_address_required_for_quotation"
+msgid "To get a quote for sale \"%(sale)s\" you must enter an invoice address."
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_sale_invoice_reset_draft"
+msgid ""
+"You cannot reset invoice \"%(invoice)s\" to draft because it was generated "
+"by a sale."
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_sale_line_delete_cancel_draft"
+msgid ""
+"To delete line \"%(line)s\" you must cancel or reset to draft sale "
+"\"%(sale)s\"."
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_sale_missing_account_revenue"
+msgid "To invoice sale \"%(sale)s\" you must configure a default account revenue."
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_sale_modify_header_draft"
+msgid "To modify the header of sale \"%(sale)s\", it must be in \"draft\" state."
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_sale_move_reset_draft"
+msgid ""
+"You cannot reset move \"%(move)s\" to draft because it was generated by a "
+"sale."
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_sale_product_missing_account_revenue"
+msgid ""
+"To invoice sale \"%(sale)s\" you must define an account revenue for product "
+"\"%(product)s\"."
+msgstr ""
+
+#, fuzzy
+msgctxt "model:ir.message,text:msg_sale_reporting_company"
+msgid "Company"
+msgstr "Firma"
+
+#, fuzzy
+msgctxt "model:ir.message,text:msg_sale_reporting_currency"
+msgid "Currency"
+msgstr "Waluta"
+
+#, fuzzy
+msgctxt "model:ir.message,text:msg_sale_reporting_currency_digits"
+msgid "Currency Digits"
+msgstr "Cyfry waluty"
+
+#, fuzzy
+msgctxt "model:ir.message,text:msg_sale_reporting_number"
+msgid "#"
+msgstr "#"
+
+msgctxt "model:ir.message,text:msg_sale_reporting_number_help"
+msgid "Number of sales"
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_sale_reporting_revenue"
+msgid "Revenue"
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_sale_reporting_revenue_trend"
+msgid "Revenue Trend"
+msgstr ""
+
+msgctxt ""
+"model:ir.message,text:msg_sale_shipment_address_required_for_quotation"
+msgid "To get a quote for sale \"%(sale)s\" you must enter a shipment address."
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_sale_warehouse_required_for_quotation"
+msgid "To get a quote for sale \"%(sale)s\" you must enter a warehouse."
+msgstr ""
+
+msgctxt "model:ir.model.button,string:sale_cancel_button"
+msgid "Cancel"
+msgstr "Cancel"
+
+msgctxt "model:ir.model.button,string:sale_confirm_button"
+msgid "Confirm"
+msgstr "Confirm"
+
+msgctxt "model:ir.model.button,string:sale_draft_button"
+msgid "Draft"
+msgstr "Draft"
+
+msgctxt "model:ir.model.button,string:sale_handle_invoice_exception_button"
+msgid "Handle Invoice Exception"
+msgstr "Handle Invoice Exception"
+
+msgctxt "model:ir.model.button,string:sale_handle_shipment_exception_button"
+msgid "Handle Shipment Exception"
+msgstr "Handle Shipment Exception"
+
+msgctxt "model:ir.model.button,string:sale_modify_header_button"
+msgid "Modify Header"
+msgstr "Modify Header"
+
+msgctxt "model:ir.model.button,string:sale_process_button"
+msgid "Process"
+msgstr "Process"
+
+msgctxt "model:ir.model.button,string:sale_quote_button"
+msgid "Quote"
+msgstr "Quote"
+
+msgctxt "model:ir.rule.group,name:rule_group_reporting_category_companies"
+msgid "User in companies"
+msgstr ""
+
+msgctxt ""
+"model:ir.rule.group,name:rule_group_reporting_category_time_series_companies"
+msgid "User in companies"
+msgstr ""
+
+msgctxt ""
+"model:ir.rule.group,name:rule_group_reporting_country_subdivision_time_series_companies"
+msgid "User in companies"
+msgstr ""
+
+msgctxt ""
+"model:ir.rule.group,name:rule_group_reporting_country_time_series_companies"
+msgid "User in companies"
+msgstr ""
+
+msgctxt "model:ir.rule.group,name:rule_group_reporting_customer_companies"
+msgid "User in companies"
+msgstr ""
+
+msgctxt ""
+"model:ir.rule.group,name:rule_group_reporting_customer_time_series_companies"
+msgid "User in companies"
+msgstr ""
+
+msgctxt "model:ir.rule.group,name:rule_group_reporting_product_companies"
+msgid "User in companies"
+msgstr ""
+
+msgctxt ""
+"model:ir.rule.group,name:rule_group_reporting_product_time_series_companies"
+msgid "User in companies"
+msgstr ""
+
+msgctxt "model:ir.rule.group,name:rule_group_reporting_region_companies"
+msgid "User in companies"
+msgstr ""
+
+msgctxt "model:ir.rule.group,name:rule_group_sale_companies"
+msgid "User in companies"
+msgstr ""
+
+#, fuzzy
+msgctxt "model:ir.sequence,name:sequence_sale"
+msgid "Sale"
+msgstr "Sale"
+
+#, fuzzy
+msgctxt "model:ir.sequence.type,name:sequence_type_sale"
+msgid "Sale"
+msgstr "Sale"
+
+msgctxt "model:ir.ui.menu,name:menu_configuration"
+msgid "Configuration"
+msgstr "Konfiguracja"
+
+#, fuzzy
+msgctxt "model:ir.ui.menu,name:menu_customer"
+msgid "Associated to Sales"
+msgstr "Parties associated to Sales"
+
+#, fuzzy
+msgctxt "model:ir.ui.menu,name:menu_product"
+msgid "Products"
+msgstr "Produkt"
+
+msgctxt "model:ir.ui.menu,name:menu_reporting"
+msgid "Reporting"
+msgstr "Reporting"
+
+msgctxt "model:ir.ui.menu,name:menu_reporting_sale"
+msgid "Sales"
+msgstr "Sales"
+
+#, fuzzy
+msgctxt "model:ir.ui.menu,name:menu_sale"
+msgid "Sales"
+msgstr "Sales"
+
+#, fuzzy
+msgctxt "model:ir.ui.menu,name:menu_sale_configuration"
+msgid "Configuration"
+msgstr "Konfiguracja"
+
+#, fuzzy
+msgctxt "model:ir.ui.menu,name:menu_sale_form"
+msgid "Sales"
+msgstr "Sales"
+
+msgctxt "model:product.configuration.default_lead_time,name:"
+msgid "Product Default Lead Time"
+msgstr ""
+
+msgctxt "model:product.sale.context,name:"
+msgid "Product Sale Context"
+msgstr ""
+
+#, fuzzy
+msgctxt "model:res.group,name:group_sale"
+msgid "Sales"
+msgstr "Sales"
+
+#, fuzzy
+msgctxt "model:res.group,name:group_sale_admin"
+msgid "Sales Administrator"
+msgstr "Sales Administrator"
+
+msgctxt "model:sale.configuration,name:"
+msgid "Sale Configuration"
+msgstr "Konfiguracja sprzedaży"
+
+msgctxt "model:sale.configuration.sale_method,name:"
+msgid "Sale Configuration Sale Method"
+msgstr ""
+
+msgctxt "model:sale.configuration.sequence,name:"
+msgid "Sale Configuration Sequence"
+msgstr "Sekwencja konfiguracji sprzedaży"
+
+#, fuzzy
+msgctxt "model:sale.handle.invoice.exception.ask,name:"
+msgid "Handle Invoice Exception"
+msgstr "Handle Invoice Exception"
+
+#, fuzzy
+msgctxt "model:sale.handle.shipment.exception.ask,name:"
+msgid "Handle Shipment Exception"
+msgstr "Handle Shipment Exception"
+
+msgctxt "model:sale.line,name:"
+msgid "Sale Line"
+msgstr "Wiersz sprzedaży"
+
+msgctxt "model:sale.line-account.tax,name:"
+msgid "Sale Line - Tax"
+msgstr "Wiersz sprzedaży - Podatek"
+
+msgctxt "model:sale.line-ignored-stock.move,name:"
+msgid "Sale Line - Ignored Move"
+msgstr "Wiersz sprzedaży - Zignorowany ruch"
+
+msgctxt "model:sale.line-recreated-stock.move,name:"
+msgid "Sale Line - Recreated Move"
+msgstr ""
+
+msgctxt "model:sale.reporting.category,name:"
+msgid "Sale Reporting per Category"
+msgstr ""
+
+msgctxt "model:sale.reporting.category.time_series,name:"
+msgid "Sale Reporting per Category"
+msgstr ""
+
+msgctxt "model:sale.reporting.category.tree,name:"
+msgid "Sale Reporting per Category"
+msgstr ""
+
+msgctxt "model:sale.reporting.context,name:"
+msgid "Sale Reporting Context"
+msgstr ""
+
+msgctxt "model:sale.reporting.country,name:"
+msgid "Sale Reporting per Country"
+msgstr ""
+
+msgctxt "model:sale.reporting.country.subdivision,name:"
+msgid "Sale Reporting per Subdivision"
+msgstr ""
+
+msgctxt "model:sale.reporting.country.subdivision.time_series,name:"
+msgid "Sale Reporting per Subdivision"
+msgstr ""
+
+msgctxt "model:sale.reporting.country.time_series,name:"
+msgid "Sale Reporting per Country"
+msgstr ""
+
+msgctxt "model:sale.reporting.customer,name:"
+msgid "Sale Reporting per Customer"
+msgstr ""
+
+msgctxt "model:sale.reporting.customer.time_series,name:"
+msgid "Sale Reporting per Customer"
+msgstr ""
+
+msgctxt "model:sale.reporting.product,name:"
+msgid "Sale Reporting per Product"
+msgstr ""
+
+msgctxt "model:sale.reporting.product.time_series,name:"
+msgid "Sale Reporting per Product"
+msgstr ""
+
+msgctxt "model:sale.reporting.region,name:"
+msgid "Sale Reporting per Region"
+msgstr ""
+
+msgctxt "model:sale.return_sale.start,name:"
+msgid "Return Sale"
+msgstr "Zwrot sprzedaży"
+
+msgctxt "model:sale.sale,name:"
+msgid "Sale"
+msgstr "Sprzedaż"
+
+msgctxt "model:sale.sale-ignored-account.invoice,name:"
+msgid "Sale - Ignored Invoice"
+msgstr "Sprzedaż - Zignorowana faktura"
+
+msgctxt "model:sale.sale-recreated-account.invoice,name:"
+msgid "Sale - Recreated Invoice"
+msgstr ""
+
+msgctxt "report:sale.sale:"
+msgid ":"
+msgstr ":"
+
+msgctxt "report:sale.sale:"
+msgid "Amount"
+msgstr ""
+
+msgctxt "report:sale.sale:"
+msgid "Date:"
+msgstr "Data:"
+
+msgctxt "report:sale.sale:"
+msgid "Description"
+msgstr "Opis"
+
+msgctxt "report:sale.sale:"
+msgid "Description:"
+msgstr "Opis:"
+
+msgctxt "report:sale.sale:"
+msgid "Draft Sale Order"
+msgstr ""
+
+msgctxt "report:sale.sale:"
+msgid "Quantity"
+msgstr "Ilość"
+
+msgctxt "report:sale.sale:"
+msgid "Quotation N°:"
+msgstr ""
+
+msgctxt "report:sale.sale:"
+msgid "Reference:"
+msgstr "Referencja:"
+
+msgctxt "report:sale.sale:"
+msgid "Sale Order N°:"
+msgstr ""
+
+msgctxt "report:sale.sale:"
+msgid "Taxes"
+msgstr "Podatki"
+
+msgctxt "report:sale.sale:"
+msgid "Taxes:"
+msgstr "Podatki:"
+
+msgctxt "report:sale.sale:"
+msgid "Total (excl. taxes):"
+msgstr ""
+
+msgctxt "report:sale.sale:"
+msgid "Total:"
+msgstr "Razem:"
+
+msgctxt "report:sale.sale:"
+msgid "Unit Price"
+msgstr "Cena jednostkowa"
+
+msgctxt "selection:account.invoice,sale_exception_state:"
+msgid "Ignored"
+msgstr "Zignorowano"
+
+msgctxt "selection:account.invoice,sale_exception_state:"
+msgid "Recreated"
+msgstr ""
+
+msgctxt "selection:sale.line,type:"
+msgid "Comment"
+msgstr "Komentarz"
+
+msgctxt "selection:sale.line,type:"
+msgid "Line"
+msgstr "Wiersz"
+
+msgctxt "selection:sale.line,type:"
+msgid "Subtotal"
+msgstr ""
+
+msgctxt "selection:sale.line,type:"
+msgid "Title"
+msgstr "Tytuł"
+
+msgctxt "selection:sale.reporting.context,period:"
+msgid "Day"
+msgstr ""
+
+msgctxt "selection:sale.reporting.context,period:"
+msgid "Month"
+msgstr ""
+
+msgctxt "selection:sale.reporting.context,period:"
+msgid "Year"
+msgstr ""
+
+msgctxt "selection:sale.sale,invoice_method:"
+msgid "Manual"
+msgstr ""
+
+msgctxt "selection:sale.sale,invoice_method:"
+msgid "On Order Processed"
+msgstr ""
+
+msgctxt "selection:sale.sale,invoice_method:"
+msgid "On Shipment Sent"
+msgstr ""
+
+msgctxt "selection:sale.sale,invoice_state:"
+msgid "Exception"
+msgstr "Wyjątek"
+
+msgctxt "selection:sale.sale,invoice_state:"
+msgid "None"
+msgstr "Brak"
+
+msgctxt "selection:sale.sale,invoice_state:"
+msgid "Paid"
+msgstr ""
+
+msgctxt "selection:sale.sale,invoice_state:"
+msgid "Waiting"
+msgstr ""
+
+msgctxt "selection:sale.sale,shipment_method:"
+msgid "Manual"
+msgstr ""
+
+msgctxt "selection:sale.sale,shipment_method:"
+msgid "On Invoice Paid"
+msgstr ""
+
+msgctxt "selection:sale.sale,shipment_method:"
+msgid "On Order Processed"
+msgstr ""
+
+msgctxt "selection:sale.sale,shipment_state:"
+msgid "Exception"
+msgstr "Wyjątek"
+
+msgctxt "selection:sale.sale,shipment_state:"
+msgid "None"
+msgstr "Brak"
+
+msgctxt "selection:sale.sale,shipment_state:"
+msgid "Sent"
+msgstr "Wysłano"
+
+msgctxt "selection:sale.sale,shipment_state:"
+msgid "Waiting"
+msgstr ""
+
+#, fuzzy
+msgctxt "selection:sale.sale,state:"
+msgid "Cancelled"
+msgstr "Anulowano"
+
+msgctxt "selection:sale.sale,state:"
+msgid "Confirmed"
+msgstr "Potwierdzono"
+
+msgctxt "selection:sale.sale,state:"
+msgid "Done"
+msgstr "Wykonano"
+
+#, fuzzy
+msgctxt "selection:sale.sale,state:"
+msgid "Draft"
+msgstr "Draft"
+
+#, fuzzy
+msgctxt "selection:sale.sale,state:"
+msgid "Processing"
+msgstr "Processing"
+
+#, fuzzy
+msgctxt "selection:sale.sale,state:"
+msgid "Quotation"
+msgstr "Quotation"
+
+msgctxt "selection:stock.move,sale_exception_state:"
+msgid "Ignored"
+msgstr "Zignorowano"
+
+msgctxt "selection:stock.move,sale_exception_state:"
+msgid "Recreated"
+msgstr ""
+
+msgctxt "view:party.party:"
+msgid "Sale"
+msgstr "Sprzedaż"
+
+msgctxt "view:product.template:"
+msgid "Customers"
+msgstr "Odbiorcy"
+
+msgctxt "view:sale.handle.invoice.exception.ask:"
+msgid "Choose invoices to recreate:"
+msgstr ""
+
+msgctxt "view:sale.handle.shipment.exception.ask:"
+msgid "Choose move to recreate:"
+msgstr ""
+
+msgctxt "view:sale.line:"
+msgid "General"
+msgstr "Ogólne"
+
+msgctxt "view:sale.line:"
+msgid "Notes"
+msgstr "Notatki"
+
+msgctxt "view:sale.line:"
+msgid "Taxes"
+msgstr "Podatki"
+
+#, fuzzy
+msgctxt "view:sale.return_sale.start:"
+msgid "Are you sure to return these/this sale(s)?"
+msgstr "Czy na pewno zwrócić te/tę dostawę(y)?"
+
+msgctxt "view:sale.sale:"
+msgid "Other Info"
+msgstr "Inne informacje"
+
+msgctxt "view:sale.sale:"
+msgid "Sale"
+msgstr "Sprzedaż"
+
+msgctxt "wizard_button:sale.handle.invoice.exception,ask,end:"
+msgid "Cancel"
+msgstr "Anuluj"
+
+msgctxt "wizard_button:sale.handle.invoice.exception,ask,handle:"
+msgid "OK"
+msgstr "OK"
+
+msgctxt "wizard_button:sale.handle.shipment.exception,ask,end:"
+msgid "Cancel"
+msgstr "Anuluj"
+
+msgctxt "wizard_button:sale.handle.shipment.exception,ask,handle:"
+msgid "OK"
+msgstr "OK"
+
+#, fuzzy
+msgctxt "wizard_button:sale.modify_header,start,end:"
+msgid "Cancel"
+msgstr "Anuluj"
+
+msgctxt "wizard_button:sale.modify_header,start,modify:"
+msgid "Modify"
+msgstr ""
+
+msgctxt "wizard_button:sale.return_sale,start,end:"
+msgid "Cancel"
+msgstr "Anuluj"
+
+msgctxt "wizard_button:sale.return_sale,start,return_:"
+msgid "Return"
+msgstr "Zwrot"
diff --git a/modules/sale/locale/pt.po b/modules/sale/locale/pt.po
new file mode 100644
index 0000000000..8bd2dc1642
--- /dev/null
+++ b/modules/sale/locale/pt.po
@@ -0,0 +1,1412 @@
+#
+msgid ""
+msgstr "Content-Type: text/plain; charset=utf-8\n"
+
+msgctxt "field:account.invoice,sale_exception_state:"
+msgid "Exception State"
+msgstr "Estado da exceção"
+
+msgctxt "field:account.invoice,sales:"
+msgid "Sales"
+msgstr "Vendas"
+
+#, fuzzy
+msgctxt "field:product.configuration,default_lead_time:"
+msgid "Default Lead Time"
+msgstr "Tempo de Espera"
+
+#, fuzzy
+msgctxt "field:product.configuration.default_lead_time,company:"
+msgid "Company"
+msgstr "Empresa"
+
+#, fuzzy
+msgctxt "field:product.configuration.default_lead_time,default_lead_time:"
+msgid "Default Lead Time"
+msgstr "Tempo de Espera"
+
+msgctxt "field:product.product,lead_time:"
+msgid "Lead Time"
+msgstr "Tempo de Espera"
+
+msgctxt "field:product.product,salable:"
+msgid "Salable"
+msgstr "Vendável"
+
+msgctxt "field:product.product,sale_price_uom:"
+msgid "Sale Price"
+msgstr "Preço de Venda"
+
+msgctxt "field:product.product,sale_uom:"
+msgid "Sale UOM"
+msgstr "UDM para venda"
+
+#, fuzzy
+msgctxt "field:product.sale.context,company:"
+msgid "Company"
+msgstr "Empresa"
+
+#, fuzzy
+msgctxt "field:product.sale.context,currency:"
+msgid "Currency"
+msgstr "Moeda"
+
+#, fuzzy
+msgctxt "field:product.sale.context,customer:"
+msgid "Customer"
+msgstr "Clientes"
+
+#, fuzzy
+msgctxt "field:product.sale.context,locations:"
+msgid "Warehouses"
+msgstr "Almoxarifado"
+
+#, fuzzy
+msgctxt "field:product.sale.context,quantity:"
+msgid "Quantity"
+msgstr "Quantidade"
+
+#, fuzzy
+msgctxt "field:product.sale.context,sale_date:"
+msgid "Sale Date"
+msgstr "Data da venda"
+
+msgctxt "field:product.sale.context,stock_date_end:"
+msgid "Stock End Date"
+msgstr ""
+
+msgctxt "field:product.template,lead_time:"
+msgid "Lead Time"
+msgstr "Tempo de Espera"
+
+msgctxt "field:product.template,salable:"
+msgid "Salable"
+msgstr "Vendável"
+
+msgctxt "field:product.template,sale_uom:"
+msgid "Sale UOM"
+msgstr "UM para venda"
+
+msgctxt "field:sale.configuration,sale_invoice_method:"
+msgid "Sale Invoice Method"
+msgstr "Método da fatura da venda"
+
+msgctxt "field:sale.configuration,sale_process_after:"
+msgid "Process Sale after"
+msgstr ""
+
+msgctxt "field:sale.configuration,sale_sequence:"
+msgid "Sale Sequence"
+msgstr "Sequência de Venda"
+
+msgctxt "field:sale.configuration,sale_shipment_method:"
+msgid "Sale Shipment Method"
+msgstr "Método da expedição da venda"
+
+msgctxt "field:sale.configuration.sale_method,sale_invoice_method:"
+msgid "Sale Invoice Method"
+msgstr "Método da Fatura de Venda"
+
+msgctxt "field:sale.configuration.sale_method,sale_shipment_method:"
+msgid "Sale Shipment Method"
+msgstr "Método da Remessa ao Cliente"
+
+msgctxt "field:sale.configuration.sequence,company:"
+msgid "Company"
+msgstr "Empresa"
+
+msgctxt "field:sale.configuration.sequence,sale_sequence:"
+msgid "Sale Sequence"
+msgstr "Sequência de Venda"
+
+msgctxt "field:sale.handle.invoice.exception.ask,domain_invoices:"
+msgid "Domain Invoices"
+msgstr "Faturas do domínio"
+
+msgctxt "field:sale.handle.invoice.exception.ask,recreate_invoices:"
+msgid "Recreate Invoices"
+msgstr "Recriar faturas"
+
+msgctxt "field:sale.handle.shipment.exception.ask,domain_moves:"
+msgid "Domain Moves"
+msgstr "Movimentações no domínio"
+
+msgctxt "field:sale.handle.shipment.exception.ask,recreate_moves:"
+msgid "Recreate Moves"
+msgstr "Recriar movimentações"
+
+#, fuzzy
+msgctxt "field:sale.line,actual_quantity:"
+msgid "Actual Quantity"
+msgstr "Quantidade"
+
+msgctxt "field:sale.line,amount:"
+msgid "Amount"
+msgstr "Quantidade"
+
+#, fuzzy
+msgctxt "field:sale.line,company:"
+msgid "Company"
+msgstr "Empresa"
+
+#, fuzzy
+msgctxt "field:sale.line,currency:"
+msgid "Currency"
+msgstr "Moeda"
+
+msgctxt "field:sale.line,description:"
+msgid "Description"
+msgstr "Descrição"
+
+msgctxt "field:sale.line,from_location:"
+msgid "From Location"
+msgstr "Origem"
+
+msgctxt "field:sale.line,invoice_lines:"
+msgid "Invoice Lines"
+msgstr "Linhas da fatura"
+
+msgctxt "field:sale.line,move_done:"
+msgid "Moves Done"
+msgstr "Movimentações feitas"
+
+msgctxt "field:sale.line,move_exception:"
+msgid "Moves Exception"
+msgstr "Exceção nas movimentações"
+
+msgctxt "field:sale.line,moves:"
+msgid "Moves"
+msgstr "Movimentações"
+
+msgctxt "field:sale.line,moves_ignored:"
+msgid "Ignored Moves"
+msgstr "Movimentações ignoradas"
+
+msgctxt "field:sale.line,moves_recreated:"
+msgid "Recreated Moves"
+msgstr "Recriar movimentações"
+
+msgctxt "field:sale.line,note:"
+msgid "Note"
+msgstr "Observação"
+
+msgctxt "field:sale.line,product:"
+msgid "Product"
+msgstr "Produto"
+
+msgctxt "field:sale.line,product_uom_category:"
+msgid "Product Uom Category"
+msgstr "Categoria da UDM do Produto"
+
+msgctxt "field:sale.line,quantity:"
+msgid "Quantity"
+msgstr "Quantidade"
+
+msgctxt "field:sale.line,sale:"
+msgid "Sale"
+msgstr "Venda"
+
+msgctxt "field:sale.line,sale_state:"
+msgid "Sale State"
+msgstr "Estado da Venda"
+
+msgctxt "field:sale.line,shipping_date:"
+msgid "Shipping Date"
+msgstr "Data da Remessa"
+
+msgctxt "field:sale.line,summary:"
+msgid "Summary"
+msgstr ""
+
+msgctxt "field:sale.line,taxes:"
+msgid "Taxes"
+msgstr "Impostos"
+
+msgctxt "field:sale.line,to_location:"
+msgid "To Location"
+msgstr "Destino"
+
+msgctxt "field:sale.line,type:"
+msgid "Type"
+msgstr "Tipo"
+
+msgctxt "field:sale.line,unit:"
+msgid "Unit"
+msgstr "Unidade"
+
+msgctxt "field:sale.line,unit_digits:"
+msgid "Unit Digits"
+msgstr "Dígitos da unidade"
+
+msgctxt "field:sale.line,unit_price:"
+msgid "Unit Price"
+msgstr "Preço unitário"
+
+msgctxt "field:sale.line,warehouse:"
+msgid "Warehouse"
+msgstr "Almoxarifado"
+
+msgctxt "field:sale.line-account.tax,line:"
+msgid "Sale Line"
+msgstr "Linha da fatura"
+
+msgctxt "field:sale.line-account.tax,tax:"
+msgid "Tax"
+msgstr "Impostos"
+
+msgctxt "field:sale.line-ignored-stock.move,move:"
+msgid "Move"
+msgstr "Movimentação"
+
+msgctxt "field:sale.line-ignored-stock.move,sale_line:"
+msgid "Sale Line"
+msgstr "Linha da fatura"
+
+msgctxt "field:sale.line-recreated-stock.move,move:"
+msgid "Move"
+msgstr "Movimentação"
+
+msgctxt "field:sale.line-recreated-stock.move,sale_line:"
+msgid "Sale Line"
+msgstr "Linha da fatura"
+
+msgctxt "field:sale.reporting.category,category:"
+msgid "Category"
+msgstr ""
+
+msgctxt "field:sale.reporting.category,time_series:"
+msgid "Time Series"
+msgstr ""
+
+msgctxt "field:sale.reporting.category.time_series,category:"
+msgid "Category"
+msgstr ""
+
+#, fuzzy
+msgctxt "field:sale.reporting.category.time_series,date:"
+msgid "Date"
+msgstr "Data:"
+
+msgctxt "field:sale.reporting.category.tree,children:"
+msgid "Children"
+msgstr ""
+
+#, fuzzy
+msgctxt "field:sale.reporting.category.tree,currency_digits:"
+msgid "Currency Digits"
+msgstr "Dígitos da moeda"
+
+#, fuzzy
+msgctxt "field:sale.reporting.category.tree,name:"
+msgid "Name"
+msgstr "Nome"
+
+msgctxt "field:sale.reporting.category.tree,parent:"
+msgid "Parent"
+msgstr ""
+
+msgctxt "field:sale.reporting.category.tree,revenue:"
+msgid "Revenue"
+msgstr ""
+
+#, fuzzy
+msgctxt "field:sale.reporting.context,company:"
+msgid "Company"
+msgstr "Empresa"
+
+msgctxt "field:sale.reporting.context,from_date:"
+msgid "From Date"
+msgstr ""
+
+msgctxt "field:sale.reporting.context,period:"
+msgid "Period"
+msgstr ""
+
+msgctxt "field:sale.reporting.context,to_date:"
+msgid "To Date"
+msgstr ""
+
+#, fuzzy
+msgctxt "field:sale.reporting.context,warehouse:"
+msgid "Warehouse"
+msgstr "Almoxarifado"
+
+msgctxt "field:sale.reporting.country,country:"
+msgid "Country"
+msgstr ""
+
+msgctxt "field:sale.reporting.country,time_series:"
+msgid "Time Series"
+msgstr ""
+
+msgctxt "field:sale.reporting.country.subdivision,country:"
+msgid "Country"
+msgstr ""
+
+msgctxt "field:sale.reporting.country.subdivision,subdivision:"
+msgid "Subdivision"
+msgstr ""
+
+msgctxt "field:sale.reporting.country.subdivision,time_series:"
+msgid "Time Series"
+msgstr ""
+
+msgctxt "field:sale.reporting.country.subdivision.time_series,country:"
+msgid "Country"
+msgstr ""
+
+#, fuzzy
+msgctxt "field:sale.reporting.country.subdivision.time_series,date:"
+msgid "Date"
+msgstr "Data:"
+
+msgctxt "field:sale.reporting.country.subdivision.time_series,subdivision:"
+msgid "Subdivision"
+msgstr ""
+
+msgctxt "field:sale.reporting.country.time_series,country:"
+msgid "Country"
+msgstr ""
+
+#, fuzzy
+msgctxt "field:sale.reporting.country.time_series,date:"
+msgid "Date"
+msgstr "Data:"
+
+#, fuzzy
+msgctxt "field:sale.reporting.customer,customer:"
+msgid "Customer"
+msgstr "Clientes"
+
+msgctxt "field:sale.reporting.customer,time_series:"
+msgid "Time Series"
+msgstr ""
+
+#, fuzzy
+msgctxt "field:sale.reporting.customer.time_series,customer:"
+msgid "Customer"
+msgstr "Clientes"
+
+#, fuzzy
+msgctxt "field:sale.reporting.customer.time_series,date:"
+msgid "Date"
+msgstr "Data:"
+
+#, fuzzy
+msgctxt "field:sale.reporting.product,product:"
+msgid "Product"
+msgstr "Produto"
+
+msgctxt "field:sale.reporting.product,time_series:"
+msgid "Time Series"
+msgstr ""
+
+#, fuzzy
+msgctxt "field:sale.reporting.product.time_series,date:"
+msgid "Date"
+msgstr "Data:"
+
+#, fuzzy
+msgctxt "field:sale.reporting.product.time_series,product:"
+msgid "Product"
+msgstr "Produto"
+
+msgctxt "field:sale.reporting.region,children:"
+msgid "Children"
+msgstr ""
+
+msgctxt "field:sale.reporting.region,parent:"
+msgid "Parent"
+msgstr ""
+
+msgctxt "field:sale.reporting.region,region:"
+msgid "Region"
+msgstr ""
+
+msgctxt "field:sale.sale,comment:"
+msgid "Comment"
+msgstr "Comentário"
+
+msgctxt "field:sale.sale,company:"
+msgid "Company"
+msgstr "Empresa"
+
+#, fuzzy
+msgctxt "field:sale.sale,confirmed_by:"
+msgid "Confirmed By"
+msgstr "Confirmed"
+
+msgctxt "field:sale.sale,contact:"
+msgid "Contact"
+msgstr ""
+
+msgctxt "field:sale.sale,currency:"
+msgid "Currency"
+msgstr "Moeda"
+
+msgctxt "field:sale.sale,currency_digits:"
+msgid "Currency Digits"
+msgstr "Dígitos da moeda"
+
+msgctxt "field:sale.sale,description:"
+msgid "Description"
+msgstr "Descrição"
+
+msgctxt "field:sale.sale,invoice_address:"
+msgid "Invoice Address"
+msgstr "Endereço para faturamento"
+
+msgctxt "field:sale.sale,invoice_method:"
+msgid "Invoice Method"
+msgstr "Método da fatura"
+
+#, fuzzy
+msgctxt "field:sale.sale,invoice_party:"
+msgid "Invoice Party"
+msgstr "Estado da fatura"
+
+msgctxt "field:sale.sale,invoice_state:"
+msgid "Invoice State"
+msgstr "Estado da fatura"
+
+msgctxt "field:sale.sale,invoices:"
+msgid "Invoices"
+msgstr "Faturas"
+
+msgctxt "field:sale.sale,invoices_ignored:"
+msgid "Ignored Invoices"
+msgstr "Faturas ignoradas"
+
+msgctxt "field:sale.sale,invoices_recreated:"
+msgid "Recreated Invoices"
+msgstr "Faturas Recriadas"
+
+msgctxt "field:sale.sale,lines:"
+msgid "Lines"
+msgstr "Linhas"
+
+msgctxt "field:sale.sale,moves:"
+msgid "Moves"
+msgstr "Movimentações"
+
+msgctxt "field:sale.sale,number:"
+msgid "Number"
+msgstr "Número"
+
+msgctxt "field:sale.sale,origin:"
+msgid "Origin"
+msgstr "Origem"
+
+msgctxt "field:sale.sale,party:"
+msgid "Party"
+msgstr "Parceiro"
+
+msgctxt "field:sale.sale,party_lang:"
+msgid "Party Language"
+msgstr "Língua do parceiro"
+
+msgctxt "field:sale.sale,payment_term:"
+msgid "Payment Term"
+msgstr "Prazo de Pagamento"
+
+#, fuzzy
+msgctxt "field:sale.sale,quoted_by:"
+msgid "Quoted By"
+msgstr "Quote"
+
+msgctxt "field:sale.sale,reference:"
+msgid "Reference"
+msgstr "Referência"
+
+msgctxt "field:sale.sale,sale_date:"
+msgid "Sale Date"
+msgstr "Data da venda"
+
+msgctxt "field:sale.sale,shipment_address:"
+msgid "Shipment Address"
+msgstr "Endereço de entrega"
+
+msgctxt "field:sale.sale,shipment_method:"
+msgid "Shipment Method"
+msgstr "Método da Remessa"
+
+msgctxt "field:sale.sale,shipment_party:"
+msgid "Shipment Party"
+msgstr "Destinatário da Remessa"
+
+msgctxt "field:sale.sale,shipment_returns:"
+msgid "Shipment Returns"
+msgstr "Retornos de Remessas"
+
+msgctxt "field:sale.sale,shipment_state:"
+msgid "Shipment State"
+msgstr "Estado da expedição"
+
+msgctxt "field:sale.sale,shipments:"
+msgid "Shipments"
+msgstr "Remessas"
+
+#, fuzzy
+msgctxt "field:sale.sale,shipping_date:"
+msgid "Shipping Date"
+msgstr "Data da Remessa"
+
+msgctxt "field:sale.sale,state:"
+msgid "State"
+msgstr "Estado"
+
+msgctxt "field:sale.sale,tax_amount:"
+msgid "Tax"
+msgstr "Impostos"
+
+msgctxt "field:sale.sale,tax_amount_cache:"
+msgid "Tax Cache"
+msgstr "Tributos Pré-calculados"
+
+msgctxt "field:sale.sale,total_amount:"
+msgid "Total"
+msgstr "Total"
+
+#, fuzzy
+msgctxt "field:sale.sale,total_amount_cache:"
+msgid "Total Cache"
+msgstr "Tributos Pré-calculados"
+
+msgctxt "field:sale.sale,untaxed_amount:"
+msgid "Untaxed"
+msgstr "Não tributado"
+
+msgctxt "field:sale.sale,untaxed_amount_cache:"
+msgid "Untaxed Cache"
+msgstr "Isenção Pré-Calculada"
+
+msgctxt "field:sale.sale,warehouse:"
+msgid "Warehouse"
+msgstr "Almoxarifado"
+
+msgctxt "field:sale.sale-ignored-account.invoice,invoice:"
+msgid "Invoice"
+msgstr "Fatura"
+
+msgctxt "field:sale.sale-ignored-account.invoice,sale:"
+msgid "Sale"
+msgstr "Venda"
+
+msgctxt "field:sale.sale-recreated-account.invoice,invoice:"
+msgid "Invoice"
+msgstr "Fatura"
+
+msgctxt "field:sale.sale-recreated-account.invoice,sale:"
+msgid "Sale"
+msgstr "Venda"
+
+msgctxt "field:stock.move,sale:"
+msgid "Sale"
+msgstr "Venda"
+
+msgctxt "field:stock.move,sale_exception_state:"
+msgid "Exception State"
+msgstr "Estado da exceção"
+
+msgctxt "help:product.configuration,default_lead_time:"
+msgid ""
+"The time from confirming the sales order to sending the products.\n"
+"Used for products without a lead time."
+msgstr ""
+
+msgctxt "help:product.product,lead_time:"
+msgid ""
+"The time from confirming the sales order to sending the products.\n"
+"If empty the default lead time from the configuration is used."
+msgstr ""
+
+msgctxt "help:product.template,lead_time:"
+msgid ""
+"The time from confirming the sales order to sending the products.\n"
+"If empty the default lead time from the configuration is used."
+msgstr ""
+
+msgctxt "help:sale.configuration,sale_process_after:"
+msgid ""
+"The grace period during which confirmed sale can still be reset to draft.\n"
+"Applied if a worker queue is activated."
+msgstr ""
+
+msgctxt "help:sale.handle.invoice.exception.ask,recreate_invoices:"
+msgid ""
+"The selected invoices will be recreated. The other ones will be ignored."
+msgstr ""
+"As faturas escolhidas serão recriadas. As demais faturas serão ignoradas"
+
+msgctxt "help:sale.sale,shipping_date:"
+msgid "When the shipping of goods should start."
+msgstr ""
+
+#, fuzzy
+msgctxt "model:ir.action,name:act_invoice_form"
+msgid "Invoices"
+msgstr "Invoices"
+
+#, fuzzy
+msgctxt "model:ir.action,name:act_open_customer"
+msgid "Parties associated to Sales"
+msgstr "Parties associated to Sales"
+
+#, fuzzy
+msgctxt "model:ir.action,name:act_product"
+msgid "Products"
+msgstr "Produto"
+
+msgctxt "model:ir.action,name:act_reporting_category"
+msgid "Sales per Category"
+msgstr "Sales per Category"
+
+msgctxt "model:ir.action,name:act_reporting_category_time_series"
+msgid "Sales per Category"
+msgstr "Sales per Category"
+
+msgctxt "model:ir.action,name:act_reporting_category_tree"
+msgid "Sales per Category"
+msgstr "Sales per Category"
+
+msgctxt "model:ir.action,name:act_reporting_country_subdivision_time_series"
+msgid "Sales per Subdivision"
+msgstr "Sales per Subdivision"
+
+msgctxt "model:ir.action,name:act_reporting_country_time_series"
+msgid "Sales per Country"
+msgstr "Sales per Country"
+
+msgctxt "model:ir.action,name:act_reporting_customer"
+msgid "Sales per Customer"
+msgstr "Sales per Customer"
+
+msgctxt "model:ir.action,name:act_reporting_customer_time_series"
+msgid "Sales per Customer"
+msgstr "Sales per Customer"
+
+msgctxt "model:ir.action,name:act_reporting_product"
+msgid "Sales per Product"
+msgstr "Sales per Product"
+
+msgctxt "model:ir.action,name:act_reporting_product_time_series"
+msgid "Sales per Product"
+msgstr "Sales per Product"
+
+msgctxt "model:ir.action,name:act_reporting_region"
+msgid "Sales per Region"
+msgstr "Sales per Region"
+
+#, fuzzy
+msgctxt "model:ir.action,name:act_return_form"
+msgid "Returns"
+msgstr "Returns"
+
+#, fuzzy
+msgctxt "model:ir.action,name:act_sale_configuration_form"
+msgid "Configuration"
+msgstr "Configuration"
+
+#, fuzzy
+msgctxt "model:ir.action,name:act_sale_form"
+msgid "Sales"
+msgstr "Sales"
+
+#, fuzzy
+msgctxt "model:ir.action,name:act_sale_form2"
+msgid "Sales"
+msgstr "Sales"
+
+#, fuzzy
+msgctxt "model:ir.action,name:act_sale_invoice_relate"
+msgid "Sales"
+msgstr "Sales"
+
+#, fuzzy
+msgctxt "model:ir.action,name:act_sale_move_relate"
+msgid "Moves"
+msgstr "Movimentações"
+
+msgctxt "model:ir.action,name:act_sale_shipment_returns_relate"
+msgid "Sales"
+msgstr "Sales"
+
+#, fuzzy
+msgctxt "model:ir.action,name:act_sale_shipments_relate"
+msgid "Sales"
+msgstr "Sales"
+
+#, fuzzy
+msgctxt "model:ir.action,name:act_shipment_form"
+msgid "Shipments"
+msgstr "Shipments"
+
+#, fuzzy
+msgctxt "model:ir.action,name:report_sale"
+msgid "Sale"
+msgstr "Sale"
+
+#, fuzzy
+msgctxt "model:ir.action,name:wizard_invoice_handle_exception"
+msgid "Handle Invoice Exception"
+msgstr "Handle Invoice Exception"
+
+msgctxt "model:ir.action,name:wizard_modify_header"
+msgid "Modify Header"
+msgstr "Modify Header"
+
+msgctxt "model:ir.action,name:wizard_reporting_region_open"
+msgid "Open Region"
+msgstr "Open Region"
+
+#, fuzzy
+msgctxt "model:ir.action,name:wizard_return_sale"
+msgid "Return Sale"
+msgstr "Return Sale"
+
+#, fuzzy
+msgctxt "model:ir.action,name:wizard_shipment_handle_exception"
+msgid "Handle Shipment Exception"
+msgstr "Handle Shipment Exception"
+
+#, fuzzy
+msgctxt "model:ir.action.act_window.domain,name:act_sale_form_domain_all"
+msgid "All"
+msgstr "All"
+
+#, fuzzy
+msgctxt ""
+"model:ir.action.act_window.domain,name:act_sale_form_domain_confirmed"
+msgid "Confirmed"
+msgstr "Confirmed"
+
+#, fuzzy
+msgctxt "model:ir.action.act_window.domain,name:act_sale_form_domain_draft"
+msgid "Draft"
+msgstr "Draft"
+
+#, fuzzy
+msgctxt ""
+"model:ir.action.act_window.domain,name:act_sale_form_domain_exception"
+msgid "Exception"
+msgstr "Exceção"
+
+#, fuzzy
+msgctxt ""
+"model:ir.action.act_window.domain,name:act_sale_form_domain_processing"
+msgid "Processing"
+msgstr "Processing"
+
+#, fuzzy
+msgctxt ""
+"model:ir.action.act_window.domain,name:act_sale_form_domain_quotation"
+msgid "Quotation"
+msgstr "Quotation"
+
+msgctxt "model:ir.message,text:msg_erase_party_pending_sale"
+msgid ""
+"You cannot erase party \"%(party)s\" while they have pending sales with "
+"company \"%(company)s\"."
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_sale_customer_location_required"
+msgid ""
+"To process sale \"%(sale)s\" you must set a customer location on party "
+"\"%(party)s\"."
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_sale_delete_cancel"
+msgid "To delete sale \"%(sale)s\" you must cancel it."
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_sale_invalid_method"
+msgid ""
+"You cannot use together invoice \"%(invoice_method)s\" and shipment "
+"\"%(shipment_method)s\" on sale \"%(sale)s\"."
+msgstr ""
+
+msgctxt ""
+"model:ir.message,text:msg_sale_invoice_address_required_for_quotation"
+msgid "To get a quote for sale \"%(sale)s\" you must enter an invoice address."
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_sale_invoice_reset_draft"
+msgid ""
+"You cannot reset invoice \"%(invoice)s\" to draft because it was generated "
+"by a sale."
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_sale_line_delete_cancel_draft"
+msgid ""
+"To delete line \"%(line)s\" you must cancel or reset to draft sale "
+"\"%(sale)s\"."
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_sale_missing_account_revenue"
+msgid "To invoice sale \"%(sale)s\" you must configure a default account revenue."
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_sale_modify_header_draft"
+msgid "To modify the header of sale \"%(sale)s\", it must be in \"draft\" state."
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_sale_move_reset_draft"
+msgid ""
+"You cannot reset move \"%(move)s\" to draft because it was generated by a "
+"sale."
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_sale_product_missing_account_revenue"
+msgid ""
+"To invoice sale \"%(sale)s\" you must define an account revenue for product "
+"\"%(product)s\"."
+msgstr ""
+
+#, fuzzy
+msgctxt "model:ir.message,text:msg_sale_reporting_company"
+msgid "Company"
+msgstr "Empresa"
+
+#, fuzzy
+msgctxt "model:ir.message,text:msg_sale_reporting_currency"
+msgid "Currency"
+msgstr "Moeda"
+
+#, fuzzy
+msgctxt "model:ir.message,text:msg_sale_reporting_currency_digits"
+msgid "Currency Digits"
+msgstr "Dígitos da moeda"
+
+#, fuzzy
+msgctxt "model:ir.message,text:msg_sale_reporting_number"
+msgid "#"
+msgstr "#"
+
+msgctxt "model:ir.message,text:msg_sale_reporting_number_help"
+msgid "Number of sales"
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_sale_reporting_revenue"
+msgid "Revenue"
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_sale_reporting_revenue_trend"
+msgid "Revenue Trend"
+msgstr ""
+
+msgctxt ""
+"model:ir.message,text:msg_sale_shipment_address_required_for_quotation"
+msgid "To get a quote for sale \"%(sale)s\" you must enter a shipment address."
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_sale_warehouse_required_for_quotation"
+msgid "To get a quote for sale \"%(sale)s\" you must enter a warehouse."
+msgstr ""
+
+msgctxt "model:ir.model.button,string:sale_cancel_button"
+msgid "Cancel"
+msgstr "Cancel"
+
+msgctxt "model:ir.model.button,string:sale_confirm_button"
+msgid "Confirm"
+msgstr "Confirm"
+
+msgctxt "model:ir.model.button,string:sale_draft_button"
+msgid "Draft"
+msgstr "Draft"
+
+msgctxt "model:ir.model.button,string:sale_handle_invoice_exception_button"
+msgid "Handle Invoice Exception"
+msgstr "Handle Invoice Exception"
+
+msgctxt "model:ir.model.button,string:sale_handle_shipment_exception_button"
+msgid "Handle Shipment Exception"
+msgstr "Handle Shipment Exception"
+
+msgctxt "model:ir.model.button,string:sale_modify_header_button"
+msgid "Modify Header"
+msgstr "Modify Header"
+
+msgctxt "model:ir.model.button,string:sale_process_button"
+msgid "Process"
+msgstr "Process"
+
+msgctxt "model:ir.model.button,string:sale_quote_button"
+msgid "Quote"
+msgstr "Quote"
+
+msgctxt "model:ir.rule.group,name:rule_group_reporting_category_companies"
+msgid "User in companies"
+msgstr ""
+
+msgctxt ""
+"model:ir.rule.group,name:rule_group_reporting_category_time_series_companies"
+msgid "User in companies"
+msgstr ""
+
+msgctxt ""
+"model:ir.rule.group,name:rule_group_reporting_country_subdivision_time_series_companies"
+msgid "User in companies"
+msgstr ""
+
+msgctxt ""
+"model:ir.rule.group,name:rule_group_reporting_country_time_series_companies"
+msgid "User in companies"
+msgstr ""
+
+msgctxt "model:ir.rule.group,name:rule_group_reporting_customer_companies"
+msgid "User in companies"
+msgstr ""
+
+msgctxt ""
+"model:ir.rule.group,name:rule_group_reporting_customer_time_series_companies"
+msgid "User in companies"
+msgstr ""
+
+msgctxt "model:ir.rule.group,name:rule_group_reporting_product_companies"
+msgid "User in companies"
+msgstr ""
+
+msgctxt ""
+"model:ir.rule.group,name:rule_group_reporting_product_time_series_companies"
+msgid "User in companies"
+msgstr ""
+
+msgctxt "model:ir.rule.group,name:rule_group_reporting_region_companies"
+msgid "User in companies"
+msgstr ""
+
+msgctxt "model:ir.rule.group,name:rule_group_sale_companies"
+msgid "User in companies"
+msgstr ""
+
+#, fuzzy
+msgctxt "model:ir.sequence,name:sequence_sale"
+msgid "Sale"
+msgstr "Sale"
+
+#, fuzzy
+msgctxt "model:ir.sequence.type,name:sequence_type_sale"
+msgid "Sale"
+msgstr "Sale"
+
+#, fuzzy
+msgctxt "model:ir.ui.menu,name:menu_configuration"
+msgid "Configuration"
+msgstr "Configuration"
+
+#, fuzzy
+msgctxt "model:ir.ui.menu,name:menu_customer"
+msgid "Associated to Sales"
+msgstr "Parties associated to Sales"
+
+#, fuzzy
+msgctxt "model:ir.ui.menu,name:menu_product"
+msgid "Products"
+msgstr "Produto"
+
+msgctxt "model:ir.ui.menu,name:menu_reporting"
+msgid "Reporting"
+msgstr "Reporting"
+
+msgctxt "model:ir.ui.menu,name:menu_reporting_sale"
+msgid "Sales"
+msgstr "Sales"
+
+#, fuzzy
+msgctxt "model:ir.ui.menu,name:menu_sale"
+msgid "Sales"
+msgstr "Sales"
+
+#, fuzzy
+msgctxt "model:ir.ui.menu,name:menu_sale_configuration"
+msgid "Configuration"
+msgstr "Configuration"
+
+#, fuzzy
+msgctxt "model:ir.ui.menu,name:menu_sale_form"
+msgid "Sales"
+msgstr "Sales"
+
+msgctxt "model:product.configuration.default_lead_time,name:"
+msgid "Product Default Lead Time"
+msgstr ""
+
+msgctxt "model:product.sale.context,name:"
+msgid "Product Sale Context"
+msgstr ""
+
+#, fuzzy
+msgctxt "model:res.group,name:group_sale"
+msgid "Sales"
+msgstr "Sales"
+
+#, fuzzy
+msgctxt "model:res.group,name:group_sale_admin"
+msgid "Sales Administrator"
+msgstr "Sales Administrator"
+
+msgctxt "model:sale.configuration,name:"
+msgid "Sale Configuration"
+msgstr "Configuração de vendas"
+
+msgctxt "model:sale.configuration.sale_method,name:"
+msgid "Sale Configuration Sale Method"
+msgstr "Configuração de Venda Método de Venda"
+
+msgctxt "model:sale.configuration.sequence,name:"
+msgid "Sale Configuration Sequence"
+msgstr "Configuração de Venda Sequência"
+
+msgctxt "model:sale.handle.invoice.exception.ask,name:"
+msgid "Handle Invoice Exception"
+msgstr "Exceção da fatura do punho"
+
+msgctxt "model:sale.handle.shipment.exception.ask,name:"
+msgid "Handle Shipment Exception"
+msgstr "Manejar Exceção da Remessa"
+
+msgctxt "model:sale.line,name:"
+msgid "Sale Line"
+msgstr "Linha da fatura"
+
+msgctxt "model:sale.line-account.tax,name:"
+msgid "Sale Line - Tax"
+msgstr "Linha da venda - Imposto"
+
+msgctxt "model:sale.line-ignored-stock.move,name:"
+msgid "Sale Line - Ignored Move"
+msgstr "Linha da venda - Movimentação ignorado"
+
+msgctxt "model:sale.line-recreated-stock.move,name:"
+msgid "Sale Line - Recreated Move"
+msgstr "Linha da Fatura - Recriar movimentação"
+
+msgctxt "model:sale.reporting.category,name:"
+msgid "Sale Reporting per Category"
+msgstr ""
+
+msgctxt "model:sale.reporting.category.time_series,name:"
+msgid "Sale Reporting per Category"
+msgstr ""
+
+msgctxt "model:sale.reporting.category.tree,name:"
+msgid "Sale Reporting per Category"
+msgstr ""
+
+msgctxt "model:sale.reporting.context,name:"
+msgid "Sale Reporting Context"
+msgstr ""
+
+msgctxt "model:sale.reporting.country,name:"
+msgid "Sale Reporting per Country"
+msgstr ""
+
+msgctxt "model:sale.reporting.country.subdivision,name:"
+msgid "Sale Reporting per Subdivision"
+msgstr ""
+
+msgctxt "model:sale.reporting.country.subdivision.time_series,name:"
+msgid "Sale Reporting per Subdivision"
+msgstr ""
+
+msgctxt "model:sale.reporting.country.time_series,name:"
+msgid "Sale Reporting per Country"
+msgstr ""
+
+msgctxt "model:sale.reporting.customer,name:"
+msgid "Sale Reporting per Customer"
+msgstr ""
+
+msgctxt "model:sale.reporting.customer.time_series,name:"
+msgid "Sale Reporting per Customer"
+msgstr ""
+
+msgctxt "model:sale.reporting.product,name:"
+msgid "Sale Reporting per Product"
+msgstr ""
+
+msgctxt "model:sale.reporting.product.time_series,name:"
+msgid "Sale Reporting per Product"
+msgstr ""
+
+msgctxt "model:sale.reporting.region,name:"
+msgid "Sale Reporting per Region"
+msgstr ""
+
+msgctxt "model:sale.return_sale.start,name:"
+msgid "Return Sale"
+msgstr "Criar Devolução de Venda"
+
+msgctxt "model:sale.sale,name:"
+msgid "Sale"
+msgstr "Venda"
+
+msgctxt "model:sale.sale-ignored-account.invoice,name:"
+msgid "Sale - Ignored Invoice"
+msgstr "Venda - Fatura ignorada"
+
+msgctxt "model:sale.sale-recreated-account.invoice,name:"
+msgid "Sale - Recreated Invoice"
+msgstr "Venda - Recriar fatura"
+
+msgctxt "report:sale.sale:"
+msgid ":"
+msgstr ":"
+
+msgctxt "report:sale.sale:"
+msgid "Amount"
+msgstr "Quantidade"
+
+msgctxt "report:sale.sale:"
+msgid "Date:"
+msgstr "Data:"
+
+msgctxt "report:sale.sale:"
+msgid "Description"
+msgstr "Descrição"
+
+msgctxt "report:sale.sale:"
+msgid "Description:"
+msgstr "Descrição:"
+
+msgctxt "report:sale.sale:"
+msgid "Draft Sale Order"
+msgstr "Rascunho de Ordem de Venda"
+
+msgctxt "report:sale.sale:"
+msgid "Quantity"
+msgstr "Quantidade"
+
+msgctxt "report:sale.sale:"
+msgid "Quotation N°:"
+msgstr "Cotação n°:"
+
+msgctxt "report:sale.sale:"
+msgid "Reference:"
+msgstr "Referência:"
+
+msgctxt "report:sale.sale:"
+msgid "Sale Order N°:"
+msgstr "Ordem de Venda n°:"
+
+msgctxt "report:sale.sale:"
+msgid "Taxes"
+msgstr "Impostos"
+
+msgctxt "report:sale.sale:"
+msgid "Taxes:"
+msgstr "Tributos"
+
+msgctxt "report:sale.sale:"
+msgid "Total (excl. taxes):"
+msgstr "Total (sem tributos):"
+
+msgctxt "report:sale.sale:"
+msgid "Total:"
+msgstr "Total:"
+
+msgctxt "report:sale.sale:"
+msgid "Unit Price"
+msgstr "Preço unitário"
+
+msgctxt "selection:account.invoice,sale_exception_state:"
+msgid "Ignored"
+msgstr "Ignorado"
+
+msgctxt "selection:account.invoice,sale_exception_state:"
+msgid "Recreated"
+msgstr "Recriado"
+
+msgctxt "selection:sale.line,type:"
+msgid "Comment"
+msgstr "Comentário"
+
+msgctxt "selection:sale.line,type:"
+msgid "Line"
+msgstr "Linha"
+
+msgctxt "selection:sale.line,type:"
+msgid "Subtotal"
+msgstr "Subtotal"
+
+msgctxt "selection:sale.line,type:"
+msgid "Title"
+msgstr "Título"
+
+msgctxt "selection:sale.reporting.context,period:"
+msgid "Day"
+msgstr ""
+
+msgctxt "selection:sale.reporting.context,period:"
+msgid "Month"
+msgstr ""
+
+msgctxt "selection:sale.reporting.context,period:"
+msgid "Year"
+msgstr ""
+
+msgctxt "selection:sale.sale,invoice_method:"
+msgid "Manual"
+msgstr "Manual"
+
+msgctxt "selection:sale.sale,invoice_method:"
+msgid "On Order Processed"
+msgstr "Ao Processar a Ordem"
+
+msgctxt "selection:sale.sale,invoice_method:"
+msgid "On Shipment Sent"
+msgstr "No Envio da Remessa"
+
+msgctxt "selection:sale.sale,invoice_state:"
+msgid "Exception"
+msgstr "Exceção"
+
+msgctxt "selection:sale.sale,invoice_state:"
+msgid "None"
+msgstr "Nenhum"
+
+msgctxt "selection:sale.sale,invoice_state:"
+msgid "Paid"
+msgstr "Pago"
+
+msgctxt "selection:sale.sale,invoice_state:"
+msgid "Waiting"
+msgstr "Espera"
+
+msgctxt "selection:sale.sale,shipment_method:"
+msgid "Manual"
+msgstr "Manual"
+
+msgctxt "selection:sale.sale,shipment_method:"
+msgid "On Invoice Paid"
+msgstr "No pagamento da fatura"
+
+msgctxt "selection:sale.sale,shipment_method:"
+msgid "On Order Processed"
+msgstr "Ao Processar a Ordem"
+
+msgctxt "selection:sale.sale,shipment_state:"
+msgid "Exception"
+msgstr "Exceção"
+
+msgctxt "selection:sale.sale,shipment_state:"
+msgid "None"
+msgstr "Nenhum"
+
+msgctxt "selection:sale.sale,shipment_state:"
+msgid "Sent"
+msgstr "Emitido"
+
+msgctxt "selection:sale.sale,shipment_state:"
+msgid "Waiting"
+msgstr "Espera"
+
+#, fuzzy
+msgctxt "selection:sale.sale,state:"
+msgid "Cancelled"
+msgstr "Cancelado"
+
+msgctxt "selection:sale.sale,state:"
+msgid "Confirmed"
+msgstr "Confirmado"
+
+msgctxt "selection:sale.sale,state:"
+msgid "Done"
+msgstr "Feito"
+
+msgctxt "selection:sale.sale,state:"
+msgid "Draft"
+msgstr "Rascunho"
+
+msgctxt "selection:sale.sale,state:"
+msgid "Processing"
+msgstr "Processamento"
+
+msgctxt "selection:sale.sale,state:"
+msgid "Quotation"
+msgstr "Cotação"
+
+msgctxt "selection:stock.move,sale_exception_state:"
+msgid "Ignored"
+msgstr "Ignorado"
+
+msgctxt "selection:stock.move,sale_exception_state:"
+msgid "Recreated"
+msgstr "Recriado"
+
+msgctxt "view:party.party:"
+msgid "Sale"
+msgstr "Venda"
+
+msgctxt "view:product.template:"
+msgid "Customers"
+msgstr "Clientes"
+
+#, fuzzy
+msgctxt "view:sale.handle.invoice.exception.ask:"
+msgid "Choose invoices to recreate:"
+msgstr "Escolhe as Faturas para recriar"
+
+#, fuzzy
+msgctxt "view:sale.handle.shipment.exception.ask:"
+msgid "Choose move to recreate:"
+msgstr "Escolha as movimentações a recriar"
+
+msgctxt "view:sale.line:"
+msgid "General"
+msgstr "Geral"
+
+msgctxt "view:sale.line:"
+msgid "Notes"
+msgstr "Observação"
+
+msgctxt "view:sale.line:"
+msgid "Taxes"
+msgstr "Impostos"
+
+#, fuzzy
+msgctxt "view:sale.return_sale.start:"
+msgid "Are you sure to return these/this sale(s)?"
+msgstr "Tem certeza que deseja devolver estes pedidos de venda?"
+
+msgctxt "view:sale.sale:"
+msgid "Other Info"
+msgstr "Outras informações"
+
+msgctxt "view:sale.sale:"
+msgid "Sale"
+msgstr "Venda"
+
+msgctxt "wizard_button:sale.handle.invoice.exception,ask,end:"
+msgid "Cancel"
+msgstr "Cancelar"
+
+msgctxt "wizard_button:sale.handle.invoice.exception,ask,handle:"
+msgid "OK"
+msgstr "OK"
+
+msgctxt "wizard_button:sale.handle.shipment.exception,ask,end:"
+msgid "Cancel"
+msgstr "Cancelar"
+
+msgctxt "wizard_button:sale.handle.shipment.exception,ask,handle:"
+msgid "OK"
+msgstr "OK"
+
+#, fuzzy
+msgctxt "wizard_button:sale.modify_header,start,end:"
+msgid "Cancel"
+msgstr "Cancelar"
+
+msgctxt "wizard_button:sale.modify_header,start,modify:"
+msgid "Modify"
+msgstr ""
+
+msgctxt "wizard_button:sale.return_sale,start,end:"
+msgid "Cancel"
+msgstr "Cancelar"
+
+msgctxt "wizard_button:sale.return_sale,start,return_:"
+msgid "Return"
+msgstr "Devolver"
diff --git a/modules/sale/locale/ro.po b/modules/sale/locale/ro.po
new file mode 100644
index 0000000000..b4b809a088
--- /dev/null
+++ b/modules/sale/locale/ro.po
@@ -0,0 +1,1376 @@
+#
+msgid ""
+msgstr "Content-Type: text/plain; charset=utf-8\n"
+
+msgctxt "field:account.invoice,sale_exception_state:"
+msgid "Exception State"
+msgstr "Stare de excepție"
+
+msgctxt "field:account.invoice,sales:"
+msgid "Sales"
+msgstr "Vânzări"
+
+msgctxt "field:product.configuration,default_lead_time:"
+msgid "Default Lead Time"
+msgstr "Timp Implicit de execuţie"
+
+msgctxt "field:product.configuration.default_lead_time,company:"
+msgid "Company"
+msgstr "Companie"
+
+msgctxt "field:product.configuration.default_lead_time,default_lead_time:"
+msgid "Default Lead Time"
+msgstr "Timp Implicit de execuţie"
+
+msgctxt "field:product.product,lead_time:"
+msgid "Lead Time"
+msgstr "Timp de livrare"
+
+msgctxt "field:product.product,salable:"
+msgid "Salable"
+msgstr "Marfă"
+
+msgctxt "field:product.product,sale_price_uom:"
+msgid "Sale Price"
+msgstr "Preț de vânzare"
+
+msgctxt "field:product.product,sale_uom:"
+msgid "Sale UOM"
+msgstr "Vânzare UM"
+
+msgctxt "field:product.sale.context,company:"
+msgid "Company"
+msgstr "Companie"
+
+msgctxt "field:product.sale.context,currency:"
+msgid "Currency"
+msgstr "Moneda"
+
+msgctxt "field:product.sale.context,customer:"
+msgid "Customer"
+msgstr "Client"
+
+msgctxt "field:product.sale.context,locations:"
+msgid "Warehouses"
+msgstr "Depozite"
+
+msgctxt "field:product.sale.context,quantity:"
+msgid "Quantity"
+msgstr "Cantitate"
+
+msgctxt "field:product.sale.context,sale_date:"
+msgid "Sale Date"
+msgstr "Data vânzării"
+
+msgctxt "field:product.sale.context,stock_date_end:"
+msgid "Stock End Date"
+msgstr "Data încheiere Stoc"
+
+msgctxt "field:product.template,lead_time:"
+msgid "Lead Time"
+msgstr "Timp de livrare"
+
+msgctxt "field:product.template,salable:"
+msgid "Salable"
+msgstr "Marfă"
+
+msgctxt "field:product.template,sale_uom:"
+msgid "Sale UOM"
+msgstr "Vânzare UM"
+
+msgctxt "field:sale.configuration,sale_invoice_method:"
+msgid "Sale Invoice Method"
+msgstr "Metoda facturii de vânzare"
+
+msgctxt "field:sale.configuration,sale_process_after:"
+msgid "Process Sale after"
+msgstr "Procesează Vânzare după"
+
+msgctxt "field:sale.configuration,sale_sequence:"
+msgid "Sale Sequence"
+msgstr "Secvență de vânzare"
+
+msgctxt "field:sale.configuration,sale_shipment_method:"
+msgid "Sale Shipment Method"
+msgstr "Metoda de expediere marfă"
+
+msgctxt "field:sale.configuration.sale_method,sale_invoice_method:"
+msgid "Sale Invoice Method"
+msgstr "Metoda de facturare al vânzării"
+
+msgctxt "field:sale.configuration.sale_method,sale_shipment_method:"
+msgid "Sale Shipment Method"
+msgstr "Metoda de expediere a vânzării"
+
+msgctxt "field:sale.configuration.sequence,company:"
+msgid "Company"
+msgstr "Companie"
+
+msgctxt "field:sale.configuration.sequence,sale_sequence:"
+msgid "Sale Sequence"
+msgstr "Secvență de vânzare"
+
+msgctxt "field:sale.handle.invoice.exception.ask,domain_invoices:"
+msgid "Domain Invoices"
+msgstr "Facturi de domeniu"
+
+msgctxt "field:sale.handle.invoice.exception.ask,recreate_invoices:"
+msgid "Recreate Invoices"
+msgstr "Recreați facturi"
+
+msgctxt "field:sale.handle.shipment.exception.ask,domain_moves:"
+msgid "Domain Moves"
+msgstr "Mișcări de domeniu"
+
+msgctxt "field:sale.handle.shipment.exception.ask,recreate_moves:"
+msgid "Recreate Moves"
+msgstr "Recreați mișcări"
+
+msgctxt "field:sale.line,actual_quantity:"
+msgid "Actual Quantity"
+msgstr "Cantitatea actuală"
+
+msgctxt "field:sale.line,amount:"
+msgid "Amount"
+msgstr "Suma"
+
+msgctxt "field:sale.line,company:"
+msgid "Company"
+msgstr "Companie"
+
+msgctxt "field:sale.line,currency:"
+msgid "Currency"
+msgstr "Moneda"
+
+msgctxt "field:sale.line,description:"
+msgid "Description"
+msgstr "Descriere"
+
+msgctxt "field:sale.line,from_location:"
+msgid "From Location"
+msgstr "Din locație"
+
+msgctxt "field:sale.line,invoice_lines:"
+msgid "Invoice Lines"
+msgstr "Rând factură"
+
+msgctxt "field:sale.line,move_done:"
+msgid "Moves Done"
+msgstr "Mișcari Finalizate"
+
+msgctxt "field:sale.line,move_exception:"
+msgid "Moves Exception"
+msgstr "Excepție de Miscare"
+
+msgctxt "field:sale.line,moves:"
+msgid "Moves"
+msgstr "Mișcări"
+
+msgctxt "field:sale.line,moves_ignored:"
+msgid "Ignored Moves"
+msgstr "Mișcări ignorate"
+
+msgctxt "field:sale.line,moves_recreated:"
+msgid "Recreated Moves"
+msgstr "Mișcări recreate"
+
+msgctxt "field:sale.line,note:"
+msgid "Note"
+msgstr "Nota"
+
+msgctxt "field:sale.line,product:"
+msgid "Product"
+msgstr "Produs"
+
+msgctxt "field:sale.line,product_uom_category:"
+msgid "Product Uom Category"
+msgstr "Categorie UM Produs"
+
+msgctxt "field:sale.line,quantity:"
+msgid "Quantity"
+msgstr "Cantitate"
+
+msgctxt "field:sale.line,sale:"
+msgid "Sale"
+msgstr "Vânzare"
+
+msgctxt "field:sale.line,sale_state:"
+msgid "Sale State"
+msgstr "Starea vanzarii"
+
+msgctxt "field:sale.line,shipping_date:"
+msgid "Shipping Date"
+msgstr "Data de expediere"
+
+msgctxt "field:sale.line,summary:"
+msgid "Summary"
+msgstr "Rezumat"
+
+msgctxt "field:sale.line,taxes:"
+msgid "Taxes"
+msgstr "Impozite"
+
+msgctxt "field:sale.line,to_location:"
+msgid "To Location"
+msgstr "Spre Locație"
+
+msgctxt "field:sale.line,type:"
+msgid "Type"
+msgstr "Tip"
+
+msgctxt "field:sale.line,unit:"
+msgid "Unit"
+msgstr "Unitate"
+
+msgctxt "field:sale.line,unit_digits:"
+msgid "Unit Digits"
+msgstr "Cifre de unitate"
+
+msgctxt "field:sale.line,unit_price:"
+msgid "Unit Price"
+msgstr "Preț unitar"
+
+msgctxt "field:sale.line,warehouse:"
+msgid "Warehouse"
+msgstr "Depozit"
+
+msgctxt "field:sale.line-account.tax,line:"
+msgid "Sale Line"
+msgstr "Rând de vânzare"
+
+msgctxt "field:sale.line-account.tax,tax:"
+msgid "Tax"
+msgstr "Impozit"
+
+msgctxt "field:sale.line-ignored-stock.move,move:"
+msgid "Move"
+msgstr "Mișcare"
+
+msgctxt "field:sale.line-ignored-stock.move,sale_line:"
+msgid "Sale Line"
+msgstr "Rând de vânzare"
+
+msgctxt "field:sale.line-recreated-stock.move,move:"
+msgid "Move"
+msgstr "Mișcare"
+
+msgctxt "field:sale.line-recreated-stock.move,sale_line:"
+msgid "Sale Line"
+msgstr "Rând de vânzare"
+
+msgctxt "field:sale.reporting.category,category:"
+msgid "Category"
+msgstr "Categorie"
+
+msgctxt "field:sale.reporting.category,time_series:"
+msgid "Time Series"
+msgstr "Seria de timp"
+
+msgctxt "field:sale.reporting.category.time_series,category:"
+msgid "Category"
+msgstr "Categorie"
+
+msgctxt "field:sale.reporting.category.time_series,date:"
+msgid "Date"
+msgstr "Data"
+
+msgctxt "field:sale.reporting.category.tree,children:"
+msgid "Children"
+msgstr "Copii"
+
+msgctxt "field:sale.reporting.category.tree,currency_digits:"
+msgid "Currency Digits"
+msgstr "Zecimale valută"
+
+msgctxt "field:sale.reporting.category.tree,name:"
+msgid "Name"
+msgstr "Denumire"
+
+msgctxt "field:sale.reporting.category.tree,parent:"
+msgid "Parent"
+msgstr "Părinte"
+
+msgctxt "field:sale.reporting.category.tree,revenue:"
+msgid "Revenue"
+msgstr "Venituri"
+
+msgctxt "field:sale.reporting.context,company:"
+msgid "Company"
+msgstr "Companie"
+
+msgctxt "field:sale.reporting.context,from_date:"
+msgid "From Date"
+msgstr "Din data"
+
+msgctxt "field:sale.reporting.context,period:"
+msgid "Period"
+msgstr "Perioadă"
+
+msgctxt "field:sale.reporting.context,to_date:"
+msgid "To Date"
+msgstr "pâna la Data"
+
+msgctxt "field:sale.reporting.context,warehouse:"
+msgid "Warehouse"
+msgstr "Depozit"
+
+msgctxt "field:sale.reporting.country,country:"
+msgid "Country"
+msgstr "Țară"
+
+msgctxt "field:sale.reporting.country,time_series:"
+msgid "Time Series"
+msgstr "Seria de timp"
+
+msgctxt "field:sale.reporting.country.subdivision,country:"
+msgid "Country"
+msgstr "Țară"
+
+msgctxt "field:sale.reporting.country.subdivision,subdivision:"
+msgid "Subdivision"
+msgstr "Subdiviziune"
+
+msgctxt "field:sale.reporting.country.subdivision,time_series:"
+msgid "Time Series"
+msgstr "Seria de timp"
+
+msgctxt "field:sale.reporting.country.subdivision.time_series,country:"
+msgid "Country"
+msgstr "Țară"
+
+msgctxt "field:sale.reporting.country.subdivision.time_series,date:"
+msgid "Date"
+msgstr "Data"
+
+msgctxt "field:sale.reporting.country.subdivision.time_series,subdivision:"
+msgid "Subdivision"
+msgstr "Subdiviziune"
+
+msgctxt "field:sale.reporting.country.time_series,country:"
+msgid "Country"
+msgstr "Țară"
+
+msgctxt "field:sale.reporting.country.time_series,date:"
+msgid "Date"
+msgstr "Data"
+
+msgctxt "field:sale.reporting.customer,customer:"
+msgid "Customer"
+msgstr "Client"
+
+msgctxt "field:sale.reporting.customer,time_series:"
+msgid "Time Series"
+msgstr "Seria de timp"
+
+msgctxt "field:sale.reporting.customer.time_series,customer:"
+msgid "Customer"
+msgstr "Client"
+
+msgctxt "field:sale.reporting.customer.time_series,date:"
+msgid "Date"
+msgstr "Data"
+
+msgctxt "field:sale.reporting.product,product:"
+msgid "Product"
+msgstr "Produs"
+
+msgctxt "field:sale.reporting.product,time_series:"
+msgid "Time Series"
+msgstr "Seria de timp"
+
+msgctxt "field:sale.reporting.product.time_series,date:"
+msgid "Date"
+msgstr "Data"
+
+msgctxt "field:sale.reporting.product.time_series,product:"
+msgid "Product"
+msgstr "Produs"
+
+msgctxt "field:sale.reporting.region,children:"
+msgid "Children"
+msgstr "Copii"
+
+msgctxt "field:sale.reporting.region,parent:"
+msgid "Parent"
+msgstr "Părinte"
+
+msgctxt "field:sale.reporting.region,region:"
+msgid "Region"
+msgstr "Regiune"
+
+msgctxt "field:sale.sale,comment:"
+msgid "Comment"
+msgstr "Cometariu"
+
+msgctxt "field:sale.sale,company:"
+msgid "Company"
+msgstr "Companie"
+
+msgctxt "field:sale.sale,confirmed_by:"
+msgid "Confirmed By"
+msgstr "Confirmat de"
+
+msgctxt "field:sale.sale,contact:"
+msgid "Contact"
+msgstr "Legatura"
+
+msgctxt "field:sale.sale,currency:"
+msgid "Currency"
+msgstr "Valută"
+
+msgctxt "field:sale.sale,currency_digits:"
+msgid "Currency Digits"
+msgstr "Zecimale valută"
+
+msgctxt "field:sale.sale,description:"
+msgid "Description"
+msgstr "Descriere"
+
+msgctxt "field:sale.sale,invoice_address:"
+msgid "Invoice Address"
+msgstr "Adresa de facturare"
+
+msgctxt "field:sale.sale,invoice_method:"
+msgid "Invoice Method"
+msgstr "Metoda de facturare"
+
+msgctxt "field:sale.sale,invoice_party:"
+msgid "Invoice Party"
+msgstr "Parte Facturata"
+
+msgctxt "field:sale.sale,invoice_state:"
+msgid "Invoice State"
+msgstr "Stare Factura"
+
+msgctxt "field:sale.sale,invoices:"
+msgid "Invoices"
+msgstr "Facturi"
+
+msgctxt "field:sale.sale,invoices_ignored:"
+msgid "Ignored Invoices"
+msgstr "Facturi ignorate"
+
+msgctxt "field:sale.sale,invoices_recreated:"
+msgid "Recreated Invoices"
+msgstr "Facturi recreate"
+
+msgctxt "field:sale.sale,lines:"
+msgid "Lines"
+msgstr "Rânduri"
+
+msgctxt "field:sale.sale,moves:"
+msgid "Moves"
+msgstr "Mișcări"
+
+msgctxt "field:sale.sale,number:"
+msgid "Number"
+msgstr "Număr"
+
+msgctxt "field:sale.sale,origin:"
+msgid "Origin"
+msgstr "Origine"
+
+msgctxt "field:sale.sale,party:"
+msgid "Party"
+msgstr "Parte"
+
+msgctxt "field:sale.sale,party_lang:"
+msgid "Party Language"
+msgstr "Limba Părții"
+
+msgctxt "field:sale.sale,payment_term:"
+msgid "Payment Term"
+msgstr "Termen de plata"
+
+msgctxt "field:sale.sale,quoted_by:"
+msgid "Quoted By"
+msgstr "Ofertat de"
+
+msgctxt "field:sale.sale,reference:"
+msgid "Reference"
+msgstr "Referinţă"
+
+msgctxt "field:sale.sale,sale_date:"
+msgid "Sale Date"
+msgstr "Data vanzarii"
+
+msgctxt "field:sale.sale,shipment_address:"
+msgid "Shipment Address"
+msgstr "Adresa de expediere"
+
+msgctxt "field:sale.sale,shipment_method:"
+msgid "Shipment Method"
+msgstr "Metoda de expediere"
+
+msgctxt "field:sale.sale,shipment_party:"
+msgid "Shipment Party"
+msgstr "Parte Expeditor"
+
+msgctxt "field:sale.sale,shipment_returns:"
+msgid "Shipment Returns"
+msgstr "Retururi expediție"
+
+msgctxt "field:sale.sale,shipment_state:"
+msgid "Shipment State"
+msgstr "Data de expediere"
+
+msgctxt "field:sale.sale,shipments:"
+msgid "Shipments"
+msgstr "Transporturi"
+
+msgctxt "field:sale.sale,shipping_date:"
+msgid "Shipping Date"
+msgstr "Data de expediere"
+
+msgctxt "field:sale.sale,state:"
+msgid "State"
+msgstr "Stare"
+
+msgctxt "field:sale.sale,tax_amount:"
+msgid "Tax"
+msgstr "Impozit"
+
+#, fuzzy
+msgctxt "field:sale.sale,tax_amount_cache:"
+msgid "Tax Cache"
+msgstr "Impozit precalculat"
+
+msgctxt "field:sale.sale,total_amount:"
+msgid "Total"
+msgstr "Total"
+
+#, fuzzy
+msgctxt "field:sale.sale,total_amount_cache:"
+msgid "Total Cache"
+msgstr "Impozit precalculat"
+
+msgctxt "field:sale.sale,untaxed_amount:"
+msgid "Untaxed"
+msgstr "Neimpozitat"
+
+#, fuzzy
+msgctxt "field:sale.sale,untaxed_amount_cache:"
+msgid "Untaxed Cache"
+msgstr "Baza de impozitare"
+
+msgctxt "field:sale.sale,warehouse:"
+msgid "Warehouse"
+msgstr "Depozit"
+
+msgctxt "field:sale.sale-ignored-account.invoice,invoice:"
+msgid "Invoice"
+msgstr "Factura fiscala"
+
+msgctxt "field:sale.sale-ignored-account.invoice,sale:"
+msgid "Sale"
+msgstr "Vânzare"
+
+msgctxt "field:sale.sale-recreated-account.invoice,invoice:"
+msgid "Invoice"
+msgstr "Factura fiscala"
+
+msgctxt "field:sale.sale-recreated-account.invoice,sale:"
+msgid "Sale"
+msgstr "Vânzare"
+
+msgctxt "field:stock.move,sale:"
+msgid "Sale"
+msgstr "Vânzare"
+
+msgctxt "field:stock.move,sale_exception_state:"
+msgid "Exception State"
+msgstr "Stare de excepție"
+
+msgctxt "help:product.configuration,default_lead_time:"
+msgid ""
+"The time from confirming the sales order to sending the products.\n"
+"Used for products without a lead time."
+msgstr ""
+"Timpul între confirmarea vânzării pana la trimiterea al produselor.\n"
+"Utilizat pentru produse fără un timp de execuţie."
+
+msgctxt "help:product.product,lead_time:"
+msgid ""
+"The time from confirming the sales order to sending the products.\n"
+"If empty the default lead time from the configuration is used."
+msgstr ""
+"Timpul de la confirmarea vânzării pana la trimiterea al produselor.\n"
+"Daca este gol se va folosi timpul implicit de execuţie."
+
+msgctxt "help:product.template,lead_time:"
+msgid ""
+"The time from confirming the sales order to sending the products.\n"
+"If empty the default lead time from the configuration is used."
+msgstr ""
+"Timpul de la confirmarea vânzării pana la trimiterea al produselor.\n"
+"Daca este gol se va folosi timpul implicit de execuţie."
+
+msgctxt "help:sale.configuration,sale_process_after:"
+msgid ""
+"The grace period during which confirmed sale can still be reset to draft.\n"
+"Applied if a worker queue is activated."
+msgstr ""
+"Perioada de grație în timpul căreia vânzarea confirmată poate fi încă resetată la draft.\n"
+"Se aplică dacă este activată o coadă de muncitori."
+
+msgctxt "help:sale.handle.invoice.exception.ask,recreate_invoices:"
+msgid ""
+"The selected invoices will be recreated. The other ones will be ignored."
+msgstr "Facturile selectate vor fi recreate. Celelalte vor fi ignorate."
+
+msgctxt "help:sale.sale,shipping_date:"
+msgid "When the shipping of goods should start."
+msgstr "Când ar trebui sa se expediază marfa."
+
+msgctxt "model:ir.action,name:act_invoice_form"
+msgid "Invoices"
+msgstr "Facturi"
+
+msgctxt "model:ir.action,name:act_open_customer"
+msgid "Parties associated to Sales"
+msgstr "Părțile asociate Vânzărilor"
+
+msgctxt "model:ir.action,name:act_product"
+msgid "Products"
+msgstr "Produse"
+
+msgctxt "model:ir.action,name:act_reporting_category"
+msgid "Sales per Category"
+msgstr "Vânzări pe categorii"
+
+msgctxt "model:ir.action,name:act_reporting_category_time_series"
+msgid "Sales per Category"
+msgstr "Vânzări pe categorii"
+
+msgctxt "model:ir.action,name:act_reporting_category_tree"
+msgid "Sales per Category"
+msgstr "Vânzări pe categorii"
+
+msgctxt "model:ir.action,name:act_reporting_country_subdivision_time_series"
+msgid "Sales per Subdivision"
+msgstr "Vânzări pe subdiviziune"
+
+msgctxt "model:ir.action,name:act_reporting_country_time_series"
+msgid "Sales per Country"
+msgstr "Vânzări pe țară"
+
+msgctxt "model:ir.action,name:act_reporting_customer"
+msgid "Sales per Customer"
+msgstr "Vânzări pe client"
+
+msgctxt "model:ir.action,name:act_reporting_customer_time_series"
+msgid "Sales per Customer"
+msgstr "Vânzări pe client"
+
+msgctxt "model:ir.action,name:act_reporting_product"
+msgid "Sales per Product"
+msgstr "Vânzări pe produs"
+
+msgctxt "model:ir.action,name:act_reporting_product_time_series"
+msgid "Sales per Product"
+msgstr "Vânzări pe produs"
+
+msgctxt "model:ir.action,name:act_reporting_region"
+msgid "Sales per Region"
+msgstr "Vânzări pe regiune"
+
+msgctxt "model:ir.action,name:act_return_form"
+msgid "Returns"
+msgstr "Retururi"
+
+msgctxt "model:ir.action,name:act_sale_configuration_form"
+msgid "Configuration"
+msgstr "Configurare"
+
+msgctxt "model:ir.action,name:act_sale_form"
+msgid "Sales"
+msgstr "Vânzări"
+
+msgctxt "model:ir.action,name:act_sale_form2"
+msgid "Sales"
+msgstr "Vânzări"
+
+msgctxt "model:ir.action,name:act_sale_invoice_relate"
+msgid "Sales"
+msgstr "Vânzări"
+
+msgctxt "model:ir.action,name:act_sale_move_relate"
+msgid "Moves"
+msgstr "Mișcări"
+
+msgctxt "model:ir.action,name:act_sale_shipment_returns_relate"
+msgid "Sales"
+msgstr "Vânzări"
+
+msgctxt "model:ir.action,name:act_sale_shipments_relate"
+msgid "Sales"
+msgstr "Vânzări"
+
+msgctxt "model:ir.action,name:act_shipment_form"
+msgid "Shipments"
+msgstr "Transporturi"
+
+msgctxt "model:ir.action,name:report_sale"
+msgid "Sale"
+msgstr "Vânzare"
+
+msgctxt "model:ir.action,name:wizard_invoice_handle_exception"
+msgid "Handle Invoice Exception"
+msgstr "Gestionare Excepție Factura"
+
+msgctxt "model:ir.action,name:wizard_modify_header"
+msgid "Modify Header"
+msgstr "Modificați antetul"
+
+msgctxt "model:ir.action,name:wizard_reporting_region_open"
+msgid "Open Region"
+msgstr "Regiune deschisă"
+
+msgctxt "model:ir.action,name:wizard_return_sale"
+msgid "Return Sale"
+msgstr "Retur Vânzarii"
+
+msgctxt "model:ir.action,name:wizard_shipment_handle_exception"
+msgid "Handle Shipment Exception"
+msgstr "Gestioneaza Excepție de expediere"
+
+msgctxt "model:ir.action.act_window.domain,name:act_sale_form_domain_all"
+msgid "All"
+msgstr "Tot"
+
+msgctxt ""
+"model:ir.action.act_window.domain,name:act_sale_form_domain_confirmed"
+msgid "Confirmed"
+msgstr "Confirmat"
+
+msgctxt "model:ir.action.act_window.domain,name:act_sale_form_domain_draft"
+msgid "Draft"
+msgstr "Draft"
+
+msgctxt ""
+"model:ir.action.act_window.domain,name:act_sale_form_domain_exception"
+msgid "Exception"
+msgstr "Excepție"
+
+msgctxt ""
+"model:ir.action.act_window.domain,name:act_sale_form_domain_processing"
+msgid "Processing"
+msgstr "Se prelucreaza"
+
+msgctxt ""
+"model:ir.action.act_window.domain,name:act_sale_form_domain_quotation"
+msgid "Quotation"
+msgstr "Ofertă"
+
+msgctxt "model:ir.message,text:msg_erase_party_pending_sale"
+msgid ""
+"You cannot erase party \"%(party)s\" while they have pending sales with "
+"company \"%(company)s\"."
+msgstr ""
+"Nu se poate șterge parte \"%(party)s\" când au vănzări nefinalizate cu "
+"compania \"%(company)s\"."
+
+msgctxt "model:ir.message,text:msg_sale_customer_location_required"
+msgid ""
+"To process sale \"%(sale)s\" you must set a customer location on party "
+"\"%(party)s\"."
+msgstr ""
+"Pentru a procesa vânzarea \"%(sale)s\" trebuie setata o locatie pentru parte"
+" \"%(party)s\"."
+
+msgctxt "model:ir.message,text:msg_sale_delete_cancel"
+msgid "To delete sale \"%(sale)s\" you must cancel it."
+msgstr "Pentru a șterge vânzarea \"%(sale)s\" trebuie să o anulați."
+
+msgctxt "model:ir.message,text:msg_sale_invalid_method"
+msgid ""
+"You cannot use together invoice \"%(invoice_method)s\" and shipment "
+"\"%(shipment_method)s\" on sale \"%(sale)s\"."
+msgstr ""
+"Nu puteți utiliza împreună factura \"%(invoice_method)s\" si "
+"expediere\"%(shipment_method)s\" la vănzare \"%(sale)s\"."
+
+msgctxt ""
+"model:ir.message,text:msg_sale_invoice_address_required_for_quotation"
+msgid "To get a quote for sale \"%(sale)s\" you must enter an invoice address."
+msgstr ""
+"Pentru a obține o ofertă pentru vânzarea \"%(sale)s\" trebuie să introduceți"
+" o adresă de facturare."
+
+msgctxt "model:ir.message,text:msg_sale_invoice_reset_draft"
+msgid ""
+"You cannot reset invoice \"%(invoice)s\" to draft because it was generated "
+"by a sale."
+msgstr ""
+"Nu puteți devalida factura \"%(invoice)s\", deoarece a fost generată de o "
+"vânzare."
+
+msgctxt "model:ir.message,text:msg_sale_line_delete_cancel_draft"
+msgid ""
+"To delete line \"%(line)s\" you must cancel or reset to draft sale "
+"\"%(sale)s\"."
+msgstr ""
+"Pentru a șterge rândul \"%(line)s\" trebuie anulat sau resetat \"%(sale)s\" "
+"la proiectul de vânzare."
+
+msgctxt "model:ir.message,text:msg_sale_missing_account_revenue"
+msgid "To invoice sale \"%(sale)s\" you must configure a default account revenue."
+msgstr ""
+"Pentru facturarea vânzării \"%(sale)s\" trebuie să configurati un cont "
+"implicit pentru venit."
+
+msgctxt "model:ir.message,text:msg_sale_modify_header_draft"
+msgid "To modify the header of sale \"%(sale)s\", it must be in \"draft\" state."
+msgstr ""
+"Pentru a modifica antetul vânzării \"%(sale)s\", acesta trebuie să fie în "
+"stare devalidata."
+
+msgctxt "model:ir.message,text:msg_sale_move_reset_draft"
+msgid ""
+"You cannot reset move \"%(move)s\" to draft because it was generated by a "
+"sale."
+msgstr ""
+"Devalidarea a mișcarii \"%(move)s\" nu este posibilă deoarece a fost "
+"generată de o vânzare."
+
+msgctxt "model:ir.message,text:msg_sale_product_missing_account_revenue"
+msgid ""
+"To invoice sale \"%(sale)s\" you must define an account revenue for product "
+"\"%(product)s\"."
+msgstr ""
+"Pentru facturarea vânzării \"%(sale)s\" trebuie definit un cont de venit "
+"pentru produsul \"%(product)s\"."
+
+msgctxt "model:ir.message,text:msg_sale_reporting_company"
+msgid "Company"
+msgstr "Companie"
+
+msgctxt "model:ir.message,text:msg_sale_reporting_currency"
+msgid "Currency"
+msgstr "Valută"
+
+msgctxt "model:ir.message,text:msg_sale_reporting_currency_digits"
+msgid "Currency Digits"
+msgstr "Zecimale valută"
+
+msgctxt "model:ir.message,text:msg_sale_reporting_number"
+msgid "#"
+msgstr "#"
+
+msgctxt "model:ir.message,text:msg_sale_reporting_number_help"
+msgid "Number of sales"
+msgstr "Numărul de vânzări"
+
+msgctxt "model:ir.message,text:msg_sale_reporting_revenue"
+msgid "Revenue"
+msgstr "Venit"
+
+msgctxt "model:ir.message,text:msg_sale_reporting_revenue_trend"
+msgid "Revenue Trend"
+msgstr "Tendința veniturilor"
+
+msgctxt ""
+"model:ir.message,text:msg_sale_shipment_address_required_for_quotation"
+msgid "To get a quote for sale \"%(sale)s\" you must enter a shipment address."
+msgstr ""
+"Pentru a obține o ofertă pentru vânzarea \"%(sale)s\" trebuie să introduceți"
+" o adresă de expediere."
+
+msgctxt "model:ir.message,text:msg_sale_warehouse_required_for_quotation"
+msgid "To get a quote for sale \"%(sale)s\" you must enter a warehouse."
+msgstr ""
+"Pentru a obține o ofertă de vânzare \"%(sale)s\" trebuie să specificați un "
+"depozit."
+
+msgctxt "model:ir.model.button,string:sale_cancel_button"
+msgid "Cancel"
+msgstr "Anulare"
+
+msgctxt "model:ir.model.button,string:sale_confirm_button"
+msgid "Confirm"
+msgstr "Confirmare"
+
+msgctxt "model:ir.model.button,string:sale_draft_button"
+msgid "Draft"
+msgstr "Draft"
+
+msgctxt "model:ir.model.button,string:sale_handle_invoice_exception_button"
+msgid "Handle Invoice Exception"
+msgstr "Gestionare Excepție Factura"
+
+msgctxt "model:ir.model.button,string:sale_handle_shipment_exception_button"
+msgid "Handle Shipment Exception"
+msgstr "Gestioneaza Excepție de expediere"
+
+msgctxt "model:ir.model.button,string:sale_modify_header_button"
+msgid "Modify Header"
+msgstr "Modificare Antet"
+
+msgctxt "model:ir.model.button,string:sale_process_button"
+msgid "Process"
+msgstr "Proces"
+
+msgctxt "model:ir.model.button,string:sale_quote_button"
+msgid "Quote"
+msgstr "Ofertă"
+
+msgctxt "model:ir.rule.group,name:rule_group_reporting_category_companies"
+msgid "User in companies"
+msgstr "Utilizator în companii"
+
+msgctxt ""
+"model:ir.rule.group,name:rule_group_reporting_category_time_series_companies"
+msgid "User in companies"
+msgstr "Utilizator în companii"
+
+msgctxt ""
+"model:ir.rule.group,name:rule_group_reporting_country_subdivision_time_series_companies"
+msgid "User in companies"
+msgstr "Utilizator în companii"
+
+msgctxt ""
+"model:ir.rule.group,name:rule_group_reporting_country_time_series_companies"
+msgid "User in companies"
+msgstr "Utilizator în companii"
+
+msgctxt "model:ir.rule.group,name:rule_group_reporting_customer_companies"
+msgid "User in companies"
+msgstr "Utilizator în companii"
+
+msgctxt ""
+"model:ir.rule.group,name:rule_group_reporting_customer_time_series_companies"
+msgid "User in companies"
+msgstr "Utilizator în companii"
+
+msgctxt "model:ir.rule.group,name:rule_group_reporting_product_companies"
+msgid "User in companies"
+msgstr "Utilizator în companii"
+
+msgctxt ""
+"model:ir.rule.group,name:rule_group_reporting_product_time_series_companies"
+msgid "User in companies"
+msgstr "Utilizator în companii"
+
+msgctxt "model:ir.rule.group,name:rule_group_reporting_region_companies"
+msgid "User in companies"
+msgstr "Utilizator în companii"
+
+msgctxt "model:ir.rule.group,name:rule_group_sale_companies"
+msgid "User in companies"
+msgstr "Utilizator în companii"
+
+msgctxt "model:ir.sequence,name:sequence_sale"
+msgid "Sale"
+msgstr "Vânzare"
+
+msgctxt "model:ir.sequence.type,name:sequence_type_sale"
+msgid "Sale"
+msgstr "Vânzare"
+
+msgctxt "model:ir.ui.menu,name:menu_configuration"
+msgid "Configuration"
+msgstr "Configurare"
+
+msgctxt "model:ir.ui.menu,name:menu_customer"
+msgid "Associated to Sales"
+msgstr "Părți asociate Vânzărilor"
+
+msgctxt "model:ir.ui.menu,name:menu_product"
+msgid "Products"
+msgstr "Produse"
+
+msgctxt "model:ir.ui.menu,name:menu_reporting"
+msgid "Reporting"
+msgstr "Raportare"
+
+msgctxt "model:ir.ui.menu,name:menu_reporting_sale"
+msgid "Sales"
+msgstr "Vânzări"
+
+msgctxt "model:ir.ui.menu,name:menu_sale"
+msgid "Sales"
+msgstr "Vânzări"
+
+msgctxt "model:ir.ui.menu,name:menu_sale_configuration"
+msgid "Configuration"
+msgstr "Configurare"
+
+msgctxt "model:ir.ui.menu,name:menu_sale_form"
+msgid "Sales"
+msgstr "Vânzări"
+
+msgctxt "model:product.configuration.default_lead_time,name:"
+msgid "Product Default Lead Time"
+msgstr "Timpul Implicit de Execuţie al Produsului"
+
+msgctxt "model:product.sale.context,name:"
+msgid "Product Sale Context"
+msgstr "Contextul vânzării produselor"
+
+msgctxt "model:res.group,name:group_sale"
+msgid "Sales"
+msgstr "Vânzări"
+
+msgctxt "model:res.group,name:group_sale_admin"
+msgid "Sales Administrator"
+msgstr "Administrator de Vanzari"
+
+msgctxt "model:sale.configuration,name:"
+msgid "Sale Configuration"
+msgstr "Configurare vânzări"
+
+msgctxt "model:sale.configuration.sale_method,name:"
+msgid "Sale Configuration Sale Method"
+msgstr "Configurare metoda de vânzare"
+
+msgctxt "model:sale.configuration.sequence,name:"
+msgid "Sale Configuration Sequence"
+msgstr "Configurare Secvență Vânzare"
+
+msgctxt "model:sale.handle.invoice.exception.ask,name:"
+msgid "Handle Invoice Exception"
+msgstr "Gestionare Excepție Factura"
+
+msgctxt "model:sale.handle.shipment.exception.ask,name:"
+msgid "Handle Shipment Exception"
+msgstr "Gestioneaza Excepție de expediere"
+
+msgctxt "model:sale.line,name:"
+msgid "Sale Line"
+msgstr "Rând de vânzare"
+
+msgctxt "model:sale.line-account.tax,name:"
+msgid "Sale Line - Tax"
+msgstr "Linie de vânzare - impozit"
+
+msgctxt "model:sale.line-ignored-stock.move,name:"
+msgid "Sale Line - Ignored Move"
+msgstr "Linie de vânzare - Mișcare Ignorată"
+
+msgctxt "model:sale.line-recreated-stock.move,name:"
+msgid "Sale Line - Recreated Move"
+msgstr "Rând de vânzare - Mișcare recreată"
+
+msgctxt "model:sale.reporting.category,name:"
+msgid "Sale Reporting per Category"
+msgstr "Raportarea vânzărilor pe categorii"
+
+msgctxt "model:sale.reporting.category.time_series,name:"
+msgid "Sale Reporting per Category"
+msgstr "Raportarea vânzărilor pe categorii"
+
+msgctxt "model:sale.reporting.category.tree,name:"
+msgid "Sale Reporting per Category"
+msgstr "Raportarea vânzărilor pe țară"
+
+msgctxt "model:sale.reporting.context,name:"
+msgid "Sale Reporting Context"
+msgstr "Contextul raportării vânzărilor"
+
+msgctxt "model:sale.reporting.country,name:"
+msgid "Sale Reporting per Country"
+msgstr "Raportarea vânzărilor pe țară"
+
+msgctxt "model:sale.reporting.country.subdivision,name:"
+msgid "Sale Reporting per Subdivision"
+msgstr "Raportarea vânzărilor pe subdiviziune"
+
+msgctxt "model:sale.reporting.country.subdivision.time_series,name:"
+msgid "Sale Reporting per Subdivision"
+msgstr "Raportarea vânzărilor pe subdiviziune"
+
+msgctxt "model:sale.reporting.country.time_series,name:"
+msgid "Sale Reporting per Country"
+msgstr "Raportarea vânzărilor pe țară"
+
+msgctxt "model:sale.reporting.customer,name:"
+msgid "Sale Reporting per Customer"
+msgstr "Raportarea vânzărilor pe client"
+
+msgctxt "model:sale.reporting.customer.time_series,name:"
+msgid "Sale Reporting per Customer"
+msgstr "Raportarea vânzărilor pe client"
+
+msgctxt "model:sale.reporting.product,name:"
+msgid "Sale Reporting per Product"
+msgstr "Raportarea vânzărilor pe produs"
+
+msgctxt "model:sale.reporting.product.time_series,name:"
+msgid "Sale Reporting per Product"
+msgstr "Raportarea vânzărilor pe produs"
+
+msgctxt "model:sale.reporting.region,name:"
+msgid "Sale Reporting per Region"
+msgstr "Raportarea vânzărilor pe regiune"
+
+msgctxt "model:sale.return_sale.start,name:"
+msgid "Return Sale"
+msgstr "Retur Vânzare"
+
+msgctxt "model:sale.sale,name:"
+msgid "Sale"
+msgstr "Vânzare"
+
+msgctxt "model:sale.sale-ignored-account.invoice,name:"
+msgid "Sale - Ignored Invoice"
+msgstr "Vânzare - factură ignorată"
+
+msgctxt "model:sale.sale-recreated-account.invoice,name:"
+msgid "Sale - Recreated Invoice"
+msgstr "Vânzare - factură recreată"
+
+msgctxt "report:sale.sale:"
+msgid ":"
+msgstr ":"
+
+msgctxt "report:sale.sale:"
+msgid "Amount"
+msgstr "Suma"
+
+msgctxt "report:sale.sale:"
+msgid "Date:"
+msgstr "Data:"
+
+msgctxt "report:sale.sale:"
+msgid "Description"
+msgstr "Descriere"
+
+msgctxt "report:sale.sale:"
+msgid "Description:"
+msgstr "Descriere:"
+
+msgctxt "report:sale.sale:"
+msgid "Draft Sale Order"
+msgstr "Comanda devalidata"
+
+msgctxt "report:sale.sale:"
+msgid "Quantity"
+msgstr "Cantitate"
+
+msgctxt "report:sale.sale:"
+msgid "Quotation N°:"
+msgstr "Oferta N°:"
+
+msgctxt "report:sale.sale:"
+msgid "Reference:"
+msgstr "Referinţă:"
+
+msgctxt "report:sale.sale:"
+msgid "Sale Order N°:"
+msgstr "Nr. Comandă de vânzare:"
+
+msgctxt "report:sale.sale:"
+msgid "Taxes"
+msgstr "Impozite"
+
+msgctxt "report:sale.sale:"
+msgid "Taxes:"
+msgstr "Impozite:"
+
+msgctxt "report:sale.sale:"
+msgid "Total (excl. taxes):"
+msgstr "Total (fără impozite):"
+
+msgctxt "report:sale.sale:"
+msgid "Total:"
+msgstr "Total:"
+
+msgctxt "report:sale.sale:"
+msgid "Unit Price"
+msgstr "Preț unitar"
+
+msgctxt "selection:account.invoice,sale_exception_state:"
+msgid "Ignored"
+msgstr "Ignorat"
+
+msgctxt "selection:account.invoice,sale_exception_state:"
+msgid "Recreated"
+msgstr "Recreat"
+
+msgctxt "selection:sale.line,type:"
+msgid "Comment"
+msgstr "Cometariu"
+
+msgctxt "selection:sale.line,type:"
+msgid "Line"
+msgstr "Rând"
+
+msgctxt "selection:sale.line,type:"
+msgid "Subtotal"
+msgstr "Subtotal"
+
+msgctxt "selection:sale.line,type:"
+msgid "Title"
+msgstr "Titlu"
+
+msgctxt "selection:sale.reporting.context,period:"
+msgid "Day"
+msgstr "Zi"
+
+msgctxt "selection:sale.reporting.context,period:"
+msgid "Month"
+msgstr "Lună"
+
+msgctxt "selection:sale.reporting.context,period:"
+msgid "Year"
+msgstr "An"
+
+msgctxt "selection:sale.sale,invoice_method:"
+msgid "Manual"
+msgstr "Manual"
+
+msgctxt "selection:sale.sale,invoice_method:"
+msgid "On Order Processed"
+msgstr "La procesarea comenzii"
+
+msgctxt "selection:sale.sale,invoice_method:"
+msgid "On Shipment Sent"
+msgstr "La expediere trimis"
+
+msgctxt "selection:sale.sale,invoice_state:"
+msgid "Exception"
+msgstr "Excepție"
+
+msgctxt "selection:sale.sale,invoice_state:"
+msgid "None"
+msgstr "Nici unul"
+
+msgctxt "selection:sale.sale,invoice_state:"
+msgid "Paid"
+msgstr "Plătit"
+
+msgctxt "selection:sale.sale,invoice_state:"
+msgid "Waiting"
+msgstr "În Aşteptare"
+
+msgctxt "selection:sale.sale,shipment_method:"
+msgid "Manual"
+msgstr "Manual"
+
+msgctxt "selection:sale.sale,shipment_method:"
+msgid "On Invoice Paid"
+msgstr "La plata facturii"
+
+msgctxt "selection:sale.sale,shipment_method:"
+msgid "On Order Processed"
+msgstr "La procesare comanda"
+
+msgctxt "selection:sale.sale,shipment_state:"
+msgid "Exception"
+msgstr "Excepție"
+
+msgctxt "selection:sale.sale,shipment_state:"
+msgid "None"
+msgstr "Nici unul"
+
+msgctxt "selection:sale.sale,shipment_state:"
+msgid "Sent"
+msgstr "Trimis"
+
+msgctxt "selection:sale.sale,shipment_state:"
+msgid "Waiting"
+msgstr "În Aşteptare"
+
+msgctxt "selection:sale.sale,state:"
+msgid "Cancelled"
+msgstr "Anulat"
+
+msgctxt "selection:sale.sale,state:"
+msgid "Confirmed"
+msgstr "Confirmat"
+
+msgctxt "selection:sale.sale,state:"
+msgid "Done"
+msgstr "Terminat"
+
+msgctxt "selection:sale.sale,state:"
+msgid "Draft"
+msgstr "Draft"
+
+msgctxt "selection:sale.sale,state:"
+msgid "Processing"
+msgstr "Se prelucreaza"
+
+msgctxt "selection:sale.sale,state:"
+msgid "Quotation"
+msgstr "Ofertă"
+
+msgctxt "selection:stock.move,sale_exception_state:"
+msgid "Ignored"
+msgstr "Ignorat"
+
+msgctxt "selection:stock.move,sale_exception_state:"
+msgid "Recreated"
+msgstr "Recreat"
+
+msgctxt "view:party.party:"
+msgid "Sale"
+msgstr "Vânzare"
+
+msgctxt "view:product.template:"
+msgid "Customers"
+msgstr "Clienți"
+
+msgctxt "view:sale.handle.invoice.exception.ask:"
+msgid "Choose invoices to recreate:"
+msgstr "Alegeți facturi de recreat:"
+
+msgctxt "view:sale.handle.shipment.exception.ask:"
+msgid "Choose move to recreate:"
+msgstr "Alegeți mișarea pentru a recrea:"
+
+msgctxt "view:sale.line:"
+msgid "General"
+msgstr "General"
+
+msgctxt "view:sale.line:"
+msgid "Notes"
+msgstr "Notițe"
+
+msgctxt "view:sale.line:"
+msgid "Taxes"
+msgstr "Impozite"
+
+msgctxt "view:sale.return_sale.start:"
+msgid "Are you sure to return these/this sale(s)?"
+msgstr "Sunteți sigur că veți returna aceste vânzări /această vânzare?"
+
+msgctxt "view:sale.sale:"
+msgid "Other Info"
+msgstr "Alte informații"
+
+msgctxt "view:sale.sale:"
+msgid "Sale"
+msgstr "Vânzare"
+
+msgctxt "wizard_button:sale.handle.invoice.exception,ask,end:"
+msgid "Cancel"
+msgstr "Anulare"
+
+msgctxt "wizard_button:sale.handle.invoice.exception,ask,handle:"
+msgid "OK"
+msgstr "OK"
+
+msgctxt "wizard_button:sale.handle.shipment.exception,ask,end:"
+msgid "Cancel"
+msgstr "Anulare"
+
+msgctxt "wizard_button:sale.handle.shipment.exception,ask,handle:"
+msgid "OK"
+msgstr "OK"
+
+msgctxt "wizard_button:sale.modify_header,start,end:"
+msgid "Cancel"
+msgstr "Anulare"
+
+msgctxt "wizard_button:sale.modify_header,start,modify:"
+msgid "Modify"
+msgstr "Modificare"
+
+msgctxt "wizard_button:sale.return_sale,start,end:"
+msgid "Cancel"
+msgstr "Anulare"
+
+msgctxt "wizard_button:sale.return_sale,start,return_:"
+msgid "Return"
+msgstr "Retur"
diff --git a/modules/sale/locale/ru.po b/modules/sale/locale/ru.po
new file mode 100644
index 0000000000..aea34af58d
--- /dev/null
+++ b/modules/sale/locale/ru.po
@@ -0,0 +1,1423 @@
+#
+msgid ""
+msgstr "Content-Type: text/plain; charset=utf-8\n"
+
+msgctxt "field:account.invoice,sale_exception_state:"
+msgid "Exception State"
+msgstr "Состояние ситуации"
+
+msgctxt "field:account.invoice,sales:"
+msgid "Sales"
+msgstr "Продажи"
+
+msgctxt "field:product.configuration,default_lead_time:"
+msgid "Default Lead Time"
+msgstr ""
+
+#, fuzzy
+msgctxt "field:product.configuration.default_lead_time,company:"
+msgid "Company"
+msgstr "Организация"
+
+msgctxt "field:product.configuration.default_lead_time,default_lead_time:"
+msgid "Default Lead Time"
+msgstr ""
+
+msgctxt "field:product.product,lead_time:"
+msgid "Lead Time"
+msgstr ""
+
+#, fuzzy
+msgctxt "field:product.product,salable:"
+msgid "Salable"
+msgstr "Для продажи"
+
+msgctxt "field:product.product,sale_price_uom:"
+msgid "Sale Price"
+msgstr ""
+
+#, fuzzy
+msgctxt "field:product.product,sale_uom:"
+msgid "Sale UOM"
+msgstr "Ед.измерения продажи"
+
+#, fuzzy
+msgctxt "field:product.sale.context,company:"
+msgid "Company"
+msgstr "Организация"
+
+#, fuzzy
+msgctxt "field:product.sale.context,currency:"
+msgid "Currency"
+msgstr "Валюта"
+
+#, fuzzy
+msgctxt "field:product.sale.context,customer:"
+msgid "Customer"
+msgstr "Заказчики"
+
+#, fuzzy
+msgctxt "field:product.sale.context,locations:"
+msgid "Warehouses"
+msgstr "Товарный склад"
+
+#, fuzzy
+msgctxt "field:product.sale.context,quantity:"
+msgid "Quantity"
+msgstr "Кол-во"
+
+#, fuzzy
+msgctxt "field:product.sale.context,sale_date:"
+msgid "Sale Date"
+msgstr "Дата продажи"
+
+msgctxt "field:product.sale.context,stock_date_end:"
+msgid "Stock End Date"
+msgstr ""
+
+msgctxt "field:product.template,lead_time:"
+msgid "Lead Time"
+msgstr ""
+
+msgctxt "field:product.template,salable:"
+msgid "Salable"
+msgstr "Для продажи"
+
+msgctxt "field:product.template,sale_uom:"
+msgid "Sale UOM"
+msgstr "Ед.измерения продажи"
+
+msgctxt "field:sale.configuration,sale_invoice_method:"
+msgid "Sale Invoice Method"
+msgstr "Метод инвойса продажи"
+
+msgctxt "field:sale.configuration,sale_process_after:"
+msgid "Process Sale after"
+msgstr ""
+
+msgctxt "field:sale.configuration,sale_sequence:"
+msgid "Sale Sequence"
+msgstr ""
+
+msgctxt "field:sale.configuration,sale_shipment_method:"
+msgid "Sale Shipment Method"
+msgstr "Способ доставки продажи"
+
+#, fuzzy
+msgctxt "field:sale.configuration.sale_method,sale_invoice_method:"
+msgid "Sale Invoice Method"
+msgstr "Метод инвойса продажи"
+
+#, fuzzy
+msgctxt "field:sale.configuration.sale_method,sale_shipment_method:"
+msgid "Sale Shipment Method"
+msgstr "Способ доставки продажи"
+
+#, fuzzy
+msgctxt "field:sale.configuration.sequence,company:"
+msgid "Company"
+msgstr "Организация"
+
+msgctxt "field:sale.configuration.sequence,sale_sequence:"
+msgid "Sale Sequence"
+msgstr ""
+
+msgctxt "field:sale.handle.invoice.exception.ask,domain_invoices:"
+msgid "Domain Invoices"
+msgstr "Домен инвойсов"
+
+msgctxt "field:sale.handle.invoice.exception.ask,recreate_invoices:"
+msgid "Recreate Invoices"
+msgstr "Создать заново инвойсы"
+
+msgctxt "field:sale.handle.shipment.exception.ask,domain_moves:"
+msgid "Domain Moves"
+msgstr "Домен проводок"
+
+msgctxt "field:sale.handle.shipment.exception.ask,recreate_moves:"
+msgid "Recreate Moves"
+msgstr "Создать заново проводки"
+
+#, fuzzy
+msgctxt "field:sale.line,actual_quantity:"
+msgid "Actual Quantity"
+msgstr "Кол-во"
+
+msgctxt "field:sale.line,amount:"
+msgid "Amount"
+msgstr "Сумма"
+
+#, fuzzy
+msgctxt "field:sale.line,company:"
+msgid "Company"
+msgstr "Организация"
+
+#, fuzzy
+msgctxt "field:sale.line,currency:"
+msgid "Currency"
+msgstr "Валюта"
+
+msgctxt "field:sale.line,description:"
+msgid "Description"
+msgstr "Описание"
+
+msgctxt "field:sale.line,from_location:"
+msgid "From Location"
+msgstr "Из местоположения"
+
+msgctxt "field:sale.line,invoice_lines:"
+msgid "Invoice Lines"
+msgstr "Строки инвойса"
+
+msgctxt "field:sale.line,move_done:"
+msgid "Moves Done"
+msgstr "Перемещения выполнены"
+
+msgctxt "field:sale.line,move_exception:"
+msgid "Moves Exception"
+msgstr "Особые ситуации перемещения"
+
+msgctxt "field:sale.line,moves:"
+msgid "Moves"
+msgstr "Перемещения"
+
+msgctxt "field:sale.line,moves_ignored:"
+msgid "Ignored Moves"
+msgstr "Игнорированные проводки"
+
+msgctxt "field:sale.line,moves_recreated:"
+msgid "Recreated Moves"
+msgstr "Созданные заново проводки"
+
+msgctxt "field:sale.line,note:"
+msgid "Note"
+msgstr "Комментарий"
+
+msgctxt "field:sale.line,product:"
+msgid "Product"
+msgstr "Продукт"
+
+msgctxt "field:sale.line,product_uom_category:"
+msgid "Product Uom Category"
+msgstr "Категория ед. измерения продукции"
+
+msgctxt "field:sale.line,quantity:"
+msgid "Quantity"
+msgstr "Кол-во"
+
+msgctxt "field:sale.line,sale:"
+msgid "Sale"
+msgstr "Продажа"
+
+#, fuzzy
+msgctxt "field:sale.line,sale_state:"
+msgid "Sale State"
+msgstr "Дата продажи"
+
+msgctxt "field:sale.line,shipping_date:"
+msgid "Shipping Date"
+msgstr ""
+
+msgctxt "field:sale.line,summary:"
+msgid "Summary"
+msgstr ""
+
+msgctxt "field:sale.line,taxes:"
+msgid "Taxes"
+msgstr "Налоги"
+
+msgctxt "field:sale.line,to_location:"
+msgid "To Location"
+msgstr "В местоположение"
+
+msgctxt "field:sale.line,type:"
+msgid "Type"
+msgstr "Тип"
+
+msgctxt "field:sale.line,unit:"
+msgid "Unit"
+msgstr "Единица измерения"
+
+msgctxt "field:sale.line,unit_digits:"
+msgid "Unit Digits"
+msgstr "Кол-во цифр после запятой"
+
+msgctxt "field:sale.line,unit_price:"
+msgid "Unit Price"
+msgstr "Цена за единицу"
+
+msgctxt "field:sale.line,warehouse:"
+msgid "Warehouse"
+msgstr "Товарный склад"
+
+msgctxt "field:sale.line-account.tax,line:"
+msgid "Sale Line"
+msgstr "Строка продажи"
+
+msgctxt "field:sale.line-account.tax,tax:"
+msgid "Tax"
+msgstr "Налог"
+
+msgctxt "field:sale.line-ignored-stock.move,move:"
+msgid "Move"
+msgstr "Перемещение"
+
+msgctxt "field:sale.line-ignored-stock.move,sale_line:"
+msgid "Sale Line"
+msgstr "Строка продажи"
+
+msgctxt "field:sale.line-recreated-stock.move,move:"
+msgid "Move"
+msgstr "Перемещение"
+
+msgctxt "field:sale.line-recreated-stock.move,sale_line:"
+msgid "Sale Line"
+msgstr "Строка продажи"
+
+msgctxt "field:sale.reporting.category,category:"
+msgid "Category"
+msgstr ""
+
+msgctxt "field:sale.reporting.category,time_series:"
+msgid "Time Series"
+msgstr ""
+
+msgctxt "field:sale.reporting.category.time_series,category:"
+msgid "Category"
+msgstr ""
+
+#, fuzzy
+msgctxt "field:sale.reporting.category.time_series,date:"
+msgid "Date"
+msgstr "Дата:"
+
+msgctxt "field:sale.reporting.category.tree,children:"
+msgid "Children"
+msgstr ""
+
+#, fuzzy
+msgctxt "field:sale.reporting.category.tree,currency_digits:"
+msgid "Currency Digits"
+msgstr "Кол-во цифр валюты"
+
+#, fuzzy
+msgctxt "field:sale.reporting.category.tree,name:"
+msgid "Name"
+msgstr "Наименование"
+
+msgctxt "field:sale.reporting.category.tree,parent:"
+msgid "Parent"
+msgstr ""
+
+msgctxt "field:sale.reporting.category.tree,revenue:"
+msgid "Revenue"
+msgstr ""
+
+#, fuzzy
+msgctxt "field:sale.reporting.context,company:"
+msgid "Company"
+msgstr "Организация"
+
+msgctxt "field:sale.reporting.context,from_date:"
+msgid "From Date"
+msgstr ""
+
+msgctxt "field:sale.reporting.context,period:"
+msgid "Period"
+msgstr ""
+
+msgctxt "field:sale.reporting.context,to_date:"
+msgid "To Date"
+msgstr ""
+
+#, fuzzy
+msgctxt "field:sale.reporting.context,warehouse:"
+msgid "Warehouse"
+msgstr "Товарный склад"
+
+msgctxt "field:sale.reporting.country,country:"
+msgid "Country"
+msgstr ""
+
+msgctxt "field:sale.reporting.country,time_series:"
+msgid "Time Series"
+msgstr ""
+
+msgctxt "field:sale.reporting.country.subdivision,country:"
+msgid "Country"
+msgstr ""
+
+msgctxt "field:sale.reporting.country.subdivision,subdivision:"
+msgid "Subdivision"
+msgstr ""
+
+msgctxt "field:sale.reporting.country.subdivision,time_series:"
+msgid "Time Series"
+msgstr ""
+
+msgctxt "field:sale.reporting.country.subdivision.time_series,country:"
+msgid "Country"
+msgstr ""
+
+#, fuzzy
+msgctxt "field:sale.reporting.country.subdivision.time_series,date:"
+msgid "Date"
+msgstr "Дата:"
+
+msgctxt "field:sale.reporting.country.subdivision.time_series,subdivision:"
+msgid "Subdivision"
+msgstr ""
+
+msgctxt "field:sale.reporting.country.time_series,country:"
+msgid "Country"
+msgstr ""
+
+#, fuzzy
+msgctxt "field:sale.reporting.country.time_series,date:"
+msgid "Date"
+msgstr "Дата:"
+
+#, fuzzy
+msgctxt "field:sale.reporting.customer,customer:"
+msgid "Customer"
+msgstr "Заказчики"
+
+msgctxt "field:sale.reporting.customer,time_series:"
+msgid "Time Series"
+msgstr ""
+
+#, fuzzy
+msgctxt "field:sale.reporting.customer.time_series,customer:"
+msgid "Customer"
+msgstr "Заказчики"
+
+#, fuzzy
+msgctxt "field:sale.reporting.customer.time_series,date:"
+msgid "Date"
+msgstr "Дата:"
+
+#, fuzzy
+msgctxt "field:sale.reporting.product,product:"
+msgid "Product"
+msgstr "Продукт"
+
+msgctxt "field:sale.reporting.product,time_series:"
+msgid "Time Series"
+msgstr ""
+
+#, fuzzy
+msgctxt "field:sale.reporting.product.time_series,date:"
+msgid "Date"
+msgstr "Дата:"
+
+#, fuzzy
+msgctxt "field:sale.reporting.product.time_series,product:"
+msgid "Product"
+msgstr "Продукт"
+
+msgctxt "field:sale.reporting.region,children:"
+msgid "Children"
+msgstr ""
+
+msgctxt "field:sale.reporting.region,parent:"
+msgid "Parent"
+msgstr ""
+
+msgctxt "field:sale.reporting.region,region:"
+msgid "Region"
+msgstr ""
+
+msgctxt "field:sale.sale,comment:"
+msgid "Comment"
+msgstr "Комментарии"
+
+msgctxt "field:sale.sale,company:"
+msgid "Company"
+msgstr "Организация"
+
+#, fuzzy
+msgctxt "field:sale.sale,confirmed_by:"
+msgid "Confirmed By"
+msgstr "Confirmed"
+
+msgctxt "field:sale.sale,contact:"
+msgid "Contact"
+msgstr ""
+
+msgctxt "field:sale.sale,currency:"
+msgid "Currency"
+msgstr "Валюта"
+
+msgctxt "field:sale.sale,currency_digits:"
+msgid "Currency Digits"
+msgstr "Кол-во цифр валюты"
+
+msgctxt "field:sale.sale,description:"
+msgid "Description"
+msgstr "Описание"
+
+msgctxt "field:sale.sale,invoice_address:"
+msgid "Invoice Address"
+msgstr "Адрес для инвойса"
+
+msgctxt "field:sale.sale,invoice_method:"
+msgid "Invoice Method"
+msgstr "Метод инвойса"
+
+#, fuzzy
+msgctxt "field:sale.sale,invoice_party:"
+msgid "Invoice Party"
+msgstr "Состояние инвойса"
+
+msgctxt "field:sale.sale,invoice_state:"
+msgid "Invoice State"
+msgstr "Состояние инвойса"
+
+msgctxt "field:sale.sale,invoices:"
+msgid "Invoices"
+msgstr "Инвойсы"
+
+msgctxt "field:sale.sale,invoices_ignored:"
+msgid "Ignored Invoices"
+msgstr "Игнорированные инвойсы"
+
+msgctxt "field:sale.sale,invoices_recreated:"
+msgid "Recreated Invoices"
+msgstr "Созданные заново инвойсы"
+
+msgctxt "field:sale.sale,lines:"
+msgid "Lines"
+msgstr "Строки"
+
+msgctxt "field:sale.sale,moves:"
+msgid "Moves"
+msgstr "Перемещения"
+
+#, fuzzy
+msgctxt "field:sale.sale,number:"
+msgid "Number"
+msgstr "Номер"
+
+#, fuzzy
+msgctxt "field:sale.sale,origin:"
+msgid "Origin"
+msgstr "Первоисточник"
+
+msgctxt "field:sale.sale,party:"
+msgid "Party"
+msgstr "Контрагент"
+
+msgctxt "field:sale.sale,party_lang:"
+msgid "Party Language"
+msgstr "Язык контрагента"
+
+msgctxt "field:sale.sale,payment_term:"
+msgid "Payment Term"
+msgstr "Правило оплаты"
+
+#, fuzzy
+msgctxt "field:sale.sale,quoted_by:"
+msgid "Quoted By"
+msgstr "Quote"
+
+msgctxt "field:sale.sale,reference:"
+msgid "Reference"
+msgstr "Ссылка"
+
+msgctxt "field:sale.sale,sale_date:"
+msgid "Sale Date"
+msgstr "Дата продажи"
+
+msgctxt "field:sale.sale,shipment_address:"
+msgid "Shipment Address"
+msgstr "Адрес доставки"
+
+msgctxt "field:sale.sale,shipment_method:"
+msgid "Shipment Method"
+msgstr "Метод доставки"
+
+msgctxt "field:sale.sale,shipment_party:"
+msgid "Shipment Party"
+msgstr ""
+
+msgctxt "field:sale.sale,shipment_returns:"
+msgid "Shipment Returns"
+msgstr "Возврат"
+
+msgctxt "field:sale.sale,shipment_state:"
+msgid "Shipment State"
+msgstr "Состояние доставки"
+
+msgctxt "field:sale.sale,shipments:"
+msgid "Shipments"
+msgstr "Доставка"
+
+#, fuzzy
+msgctxt "field:sale.sale,shipping_date:"
+msgid "Shipping Date"
+msgstr "Состояние доставки"
+
+msgctxt "field:sale.sale,state:"
+msgid "State"
+msgstr "Состояние"
+
+msgctxt "field:sale.sale,tax_amount:"
+msgid "Tax"
+msgstr "Налог"
+
+msgctxt "field:sale.sale,tax_amount_cache:"
+msgid "Tax Cache"
+msgstr "Облагаемые налогом"
+
+msgctxt "field:sale.sale,total_amount:"
+msgid "Total"
+msgstr "Итого"
+
+#, fuzzy
+msgctxt "field:sale.sale,total_amount_cache:"
+msgid "Total Cache"
+msgstr "Облагаемые налогом"
+
+msgctxt "field:sale.sale,untaxed_amount:"
+msgid "Untaxed"
+msgstr "Без налога"
+
+msgctxt "field:sale.sale,untaxed_amount_cache:"
+msgid "Untaxed Cache"
+msgstr "Необлагаемые налогом"
+
+msgctxt "field:sale.sale,warehouse:"
+msgid "Warehouse"
+msgstr "Товарный склад"
+
+msgctxt "field:sale.sale-ignored-account.invoice,invoice:"
+msgid "Invoice"
+msgstr "Инвойс"
+
+msgctxt "field:sale.sale-ignored-account.invoice,sale:"
+msgid "Sale"
+msgstr "Продажа"
+
+msgctxt "field:sale.sale-recreated-account.invoice,invoice:"
+msgid "Invoice"
+msgstr "Инвойс"
+
+msgctxt "field:sale.sale-recreated-account.invoice,sale:"
+msgid "Sale"
+msgstr "Продажа"
+
+msgctxt "field:stock.move,sale:"
+msgid "Sale"
+msgstr "Продажа"
+
+msgctxt "field:stock.move,sale_exception_state:"
+msgid "Exception State"
+msgstr "Состояние ситуации"
+
+msgctxt "help:product.configuration,default_lead_time:"
+msgid ""
+"The time from confirming the sales order to sending the products.\n"
+"Used for products without a lead time."
+msgstr ""
+
+msgctxt "help:product.product,lead_time:"
+msgid ""
+"The time from confirming the sales order to sending the products.\n"
+"If empty the default lead time from the configuration is used."
+msgstr ""
+
+msgctxt "help:product.template,lead_time:"
+msgid ""
+"The time from confirming the sales order to sending the products.\n"
+"If empty the default lead time from the configuration is used."
+msgstr ""
+
+msgctxt "help:sale.configuration,sale_process_after:"
+msgid ""
+"The grace period during which confirmed sale can still be reset to draft.\n"
+"Applied if a worker queue is activated."
+msgstr ""
+
+msgctxt "help:sale.handle.invoice.exception.ask,recreate_invoices:"
+msgid ""
+"The selected invoices will be recreated. The other ones will be ignored."
+msgstr ""
+"Выбранные инвойсы будут созданы заново. Остальные будут проигнорированы."
+
+msgctxt "help:sale.sale,shipping_date:"
+msgid "When the shipping of goods should start."
+msgstr ""
+
+#, fuzzy
+msgctxt "model:ir.action,name:act_invoice_form"
+msgid "Invoices"
+msgstr "Invoices"
+
+#, fuzzy
+msgctxt "model:ir.action,name:act_open_customer"
+msgid "Parties associated to Sales"
+msgstr "Parties associated to Sales"
+
+#, fuzzy
+msgctxt "model:ir.action,name:act_product"
+msgid "Products"
+msgstr "Продукт"
+
+msgctxt "model:ir.action,name:act_reporting_category"
+msgid "Sales per Category"
+msgstr "Sales per Category"
+
+msgctxt "model:ir.action,name:act_reporting_category_time_series"
+msgid "Sales per Category"
+msgstr "Sales per Category"
+
+msgctxt "model:ir.action,name:act_reporting_category_tree"
+msgid "Sales per Category"
+msgstr "Sales per Category"
+
+msgctxt "model:ir.action,name:act_reporting_country_subdivision_time_series"
+msgid "Sales per Subdivision"
+msgstr "Sales per Subdivision"
+
+msgctxt "model:ir.action,name:act_reporting_country_time_series"
+msgid "Sales per Country"
+msgstr "Sales per Country"
+
+msgctxt "model:ir.action,name:act_reporting_customer"
+msgid "Sales per Customer"
+msgstr "Sales per Customer"
+
+msgctxt "model:ir.action,name:act_reporting_customer_time_series"
+msgid "Sales per Customer"
+msgstr "Sales per Customer"
+
+msgctxt "model:ir.action,name:act_reporting_product"
+msgid "Sales per Product"
+msgstr "Sales per Product"
+
+msgctxt "model:ir.action,name:act_reporting_product_time_series"
+msgid "Sales per Product"
+msgstr "Sales per Product"
+
+msgctxt "model:ir.action,name:act_reporting_region"
+msgid "Sales per Region"
+msgstr "Sales per Region"
+
+#, fuzzy
+msgctxt "model:ir.action,name:act_return_form"
+msgid "Returns"
+msgstr "Returns"
+
+#, fuzzy
+msgctxt "model:ir.action,name:act_sale_configuration_form"
+msgid "Configuration"
+msgstr "Configuration"
+
+#, fuzzy
+msgctxt "model:ir.action,name:act_sale_form"
+msgid "Sales"
+msgstr "Sales"
+
+#, fuzzy
+msgctxt "model:ir.action,name:act_sale_form2"
+msgid "Sales"
+msgstr "Sales"
+
+#, fuzzy
+msgctxt "model:ir.action,name:act_sale_invoice_relate"
+msgid "Sales"
+msgstr "Продажи"
+
+#, fuzzy
+msgctxt "model:ir.action,name:act_sale_move_relate"
+msgid "Moves"
+msgstr "Перемещения"
+
+msgctxt "model:ir.action,name:act_sale_shipment_returns_relate"
+msgid "Sales"
+msgstr "Sales"
+
+#, fuzzy
+msgctxt "model:ir.action,name:act_sale_shipments_relate"
+msgid "Sales"
+msgstr "Продажи"
+
+#, fuzzy
+msgctxt "model:ir.action,name:act_shipment_form"
+msgid "Shipments"
+msgstr "Shipments"
+
+#, fuzzy
+msgctxt "model:ir.action,name:report_sale"
+msgid "Sale"
+msgstr "Sale"
+
+#, fuzzy
+msgctxt "model:ir.action,name:wizard_invoice_handle_exception"
+msgid "Handle Invoice Exception"
+msgstr "Handle Invoice Exception"
+
+msgctxt "model:ir.action,name:wizard_modify_header"
+msgid "Modify Header"
+msgstr "Modify Header"
+
+msgctxt "model:ir.action,name:wizard_reporting_region_open"
+msgid "Open Region"
+msgstr "Open Region"
+
+#, fuzzy
+msgctxt "model:ir.action,name:wizard_return_sale"
+msgid "Return Sale"
+msgstr "Создать возврат продажи"
+
+#, fuzzy
+msgctxt "model:ir.action,name:wizard_shipment_handle_exception"
+msgid "Handle Shipment Exception"
+msgstr "Handle Shipment Exception"
+
+#, fuzzy
+msgctxt "model:ir.action.act_window.domain,name:act_sale_form_domain_all"
+msgid "All"
+msgstr "All"
+
+#, fuzzy
+msgctxt ""
+"model:ir.action.act_window.domain,name:act_sale_form_domain_confirmed"
+msgid "Confirmed"
+msgstr "Confirmed"
+
+#, fuzzy
+msgctxt "model:ir.action.act_window.domain,name:act_sale_form_domain_draft"
+msgid "Draft"
+msgstr "Draft"
+
+#, fuzzy
+msgctxt ""
+"model:ir.action.act_window.domain,name:act_sale_form_domain_exception"
+msgid "Exception"
+msgstr "Особая ситуация"
+
+#, fuzzy
+msgctxt ""
+"model:ir.action.act_window.domain,name:act_sale_form_domain_processing"
+msgid "Processing"
+msgstr "Processing"
+
+#, fuzzy
+msgctxt ""
+"model:ir.action.act_window.domain,name:act_sale_form_domain_quotation"
+msgid "Quotation"
+msgstr "Quotation"
+
+msgctxt "model:ir.message,text:msg_erase_party_pending_sale"
+msgid ""
+"You cannot erase party \"%(party)s\" while they have pending sales with "
+"company \"%(company)s\"."
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_sale_customer_location_required"
+msgid ""
+"To process sale \"%(sale)s\" you must set a customer location on party "
+"\"%(party)s\"."
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_sale_delete_cancel"
+msgid "To delete sale \"%(sale)s\" you must cancel it."
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_sale_invalid_method"
+msgid ""
+"You cannot use together invoice \"%(invoice_method)s\" and shipment "
+"\"%(shipment_method)s\" on sale \"%(sale)s\"."
+msgstr ""
+
+msgctxt ""
+"model:ir.message,text:msg_sale_invoice_address_required_for_quotation"
+msgid "To get a quote for sale \"%(sale)s\" you must enter an invoice address."
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_sale_invoice_reset_draft"
+msgid ""
+"You cannot reset invoice \"%(invoice)s\" to draft because it was generated "
+"by a sale."
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_sale_line_delete_cancel_draft"
+msgid ""
+"To delete line \"%(line)s\" you must cancel or reset to draft sale "
+"\"%(sale)s\"."
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_sale_missing_account_revenue"
+msgid "To invoice sale \"%(sale)s\" you must configure a default account revenue."
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_sale_modify_header_draft"
+msgid "To modify the header of sale \"%(sale)s\", it must be in \"draft\" state."
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_sale_move_reset_draft"
+msgid ""
+"You cannot reset move \"%(move)s\" to draft because it was generated by a "
+"sale."
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_sale_product_missing_account_revenue"
+msgid ""
+"To invoice sale \"%(sale)s\" you must define an account revenue for product "
+"\"%(product)s\"."
+msgstr ""
+
+#, fuzzy
+msgctxt "model:ir.message,text:msg_sale_reporting_company"
+msgid "Company"
+msgstr "Организация"
+
+#, fuzzy
+msgctxt "model:ir.message,text:msg_sale_reporting_currency"
+msgid "Currency"
+msgstr "Валюта"
+
+#, fuzzy
+msgctxt "model:ir.message,text:msg_sale_reporting_currency_digits"
+msgid "Currency Digits"
+msgstr "Кол-во цифр валюты"
+
+#, fuzzy
+msgctxt "model:ir.message,text:msg_sale_reporting_number"
+msgid "#"
+msgstr "#"
+
+msgctxt "model:ir.message,text:msg_sale_reporting_number_help"
+msgid "Number of sales"
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_sale_reporting_revenue"
+msgid "Revenue"
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_sale_reporting_revenue_trend"
+msgid "Revenue Trend"
+msgstr ""
+
+msgctxt ""
+"model:ir.message,text:msg_sale_shipment_address_required_for_quotation"
+msgid "To get a quote for sale \"%(sale)s\" you must enter a shipment address."
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_sale_warehouse_required_for_quotation"
+msgid "To get a quote for sale \"%(sale)s\" you must enter a warehouse."
+msgstr ""
+
+msgctxt "model:ir.model.button,string:sale_cancel_button"
+msgid "Cancel"
+msgstr "Cancel"
+
+msgctxt "model:ir.model.button,string:sale_confirm_button"
+msgid "Confirm"
+msgstr "Confirm"
+
+msgctxt "model:ir.model.button,string:sale_draft_button"
+msgid "Draft"
+msgstr "Draft"
+
+msgctxt "model:ir.model.button,string:sale_handle_invoice_exception_button"
+msgid "Handle Invoice Exception"
+msgstr "Handle Invoice Exception"
+
+msgctxt "model:ir.model.button,string:sale_handle_shipment_exception_button"
+msgid "Handle Shipment Exception"
+msgstr "Handle Shipment Exception"
+
+msgctxt "model:ir.model.button,string:sale_modify_header_button"
+msgid "Modify Header"
+msgstr "Modify Header"
+
+msgctxt "model:ir.model.button,string:sale_process_button"
+msgid "Process"
+msgstr "Process"
+
+msgctxt "model:ir.model.button,string:sale_quote_button"
+msgid "Quote"
+msgstr "Quote"
+
+msgctxt "model:ir.rule.group,name:rule_group_reporting_category_companies"
+msgid "User in companies"
+msgstr ""
+
+msgctxt ""
+"model:ir.rule.group,name:rule_group_reporting_category_time_series_companies"
+msgid "User in companies"
+msgstr ""
+
+msgctxt ""
+"model:ir.rule.group,name:rule_group_reporting_country_subdivision_time_series_companies"
+msgid "User in companies"
+msgstr ""
+
+msgctxt ""
+"model:ir.rule.group,name:rule_group_reporting_country_time_series_companies"
+msgid "User in companies"
+msgstr ""
+
+msgctxt "model:ir.rule.group,name:rule_group_reporting_customer_companies"
+msgid "User in companies"
+msgstr ""
+
+msgctxt ""
+"model:ir.rule.group,name:rule_group_reporting_customer_time_series_companies"
+msgid "User in companies"
+msgstr ""
+
+msgctxt "model:ir.rule.group,name:rule_group_reporting_product_companies"
+msgid "User in companies"
+msgstr ""
+
+msgctxt ""
+"model:ir.rule.group,name:rule_group_reporting_product_time_series_companies"
+msgid "User in companies"
+msgstr ""
+
+msgctxt "model:ir.rule.group,name:rule_group_reporting_region_companies"
+msgid "User in companies"
+msgstr ""
+
+msgctxt "model:ir.rule.group,name:rule_group_sale_companies"
+msgid "User in companies"
+msgstr ""
+
+#, fuzzy
+msgctxt "model:ir.sequence,name:sequence_sale"
+msgid "Sale"
+msgstr "Sale"
+
+#, fuzzy
+msgctxt "model:ir.sequence.type,name:sequence_type_sale"
+msgid "Sale"
+msgstr "Sale"
+
+#, fuzzy
+msgctxt "model:ir.ui.menu,name:menu_configuration"
+msgid "Configuration"
+msgstr "Configuration"
+
+#, fuzzy
+msgctxt "model:ir.ui.menu,name:menu_customer"
+msgid "Associated to Sales"
+msgstr "Parties associated to Sales"
+
+#, fuzzy
+msgctxt "model:ir.ui.menu,name:menu_product"
+msgid "Products"
+msgstr "Продукт"
+
+msgctxt "model:ir.ui.menu,name:menu_reporting"
+msgid "Reporting"
+msgstr "Reporting"
+
+msgctxt "model:ir.ui.menu,name:menu_reporting_sale"
+msgid "Sales"
+msgstr "Sales"
+
+#, fuzzy
+msgctxt "model:ir.ui.menu,name:menu_sale"
+msgid "Sales"
+msgstr "Sales"
+
+#, fuzzy
+msgctxt "model:ir.ui.menu,name:menu_sale_configuration"
+msgid "Configuration"
+msgstr "Configuration"
+
+#, fuzzy
+msgctxt "model:ir.ui.menu,name:menu_sale_form"
+msgid "Sales"
+msgstr "Sales"
+
+msgctxt "model:product.configuration.default_lead_time,name:"
+msgid "Product Default Lead Time"
+msgstr ""
+
+msgctxt "model:product.sale.context,name:"
+msgid "Product Sale Context"
+msgstr ""
+
+#, fuzzy
+msgctxt "model:res.group,name:group_sale"
+msgid "Sales"
+msgstr "Sales"
+
+#, fuzzy
+msgctxt "model:res.group,name:group_sale_admin"
+msgid "Sales Administrator"
+msgstr "Sales Administrator"
+
+msgctxt "model:sale.configuration,name:"
+msgid "Sale Configuration"
+msgstr "Конфигурация продаж"
+
+msgctxt "model:sale.configuration.sale_method,name:"
+msgid "Sale Configuration Sale Method"
+msgstr ""
+
+msgctxt "model:sale.configuration.sequence,name:"
+msgid "Sale Configuration Sequence"
+msgstr ""
+
+msgctxt "model:sale.handle.invoice.exception.ask,name:"
+msgid "Handle Invoice Exception"
+msgstr "Обработка особых ситуаций инвойса"
+
+msgctxt "model:sale.handle.shipment.exception.ask,name:"
+msgid "Handle Shipment Exception"
+msgstr "Обработка особых ситуаций доставки"
+
+msgctxt "model:sale.line,name:"
+msgid "Sale Line"
+msgstr "Строка продажи"
+
+msgctxt "model:sale.line-account.tax,name:"
+msgid "Sale Line - Tax"
+msgstr "Строка продажи - Налоги"
+
+msgctxt "model:sale.line-ignored-stock.move,name:"
+msgid "Sale Line - Ignored Move"
+msgstr "Строка продажи - Игнорированные перемещения"
+
+msgctxt "model:sale.line-recreated-stock.move,name:"
+msgid "Sale Line - Recreated Move"
+msgstr "Строка продажи - Созданные заново перемещения"
+
+msgctxt "model:sale.reporting.category,name:"
+msgid "Sale Reporting per Category"
+msgstr ""
+
+msgctxt "model:sale.reporting.category.time_series,name:"
+msgid "Sale Reporting per Category"
+msgstr ""
+
+msgctxt "model:sale.reporting.category.tree,name:"
+msgid "Sale Reporting per Category"
+msgstr ""
+
+msgctxt "model:sale.reporting.context,name:"
+msgid "Sale Reporting Context"
+msgstr ""
+
+msgctxt "model:sale.reporting.country,name:"
+msgid "Sale Reporting per Country"
+msgstr ""
+
+msgctxt "model:sale.reporting.country.subdivision,name:"
+msgid "Sale Reporting per Subdivision"
+msgstr ""
+
+msgctxt "model:sale.reporting.country.subdivision.time_series,name:"
+msgid "Sale Reporting per Subdivision"
+msgstr ""
+
+msgctxt "model:sale.reporting.country.time_series,name:"
+msgid "Sale Reporting per Country"
+msgstr ""
+
+msgctxt "model:sale.reporting.customer,name:"
+msgid "Sale Reporting per Customer"
+msgstr ""
+
+msgctxt "model:sale.reporting.customer.time_series,name:"
+msgid "Sale Reporting per Customer"
+msgstr ""
+
+msgctxt "model:sale.reporting.product,name:"
+msgid "Sale Reporting per Product"
+msgstr ""
+
+msgctxt "model:sale.reporting.product.time_series,name:"
+msgid "Sale Reporting per Product"
+msgstr ""
+
+msgctxt "model:sale.reporting.region,name:"
+msgid "Sale Reporting per Region"
+msgstr ""
+
+#, fuzzy
+msgctxt "model:sale.return_sale.start,name:"
+msgid "Return Sale"
+msgstr "Создать возврат продажи"
+
+msgctxt "model:sale.sale,name:"
+msgid "Sale"
+msgstr "Продажа"
+
+msgctxt "model:sale.sale-ignored-account.invoice,name:"
+msgid "Sale - Ignored Invoice"
+msgstr "Продажи - Игнорируемые инвойсы"
+
+msgctxt "model:sale.sale-recreated-account.invoice,name:"
+msgid "Sale - Recreated Invoice"
+msgstr "Продажи - Созданные заново инвойсы"
+
+#, fuzzy
+msgctxt "report:sale.sale:"
+msgid ":"
+msgstr ":"
+
+msgctxt "report:sale.sale:"
+msgid "Amount"
+msgstr "Сумма"
+
+msgctxt "report:sale.sale:"
+msgid "Date:"
+msgstr "Дата:"
+
+msgctxt "report:sale.sale:"
+msgid "Description"
+msgstr "Описание"
+
+msgctxt "report:sale.sale:"
+msgid "Description:"
+msgstr "Описание:"
+
+msgctxt "report:sale.sale:"
+msgid "Draft Sale Order"
+msgstr "Черновой заказ на продажу"
+
+msgctxt "report:sale.sale:"
+msgid "Quantity"
+msgstr "Кол-во"
+
+msgctxt "report:sale.sale:"
+msgid "Quotation N°:"
+msgstr "Котировка N°:"
+
+#, fuzzy
+msgctxt "report:sale.sale:"
+msgid "Reference:"
+msgstr "Ссылка"
+
+msgctxt "report:sale.sale:"
+msgid "Sale Order N°:"
+msgstr "Заказ на продажу №:"
+
+msgctxt "report:sale.sale:"
+msgid "Taxes"
+msgstr "Налоги"
+
+msgctxt "report:sale.sale:"
+msgid "Taxes:"
+msgstr "Налоги:"
+
+msgctxt "report:sale.sale:"
+msgid "Total (excl. taxes):"
+msgstr "Итого (без налогов):"
+
+msgctxt "report:sale.sale:"
+msgid "Total:"
+msgstr "Итого:"
+
+msgctxt "report:sale.sale:"
+msgid "Unit Price"
+msgstr "Цена за единицу"
+
+msgctxt "selection:account.invoice,sale_exception_state:"
+msgid "Ignored"
+msgstr "Игнорируется"
+
+msgctxt "selection:account.invoice,sale_exception_state:"
+msgid "Recreated"
+msgstr "Создано заново"
+
+msgctxt "selection:sale.line,type:"
+msgid "Comment"
+msgstr "Комментарии"
+
+msgctxt "selection:sale.line,type:"
+msgid "Line"
+msgstr "Строка"
+
+msgctxt "selection:sale.line,type:"
+msgid "Subtotal"
+msgstr "Подитог"
+
+msgctxt "selection:sale.line,type:"
+msgid "Title"
+msgstr "Заголовок"
+
+msgctxt "selection:sale.reporting.context,period:"
+msgid "Day"
+msgstr ""
+
+msgctxt "selection:sale.reporting.context,period:"
+msgid "Month"
+msgstr ""
+
+msgctxt "selection:sale.reporting.context,period:"
+msgid "Year"
+msgstr ""
+
+msgctxt "selection:sale.sale,invoice_method:"
+msgid "Manual"
+msgstr "Ручной"
+
+msgctxt "selection:sale.sale,invoice_method:"
+msgid "On Order Processed"
+msgstr "При обработке заказа"
+
+msgctxt "selection:sale.sale,invoice_method:"
+msgid "On Shipment Sent"
+msgstr "При отправке груза"
+
+msgctxt "selection:sale.sale,invoice_state:"
+msgid "Exception"
+msgstr "Особая ситуация"
+
+msgctxt "selection:sale.sale,invoice_state:"
+msgid "None"
+msgstr "Отсутствует"
+
+msgctxt "selection:sale.sale,invoice_state:"
+msgid "Paid"
+msgstr "Оплачен"
+
+msgctxt "selection:sale.sale,invoice_state:"
+msgid "Waiting"
+msgstr "Ожидание"
+
+msgctxt "selection:sale.sale,shipment_method:"
+msgid "Manual"
+msgstr "Ручной"
+
+msgctxt "selection:sale.sale,shipment_method:"
+msgid "On Invoice Paid"
+msgstr "При оплате инвойса"
+
+msgctxt "selection:sale.sale,shipment_method:"
+msgid "On Order Processed"
+msgstr "При обработке заказа"
+
+msgctxt "selection:sale.sale,shipment_state:"
+msgid "Exception"
+msgstr "Особая ситуация"
+
+msgctxt "selection:sale.sale,shipment_state:"
+msgid "None"
+msgstr "Отсутствует"
+
+msgctxt "selection:sale.sale,shipment_state:"
+msgid "Sent"
+msgstr "Отправлен"
+
+msgctxt "selection:sale.sale,shipment_state:"
+msgid "Waiting"
+msgstr "Ожидание"
+
+#, fuzzy
+msgctxt "selection:sale.sale,state:"
+msgid "Cancelled"
+msgstr "Отменено"
+
+msgctxt "selection:sale.sale,state:"
+msgid "Confirmed"
+msgstr "Подтвержденно"
+
+msgctxt "selection:sale.sale,state:"
+msgid "Done"
+msgstr "Выполнено"
+
+msgctxt "selection:sale.sale,state:"
+msgid "Draft"
+msgstr "Черновик"
+
+msgctxt "selection:sale.sale,state:"
+msgid "Processing"
+msgstr "Обработка"
+
+msgctxt "selection:sale.sale,state:"
+msgid "Quotation"
+msgstr "Котировка"
+
+msgctxt "selection:stock.move,sale_exception_state:"
+msgid "Ignored"
+msgstr "Игнорируется"
+
+msgctxt "selection:stock.move,sale_exception_state:"
+msgid "Recreated"
+msgstr "Создано заново"
+
+#, fuzzy
+msgctxt "view:party.party:"
+msgid "Sale"
+msgstr "Продажа"
+
+msgctxt "view:product.template:"
+msgid "Customers"
+msgstr "Заказчики"
+
+#, fuzzy
+msgctxt "view:sale.handle.invoice.exception.ask:"
+msgid "Choose invoices to recreate:"
+msgstr "Выберите инвойсы для пересоздания"
+
+#, fuzzy
+msgctxt "view:sale.handle.shipment.exception.ask:"
+msgid "Choose move to recreate:"
+msgstr "Выберите проводки для пересоздания"
+
+msgctxt "view:sale.line:"
+msgid "General"
+msgstr "Основной"
+
+msgctxt "view:sale.line:"
+msgid "Notes"
+msgstr "Комментарии"
+
+msgctxt "view:sale.line:"
+msgid "Taxes"
+msgstr "Налоги"
+
+msgctxt "view:sale.return_sale.start:"
+msgid "Are you sure to return these/this sale(s)?"
+msgstr ""
+
+msgctxt "view:sale.sale:"
+msgid "Other Info"
+msgstr "Другая информация"
+
+msgctxt "view:sale.sale:"
+msgid "Sale"
+msgstr "Продажа"
+
+msgctxt "wizard_button:sale.handle.invoice.exception,ask,end:"
+msgid "Cancel"
+msgstr "Отменить"
+
+msgctxt "wizard_button:sale.handle.invoice.exception,ask,handle:"
+msgid "OK"
+msgstr "Ок"
+
+msgctxt "wizard_button:sale.handle.shipment.exception,ask,end:"
+msgid "Cancel"
+msgstr "Отменить"
+
+msgctxt "wizard_button:sale.handle.shipment.exception,ask,handle:"
+msgid "OK"
+msgstr "Ок"
+
+#, fuzzy
+msgctxt "wizard_button:sale.modify_header,start,end:"
+msgid "Cancel"
+msgstr "Отменить"
+
+msgctxt "wizard_button:sale.modify_header,start,modify:"
+msgid "Modify"
+msgstr ""
+
+#, fuzzy
+msgctxt "wizard_button:sale.return_sale,start,end:"
+msgid "Cancel"
+msgstr "Отменить"
+
+#, fuzzy
+msgctxt "wizard_button:sale.return_sale,start,return_:"
+msgid "Return"
+msgstr "Возвраты"
diff --git a/modules/sale/locale/sl.po b/modules/sale/locale/sl.po
new file mode 100644
index 0000000000..ecc0113812
--- /dev/null
+++ b/modules/sale/locale/sl.po
@@ -0,0 +1,1411 @@
+#
+msgid ""
+msgstr "Content-Type: text/plain; charset=utf-8\n"
+
+msgctxt "field:account.invoice,sale_exception_state:"
+msgid "Exception State"
+msgstr "Pridržano"
+
+msgctxt "field:account.invoice,sales:"
+msgid "Sales"
+msgstr "Prodajni nalogi"
+
+#, fuzzy
+msgctxt "field:product.configuration,default_lead_time:"
+msgid "Default Lead Time"
+msgstr "Dobavni rok"
+
+#, fuzzy
+msgctxt "field:product.configuration.default_lead_time,company:"
+msgid "Company"
+msgstr "Družba"
+
+#, fuzzy
+msgctxt "field:product.configuration.default_lead_time,default_lead_time:"
+msgid "Default Lead Time"
+msgstr "Dobavni rok"
+
+msgctxt "field:product.product,lead_time:"
+msgid "Lead Time"
+msgstr "Dobavni rok"
+
+msgctxt "field:product.product,salable:"
+msgid "Salable"
+msgstr "Za prodajo"
+
+msgctxt "field:product.product,sale_price_uom:"
+msgid "Sale Price"
+msgstr "Prodajna cena"
+
+msgctxt "field:product.product,sale_uom:"
+msgid "Sale UOM"
+msgstr "Prodajna ME"
+
+#, fuzzy
+msgctxt "field:product.sale.context,company:"
+msgid "Company"
+msgstr "Družba"
+
+#, fuzzy
+msgctxt "field:product.sale.context,currency:"
+msgid "Currency"
+msgstr "Valuta"
+
+#, fuzzy
+msgctxt "field:product.sale.context,customer:"
+msgid "Customer"
+msgstr "Kupci"
+
+#, fuzzy
+msgctxt "field:product.sale.context,locations:"
+msgid "Warehouses"
+msgstr "Skladišče"
+
+#, fuzzy
+msgctxt "field:product.sale.context,quantity:"
+msgid "Quantity"
+msgstr "Količina"
+
+#, fuzzy
+msgctxt "field:product.sale.context,sale_date:"
+msgid "Sale Date"
+msgstr "Datum prodaje"
+
+msgctxt "field:product.sale.context,stock_date_end:"
+msgid "Stock End Date"
+msgstr ""
+
+msgctxt "field:product.template,lead_time:"
+msgid "Lead Time"
+msgstr "Dobavni rok"
+
+msgctxt "field:product.template,salable:"
+msgid "Salable"
+msgstr "Za prodajo"
+
+msgctxt "field:product.template,sale_uom:"
+msgid "Sale UOM"
+msgstr "Prodajna ME"
+
+msgctxt "field:sale.configuration,sale_invoice_method:"
+msgid "Sale Invoice Method"
+msgstr "Način obračuna"
+
+msgctxt "field:sale.configuration,sale_process_after:"
+msgid "Process Sale after"
+msgstr ""
+
+msgctxt "field:sale.configuration,sale_sequence:"
+msgid "Sale Sequence"
+msgstr "Štetje prodajnih nalogov"
+
+msgctxt "field:sale.configuration,sale_shipment_method:"
+msgid "Sale Shipment Method"
+msgstr "Način odpreme"
+
+msgctxt "field:sale.configuration.sale_method,sale_invoice_method:"
+msgid "Sale Invoice Method"
+msgstr "Način obračuna"
+
+msgctxt "field:sale.configuration.sale_method,sale_shipment_method:"
+msgid "Sale Shipment Method"
+msgstr "Način odpreme"
+
+msgctxt "field:sale.configuration.sequence,company:"
+msgid "Company"
+msgstr "Družba"
+
+msgctxt "field:sale.configuration.sequence,sale_sequence:"
+msgid "Sale Sequence"
+msgstr "Štetje prodajnih nalogov"
+
+msgctxt "field:sale.handle.invoice.exception.ask,domain_invoices:"
+msgid "Domain Invoices"
+msgstr "Vključeni računi"
+
+msgctxt "field:sale.handle.invoice.exception.ask,recreate_invoices:"
+msgid "Recreate Invoices"
+msgstr "Ponovno izdelani računi"
+
+msgctxt "field:sale.handle.shipment.exception.ask,domain_moves:"
+msgid "Domain Moves"
+msgstr "Vključen promet"
+
+msgctxt "field:sale.handle.shipment.exception.ask,recreate_moves:"
+msgid "Recreate Moves"
+msgstr "Ponovno izdelan promet"
+
+#, fuzzy
+msgctxt "field:sale.line,actual_quantity:"
+msgid "Actual Quantity"
+msgstr "Količina"
+
+msgctxt "field:sale.line,amount:"
+msgid "Amount"
+msgstr "Znesek"
+
+#, fuzzy
+msgctxt "field:sale.line,company:"
+msgid "Company"
+msgstr "Družba"
+
+#, fuzzy
+msgctxt "field:sale.line,currency:"
+msgid "Currency"
+msgstr "Valuta"
+
+msgctxt "field:sale.line,description:"
+msgid "Description"
+msgstr "Opis"
+
+msgctxt "field:sale.line,from_location:"
+msgid "From Location"
+msgstr "Iz lokacije"
+
+msgctxt "field:sale.line,invoice_lines:"
+msgid "Invoice Lines"
+msgstr "Postavke računa"
+
+msgctxt "field:sale.line,move_done:"
+msgid "Moves Done"
+msgstr "Zaključen promet"
+
+msgctxt "field:sale.line,move_exception:"
+msgid "Moves Exception"
+msgstr "Pridržani promet"
+
+msgctxt "field:sale.line,moves:"
+msgid "Moves"
+msgstr "Promet"
+
+msgctxt "field:sale.line,moves_ignored:"
+msgid "Ignored Moves"
+msgstr "Prezrt promet"
+
+msgctxt "field:sale.line,moves_recreated:"
+msgid "Recreated Moves"
+msgstr "Ponovno izdelan promet"
+
+msgctxt "field:sale.line,note:"
+msgid "Note"
+msgstr "Opomba"
+
+msgctxt "field:sale.line,product:"
+msgid "Product"
+msgstr "Izdelek"
+
+msgctxt "field:sale.line,product_uom_category:"
+msgid "Product Uom Category"
+msgstr "Katerogija EM izdelka"
+
+msgctxt "field:sale.line,quantity:"
+msgid "Quantity"
+msgstr "Količina"
+
+msgctxt "field:sale.line,sale:"
+msgid "Sale"
+msgstr "Prodajni nalog"
+
+msgctxt "field:sale.line,sale_state:"
+msgid "Sale State"
+msgstr "Stanje prodajnega naloga"
+
+msgctxt "field:sale.line,shipping_date:"
+msgid "Shipping Date"
+msgstr "Datum odpreme"
+
+msgctxt "field:sale.line,summary:"
+msgid "Summary"
+msgstr ""
+
+msgctxt "field:sale.line,taxes:"
+msgid "Taxes"
+msgstr "Davki"
+
+msgctxt "field:sale.line,to_location:"
+msgid "To Location"
+msgstr "Na lokacijo"
+
+msgctxt "field:sale.line,type:"
+msgid "Type"
+msgstr "Tip"
+
+msgctxt "field:sale.line,unit:"
+msgid "Unit"
+msgstr "Enota"
+
+msgctxt "field:sale.line,unit_digits:"
+msgid "Unit Digits"
+msgstr "Decimalke"
+
+msgctxt "field:sale.line,unit_price:"
+msgid "Unit Price"
+msgstr "Cena"
+
+msgctxt "field:sale.line,warehouse:"
+msgid "Warehouse"
+msgstr "Skladišče"
+
+msgctxt "field:sale.line-account.tax,line:"
+msgid "Sale Line"
+msgstr "Postavka"
+
+msgctxt "field:sale.line-account.tax,tax:"
+msgid "Tax"
+msgstr "Davek"
+
+msgctxt "field:sale.line-ignored-stock.move,move:"
+msgid "Move"
+msgstr "Promet"
+
+msgctxt "field:sale.line-ignored-stock.move,sale_line:"
+msgid "Sale Line"
+msgstr "Postavka"
+
+msgctxt "field:sale.line-recreated-stock.move,move:"
+msgid "Move"
+msgstr "Promet"
+
+msgctxt "field:sale.line-recreated-stock.move,sale_line:"
+msgid "Sale Line"
+msgstr "Postavka"
+
+msgctxt "field:sale.reporting.category,category:"
+msgid "Category"
+msgstr ""
+
+msgctxt "field:sale.reporting.category,time_series:"
+msgid "Time Series"
+msgstr ""
+
+msgctxt "field:sale.reporting.category.time_series,category:"
+msgid "Category"
+msgstr ""
+
+#, fuzzy
+msgctxt "field:sale.reporting.category.time_series,date:"
+msgid "Date"
+msgstr "Datum:"
+
+msgctxt "field:sale.reporting.category.tree,children:"
+msgid "Children"
+msgstr ""
+
+#, fuzzy
+msgctxt "field:sale.reporting.category.tree,currency_digits:"
+msgid "Currency Digits"
+msgstr "Decimalke"
+
+#, fuzzy
+msgctxt "field:sale.reporting.category.tree,name:"
+msgid "Name"
+msgstr "Ime"
+
+msgctxt "field:sale.reporting.category.tree,parent:"
+msgid "Parent"
+msgstr ""
+
+msgctxt "field:sale.reporting.category.tree,revenue:"
+msgid "Revenue"
+msgstr ""
+
+#, fuzzy
+msgctxt "field:sale.reporting.context,company:"
+msgid "Company"
+msgstr "Družba"
+
+msgctxt "field:sale.reporting.context,from_date:"
+msgid "From Date"
+msgstr ""
+
+msgctxt "field:sale.reporting.context,period:"
+msgid "Period"
+msgstr ""
+
+msgctxt "field:sale.reporting.context,to_date:"
+msgid "To Date"
+msgstr ""
+
+#, fuzzy
+msgctxt "field:sale.reporting.context,warehouse:"
+msgid "Warehouse"
+msgstr "Skladišče"
+
+msgctxt "field:sale.reporting.country,country:"
+msgid "Country"
+msgstr ""
+
+msgctxt "field:sale.reporting.country,time_series:"
+msgid "Time Series"
+msgstr ""
+
+msgctxt "field:sale.reporting.country.subdivision,country:"
+msgid "Country"
+msgstr ""
+
+msgctxt "field:sale.reporting.country.subdivision,subdivision:"
+msgid "Subdivision"
+msgstr ""
+
+msgctxt "field:sale.reporting.country.subdivision,time_series:"
+msgid "Time Series"
+msgstr ""
+
+msgctxt "field:sale.reporting.country.subdivision.time_series,country:"
+msgid "Country"
+msgstr ""
+
+#, fuzzy
+msgctxt "field:sale.reporting.country.subdivision.time_series,date:"
+msgid "Date"
+msgstr "Datum:"
+
+msgctxt "field:sale.reporting.country.subdivision.time_series,subdivision:"
+msgid "Subdivision"
+msgstr ""
+
+msgctxt "field:sale.reporting.country.time_series,country:"
+msgid "Country"
+msgstr ""
+
+#, fuzzy
+msgctxt "field:sale.reporting.country.time_series,date:"
+msgid "Date"
+msgstr "Datum:"
+
+#, fuzzy
+msgctxt "field:sale.reporting.customer,customer:"
+msgid "Customer"
+msgstr "Kupci"
+
+msgctxt "field:sale.reporting.customer,time_series:"
+msgid "Time Series"
+msgstr ""
+
+#, fuzzy
+msgctxt "field:sale.reporting.customer.time_series,customer:"
+msgid "Customer"
+msgstr "Kupci"
+
+#, fuzzy
+msgctxt "field:sale.reporting.customer.time_series,date:"
+msgid "Date"
+msgstr "Datum:"
+
+#, fuzzy
+msgctxt "field:sale.reporting.product,product:"
+msgid "Product"
+msgstr "Izdelek"
+
+msgctxt "field:sale.reporting.product,time_series:"
+msgid "Time Series"
+msgstr ""
+
+#, fuzzy
+msgctxt "field:sale.reporting.product.time_series,date:"
+msgid "Date"
+msgstr "Datum:"
+
+#, fuzzy
+msgctxt "field:sale.reporting.product.time_series,product:"
+msgid "Product"
+msgstr "Izdelek"
+
+msgctxt "field:sale.reporting.region,children:"
+msgid "Children"
+msgstr ""
+
+msgctxt "field:sale.reporting.region,parent:"
+msgid "Parent"
+msgstr ""
+
+msgctxt "field:sale.reporting.region,region:"
+msgid "Region"
+msgstr ""
+
+msgctxt "field:sale.sale,comment:"
+msgid "Comment"
+msgstr "Opomba"
+
+msgctxt "field:sale.sale,company:"
+msgid "Company"
+msgstr "Družba"
+
+#, fuzzy
+msgctxt "field:sale.sale,confirmed_by:"
+msgid "Confirmed By"
+msgstr "Confirmed"
+
+msgctxt "field:sale.sale,contact:"
+msgid "Contact"
+msgstr ""
+
+msgctxt "field:sale.sale,currency:"
+msgid "Currency"
+msgstr "Valuta"
+
+msgctxt "field:sale.sale,currency_digits:"
+msgid "Currency Digits"
+msgstr "Decimalke"
+
+msgctxt "field:sale.sale,description:"
+msgid "Description"
+msgstr "Opis"
+
+msgctxt "field:sale.sale,invoice_address:"
+msgid "Invoice Address"
+msgstr "Naslov plačnika"
+
+msgctxt "field:sale.sale,invoice_method:"
+msgid "Invoice Method"
+msgstr "Način obračuna"
+
+#, fuzzy
+msgctxt "field:sale.sale,invoice_party:"
+msgid "Invoice Party"
+msgstr "Stanje računa"
+
+msgctxt "field:sale.sale,invoice_state:"
+msgid "Invoice State"
+msgstr "Stanje računa"
+
+msgctxt "field:sale.sale,invoices:"
+msgid "Invoices"
+msgstr "Računi"
+
+msgctxt "field:sale.sale,invoices_ignored:"
+msgid "Ignored Invoices"
+msgstr "Prezrti računi"
+
+msgctxt "field:sale.sale,invoices_recreated:"
+msgid "Recreated Invoices"
+msgstr "Ponovno izdelani računi"
+
+msgctxt "field:sale.sale,lines:"
+msgid "Lines"
+msgstr "Postavke"
+
+msgctxt "field:sale.sale,moves:"
+msgid "Moves"
+msgstr "Promet"
+
+msgctxt "field:sale.sale,number:"
+msgid "Number"
+msgstr "Številka"
+
+msgctxt "field:sale.sale,origin:"
+msgid "Origin"
+msgstr "Poreklo"
+
+msgctxt "field:sale.sale,party:"
+msgid "Party"
+msgstr "Partner"
+
+msgctxt "field:sale.sale,party_lang:"
+msgid "Party Language"
+msgstr "Jezik partnerja"
+
+msgctxt "field:sale.sale,payment_term:"
+msgid "Payment Term"
+msgstr "Plačilni rok"
+
+#, fuzzy
+msgctxt "field:sale.sale,quoted_by:"
+msgid "Quoted By"
+msgstr "Quote"
+
+msgctxt "field:sale.sale,reference:"
+msgid "Reference"
+msgstr "Sklic"
+
+msgctxt "field:sale.sale,sale_date:"
+msgid "Sale Date"
+msgstr "Datum prodaje"
+
+msgctxt "field:sale.sale,shipment_address:"
+msgid "Shipment Address"
+msgstr "Naslov prejemnika"
+
+msgctxt "field:sale.sale,shipment_method:"
+msgid "Shipment Method"
+msgstr "Način odpreme"
+
+msgctxt "field:sale.sale,shipment_party:"
+msgid "Shipment Party"
+msgstr "Pošiljatelj"
+
+msgctxt "field:sale.sale,shipment_returns:"
+msgid "Shipment Returns"
+msgstr "Vrnjene odpremnice"
+
+msgctxt "field:sale.sale,shipment_state:"
+msgid "Shipment State"
+msgstr "Stanje pošiljke"
+
+msgctxt "field:sale.sale,shipments:"
+msgid "Shipments"
+msgstr "Pošiljke"
+
+#, fuzzy
+msgctxt "field:sale.sale,shipping_date:"
+msgid "Shipping Date"
+msgstr "Datum odpreme"
+
+msgctxt "field:sale.sale,state:"
+msgid "State"
+msgstr "Stanje"
+
+msgctxt "field:sale.sale,tax_amount:"
+msgid "Tax"
+msgstr "Davek"
+
+msgctxt "field:sale.sale,tax_amount_cache:"
+msgid "Tax Cache"
+msgstr "Davek predpomnjen"
+
+msgctxt "field:sale.sale,total_amount:"
+msgid "Total"
+msgstr "Skupaj"
+
+#, fuzzy
+msgctxt "field:sale.sale,total_amount_cache:"
+msgid "Total Cache"
+msgstr "Davek predpomnjen"
+
+msgctxt "field:sale.sale,untaxed_amount:"
+msgid "Untaxed"
+msgstr "Neobdavčeno"
+
+msgctxt "field:sale.sale,untaxed_amount_cache:"
+msgid "Untaxed Cache"
+msgstr "Neobdavčeno predpomnjeno"
+
+msgctxt "field:sale.sale,warehouse:"
+msgid "Warehouse"
+msgstr "Skladišče"
+
+msgctxt "field:sale.sale-ignored-account.invoice,invoice:"
+msgid "Invoice"
+msgstr "Račun"
+
+msgctxt "field:sale.sale-ignored-account.invoice,sale:"
+msgid "Sale"
+msgstr "Prodajni nalog"
+
+msgctxt "field:sale.sale-recreated-account.invoice,invoice:"
+msgid "Invoice"
+msgstr "Račun"
+
+msgctxt "field:sale.sale-recreated-account.invoice,sale:"
+msgid "Sale"
+msgstr "Prodajni nalog"
+
+msgctxt "field:stock.move,sale:"
+msgid "Sale"
+msgstr "Prodajni nalog"
+
+msgctxt "field:stock.move,sale_exception_state:"
+msgid "Exception State"
+msgstr "Pridržano"
+
+msgctxt "help:product.configuration,default_lead_time:"
+msgid ""
+"The time from confirming the sales order to sending the products.\n"
+"Used for products without a lead time."
+msgstr ""
+
+msgctxt "help:product.product,lead_time:"
+msgid ""
+"The time from confirming the sales order to sending the products.\n"
+"If empty the default lead time from the configuration is used."
+msgstr ""
+
+msgctxt "help:product.template,lead_time:"
+msgid ""
+"The time from confirming the sales order to sending the products.\n"
+"If empty the default lead time from the configuration is used."
+msgstr ""
+
+msgctxt "help:sale.configuration,sale_process_after:"
+msgid ""
+"The grace period during which confirmed sale can still be reset to draft.\n"
+"Applied if a worker queue is activated."
+msgstr ""
+
+msgctxt "help:sale.handle.invoice.exception.ask,recreate_invoices:"
+msgid ""
+"The selected invoices will be recreated. The other ones will be ignored."
+msgstr "Izbrani računi bodo ponovno izdelani, ostali bodo prezrti."
+
+msgctxt "help:sale.sale,shipping_date:"
+msgid "When the shipping of goods should start."
+msgstr ""
+
+#, fuzzy
+msgctxt "model:ir.action,name:act_invoice_form"
+msgid "Invoices"
+msgstr "Invoices"
+
+#, fuzzy
+msgctxt "model:ir.action,name:act_open_customer"
+msgid "Parties associated to Sales"
+msgstr "Parties associated to Sales"
+
+#, fuzzy
+msgctxt "model:ir.action,name:act_product"
+msgid "Products"
+msgstr "Izdelek"
+
+msgctxt "model:ir.action,name:act_reporting_category"
+msgid "Sales per Category"
+msgstr "Sales per Category"
+
+msgctxt "model:ir.action,name:act_reporting_category_time_series"
+msgid "Sales per Category"
+msgstr "Sales per Category"
+
+msgctxt "model:ir.action,name:act_reporting_category_tree"
+msgid "Sales per Category"
+msgstr "Sales per Category"
+
+msgctxt "model:ir.action,name:act_reporting_country_subdivision_time_series"
+msgid "Sales per Subdivision"
+msgstr "Sales per Subdivision"
+
+msgctxt "model:ir.action,name:act_reporting_country_time_series"
+msgid "Sales per Country"
+msgstr "Sales per Country"
+
+msgctxt "model:ir.action,name:act_reporting_customer"
+msgid "Sales per Customer"
+msgstr "Sales per Customer"
+
+msgctxt "model:ir.action,name:act_reporting_customer_time_series"
+msgid "Sales per Customer"
+msgstr "Sales per Customer"
+
+msgctxt "model:ir.action,name:act_reporting_product"
+msgid "Sales per Product"
+msgstr "Sales per Product"
+
+msgctxt "model:ir.action,name:act_reporting_product_time_series"
+msgid "Sales per Product"
+msgstr "Sales per Product"
+
+msgctxt "model:ir.action,name:act_reporting_region"
+msgid "Sales per Region"
+msgstr "Sales per Region"
+
+#, fuzzy
+msgctxt "model:ir.action,name:act_return_form"
+msgid "Returns"
+msgstr "Returns"
+
+#, fuzzy
+msgctxt "model:ir.action,name:act_sale_configuration_form"
+msgid "Configuration"
+msgstr "Configuration"
+
+#, fuzzy
+msgctxt "model:ir.action,name:act_sale_form"
+msgid "Sales"
+msgstr "Sales"
+
+#, fuzzy
+msgctxt "model:ir.action,name:act_sale_form2"
+msgid "Sales"
+msgstr "Sales"
+
+#, fuzzy
+msgctxt "model:ir.action,name:act_sale_invoice_relate"
+msgid "Sales"
+msgstr "Sales"
+
+#, fuzzy
+msgctxt "model:ir.action,name:act_sale_move_relate"
+msgid "Moves"
+msgstr "Promet"
+
+msgctxt "model:ir.action,name:act_sale_shipment_returns_relate"
+msgid "Sales"
+msgstr "Sales"
+
+#, fuzzy
+msgctxt "model:ir.action,name:act_sale_shipments_relate"
+msgid "Sales"
+msgstr "Sales"
+
+#, fuzzy
+msgctxt "model:ir.action,name:act_shipment_form"
+msgid "Shipments"
+msgstr "Shipments"
+
+#, fuzzy
+msgctxt "model:ir.action,name:report_sale"
+msgid "Sale"
+msgstr "Sale"
+
+#, fuzzy
+msgctxt "model:ir.action,name:wizard_invoice_handle_exception"
+msgid "Handle Invoice Exception"
+msgstr "Handle Invoice Exception"
+
+msgctxt "model:ir.action,name:wizard_modify_header"
+msgid "Modify Header"
+msgstr "Modify Header"
+
+msgctxt "model:ir.action,name:wizard_reporting_region_open"
+msgid "Open Region"
+msgstr "Open Region"
+
+#, fuzzy
+msgctxt "model:ir.action,name:wizard_return_sale"
+msgid "Return Sale"
+msgstr "Return Sale"
+
+#, fuzzy
+msgctxt "model:ir.action,name:wizard_shipment_handle_exception"
+msgid "Handle Shipment Exception"
+msgstr "Handle Shipment Exception"
+
+#, fuzzy
+msgctxt "model:ir.action.act_window.domain,name:act_sale_form_domain_all"
+msgid "All"
+msgstr "All"
+
+#, fuzzy
+msgctxt ""
+"model:ir.action.act_window.domain,name:act_sale_form_domain_confirmed"
+msgid "Confirmed"
+msgstr "Confirmed"
+
+#, fuzzy
+msgctxt "model:ir.action.act_window.domain,name:act_sale_form_domain_draft"
+msgid "Draft"
+msgstr "Draft"
+
+#, fuzzy
+msgctxt ""
+"model:ir.action.act_window.domain,name:act_sale_form_domain_exception"
+msgid "Exception"
+msgstr "Pridržano"
+
+#, fuzzy
+msgctxt ""
+"model:ir.action.act_window.domain,name:act_sale_form_domain_processing"
+msgid "Processing"
+msgstr "Processing"
+
+#, fuzzy
+msgctxt ""
+"model:ir.action.act_window.domain,name:act_sale_form_domain_quotation"
+msgid "Quotation"
+msgstr "Quotation"
+
+msgctxt "model:ir.message,text:msg_erase_party_pending_sale"
+msgid ""
+"You cannot erase party \"%(party)s\" while they have pending sales with "
+"company \"%(company)s\"."
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_sale_customer_location_required"
+msgid ""
+"To process sale \"%(sale)s\" you must set a customer location on party "
+"\"%(party)s\"."
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_sale_delete_cancel"
+msgid "To delete sale \"%(sale)s\" you must cancel it."
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_sale_invalid_method"
+msgid ""
+"You cannot use together invoice \"%(invoice_method)s\" and shipment "
+"\"%(shipment_method)s\" on sale \"%(sale)s\"."
+msgstr ""
+
+msgctxt ""
+"model:ir.message,text:msg_sale_invoice_address_required_for_quotation"
+msgid "To get a quote for sale \"%(sale)s\" you must enter an invoice address."
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_sale_invoice_reset_draft"
+msgid ""
+"You cannot reset invoice \"%(invoice)s\" to draft because it was generated "
+"by a sale."
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_sale_line_delete_cancel_draft"
+msgid ""
+"To delete line \"%(line)s\" you must cancel or reset to draft sale "
+"\"%(sale)s\"."
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_sale_missing_account_revenue"
+msgid "To invoice sale \"%(sale)s\" you must configure a default account revenue."
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_sale_modify_header_draft"
+msgid "To modify the header of sale \"%(sale)s\", it must be in \"draft\" state."
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_sale_move_reset_draft"
+msgid ""
+"You cannot reset move \"%(move)s\" to draft because it was generated by a "
+"sale."
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_sale_product_missing_account_revenue"
+msgid ""
+"To invoice sale \"%(sale)s\" you must define an account revenue for product "
+"\"%(product)s\"."
+msgstr ""
+
+#, fuzzy
+msgctxt "model:ir.message,text:msg_sale_reporting_company"
+msgid "Company"
+msgstr "Družba"
+
+#, fuzzy
+msgctxt "model:ir.message,text:msg_sale_reporting_currency"
+msgid "Currency"
+msgstr "Valuta"
+
+#, fuzzy
+msgctxt "model:ir.message,text:msg_sale_reporting_currency_digits"
+msgid "Currency Digits"
+msgstr "Decimalke"
+
+#, fuzzy
+msgctxt "model:ir.message,text:msg_sale_reporting_number"
+msgid "#"
+msgstr "#"
+
+msgctxt "model:ir.message,text:msg_sale_reporting_number_help"
+msgid "Number of sales"
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_sale_reporting_revenue"
+msgid "Revenue"
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_sale_reporting_revenue_trend"
+msgid "Revenue Trend"
+msgstr ""
+
+msgctxt ""
+"model:ir.message,text:msg_sale_shipment_address_required_for_quotation"
+msgid "To get a quote for sale \"%(sale)s\" you must enter a shipment address."
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_sale_warehouse_required_for_quotation"
+msgid "To get a quote for sale \"%(sale)s\" you must enter a warehouse."
+msgstr ""
+
+msgctxt "model:ir.model.button,string:sale_cancel_button"
+msgid "Cancel"
+msgstr "Cancel"
+
+msgctxt "model:ir.model.button,string:sale_confirm_button"
+msgid "Confirm"
+msgstr "Confirm"
+
+msgctxt "model:ir.model.button,string:sale_draft_button"
+msgid "Draft"
+msgstr "Draft"
+
+msgctxt "model:ir.model.button,string:sale_handle_invoice_exception_button"
+msgid "Handle Invoice Exception"
+msgstr "Handle Invoice Exception"
+
+msgctxt "model:ir.model.button,string:sale_handle_shipment_exception_button"
+msgid "Handle Shipment Exception"
+msgstr "Handle Shipment Exception"
+
+msgctxt "model:ir.model.button,string:sale_modify_header_button"
+msgid "Modify Header"
+msgstr "Modify Header"
+
+msgctxt "model:ir.model.button,string:sale_process_button"
+msgid "Process"
+msgstr "Process"
+
+msgctxt "model:ir.model.button,string:sale_quote_button"
+msgid "Quote"
+msgstr "Quote"
+
+msgctxt "model:ir.rule.group,name:rule_group_reporting_category_companies"
+msgid "User in companies"
+msgstr ""
+
+msgctxt ""
+"model:ir.rule.group,name:rule_group_reporting_category_time_series_companies"
+msgid "User in companies"
+msgstr ""
+
+msgctxt ""
+"model:ir.rule.group,name:rule_group_reporting_country_subdivision_time_series_companies"
+msgid "User in companies"
+msgstr ""
+
+msgctxt ""
+"model:ir.rule.group,name:rule_group_reporting_country_time_series_companies"
+msgid "User in companies"
+msgstr ""
+
+msgctxt "model:ir.rule.group,name:rule_group_reporting_customer_companies"
+msgid "User in companies"
+msgstr ""
+
+msgctxt ""
+"model:ir.rule.group,name:rule_group_reporting_customer_time_series_companies"
+msgid "User in companies"
+msgstr ""
+
+msgctxt "model:ir.rule.group,name:rule_group_reporting_product_companies"
+msgid "User in companies"
+msgstr ""
+
+msgctxt ""
+"model:ir.rule.group,name:rule_group_reporting_product_time_series_companies"
+msgid "User in companies"
+msgstr ""
+
+msgctxt "model:ir.rule.group,name:rule_group_reporting_region_companies"
+msgid "User in companies"
+msgstr ""
+
+msgctxt "model:ir.rule.group,name:rule_group_sale_companies"
+msgid "User in companies"
+msgstr ""
+
+#, fuzzy
+msgctxt "model:ir.sequence,name:sequence_sale"
+msgid "Sale"
+msgstr "Sale"
+
+#, fuzzy
+msgctxt "model:ir.sequence.type,name:sequence_type_sale"
+msgid "Sale"
+msgstr "Sale"
+
+#, fuzzy
+msgctxt "model:ir.ui.menu,name:menu_configuration"
+msgid "Configuration"
+msgstr "Configuration"
+
+#, fuzzy
+msgctxt "model:ir.ui.menu,name:menu_customer"
+msgid "Associated to Sales"
+msgstr "Parties associated to Sales"
+
+#, fuzzy
+msgctxt "model:ir.ui.menu,name:menu_product"
+msgid "Products"
+msgstr "Izdelek"
+
+msgctxt "model:ir.ui.menu,name:menu_reporting"
+msgid "Reporting"
+msgstr "Reporting"
+
+msgctxt "model:ir.ui.menu,name:menu_reporting_sale"
+msgid "Sales"
+msgstr "Sales"
+
+#, fuzzy
+msgctxt "model:ir.ui.menu,name:menu_sale"
+msgid "Sales"
+msgstr "Sales"
+
+#, fuzzy
+msgctxt "model:ir.ui.menu,name:menu_sale_configuration"
+msgid "Configuration"
+msgstr "Configuration"
+
+#, fuzzy
+msgctxt "model:ir.ui.menu,name:menu_sale_form"
+msgid "Sales"
+msgstr "Sales"
+
+msgctxt "model:product.configuration.default_lead_time,name:"
+msgid "Product Default Lead Time"
+msgstr ""
+
+msgctxt "model:product.sale.context,name:"
+msgid "Product Sale Context"
+msgstr ""
+
+#, fuzzy
+msgctxt "model:res.group,name:group_sale"
+msgid "Sales"
+msgstr "Sales"
+
+#, fuzzy
+msgctxt "model:res.group,name:group_sale_admin"
+msgid "Sales Administrator"
+msgstr "Sales Administrator"
+
+msgctxt "model:sale.configuration,name:"
+msgid "Sale Configuration"
+msgstr "Prodajna konfiguracija"
+
+msgctxt "model:sale.configuration.sale_method,name:"
+msgid "Sale Configuration Sale Method"
+msgstr "Konfiguracija načina prodaje"
+
+msgctxt "model:sale.configuration.sequence,name:"
+msgid "Sale Configuration Sequence"
+msgstr "Konfiguracija štetja prodaje"
+
+msgctxt "model:sale.handle.invoice.exception.ask,name:"
+msgid "Handle Invoice Exception"
+msgstr "Obravnava pridržanih računov"
+
+msgctxt "model:sale.handle.shipment.exception.ask,name:"
+msgid "Handle Shipment Exception"
+msgstr "Obravnava pridržanih odpremnic"
+
+msgctxt "model:sale.line,name:"
+msgid "Sale Line"
+msgstr "Prodajna postavka"
+
+msgctxt "model:sale.line-account.tax,name:"
+msgid "Sale Line - Tax"
+msgstr "Prodajna postavka - Davek"
+
+msgctxt "model:sale.line-ignored-stock.move,name:"
+msgid "Sale Line - Ignored Move"
+msgstr "Prodajna postavka - Prezrt promet"
+
+msgctxt "model:sale.line-recreated-stock.move,name:"
+msgid "Sale Line - Recreated Move"
+msgstr "Prodajna postavka - Ponovno izdelan promet"
+
+msgctxt "model:sale.reporting.category,name:"
+msgid "Sale Reporting per Category"
+msgstr ""
+
+msgctxt "model:sale.reporting.category.time_series,name:"
+msgid "Sale Reporting per Category"
+msgstr ""
+
+msgctxt "model:sale.reporting.category.tree,name:"
+msgid "Sale Reporting per Category"
+msgstr ""
+
+msgctxt "model:sale.reporting.context,name:"
+msgid "Sale Reporting Context"
+msgstr ""
+
+msgctxt "model:sale.reporting.country,name:"
+msgid "Sale Reporting per Country"
+msgstr ""
+
+msgctxt "model:sale.reporting.country.subdivision,name:"
+msgid "Sale Reporting per Subdivision"
+msgstr ""
+
+msgctxt "model:sale.reporting.country.subdivision.time_series,name:"
+msgid "Sale Reporting per Subdivision"
+msgstr ""
+
+msgctxt "model:sale.reporting.country.time_series,name:"
+msgid "Sale Reporting per Country"
+msgstr ""
+
+msgctxt "model:sale.reporting.customer,name:"
+msgid "Sale Reporting per Customer"
+msgstr ""
+
+msgctxt "model:sale.reporting.customer.time_series,name:"
+msgid "Sale Reporting per Customer"
+msgstr ""
+
+msgctxt "model:sale.reporting.product,name:"
+msgid "Sale Reporting per Product"
+msgstr ""
+
+msgctxt "model:sale.reporting.product.time_series,name:"
+msgid "Sale Reporting per Product"
+msgstr ""
+
+msgctxt "model:sale.reporting.region,name:"
+msgid "Sale Reporting per Region"
+msgstr ""
+
+msgctxt "model:sale.return_sale.start,name:"
+msgid "Return Sale"
+msgstr "Izdelava zavrnjene odpremnice"
+
+msgctxt "model:sale.sale,name:"
+msgid "Sale"
+msgstr "Prodajni nalog"
+
+msgctxt "model:sale.sale-ignored-account.invoice,name:"
+msgid "Sale - Ignored Invoice"
+msgstr "Prodajni nalog - Prezrt račun"
+
+msgctxt "model:sale.sale-recreated-account.invoice,name:"
+msgid "Sale - Recreated Invoice"
+msgstr "Prodajni nalog - Ponovno izdelan račun"
+
+msgctxt "report:sale.sale:"
+msgid ":"
+msgstr ":"
+
+msgctxt "report:sale.sale:"
+msgid "Amount"
+msgstr "Znesek"
+
+msgctxt "report:sale.sale:"
+msgid "Date:"
+msgstr "Datum:"
+
+msgctxt "report:sale.sale:"
+msgid "Description"
+msgstr "Opis"
+
+msgctxt "report:sale.sale:"
+msgid "Description:"
+msgstr "Opis:"
+
+msgctxt "report:sale.sale:"
+msgid "Draft Sale Order"
+msgstr "Osnutek prodajnega naloga"
+
+msgctxt "report:sale.sale:"
+msgid "Quantity"
+msgstr "Količina"
+
+msgctxt "report:sale.sale:"
+msgid "Quotation N°:"
+msgstr "Ponudba št.:"
+
+msgctxt "report:sale.sale:"
+msgid "Reference:"
+msgstr "Sklic:"
+
+msgctxt "report:sale.sale:"
+msgid "Sale Order N°:"
+msgstr "Prodajni nalog št.:"
+
+msgctxt "report:sale.sale:"
+msgid "Taxes"
+msgstr "Davek"
+
+msgctxt "report:sale.sale:"
+msgid "Taxes:"
+msgstr "Davek:"
+
+msgctxt "report:sale.sale:"
+msgid "Total (excl. taxes):"
+msgstr "Skupaj (brez davka):"
+
+msgctxt "report:sale.sale:"
+msgid "Total:"
+msgstr "Skupaj:"
+
+msgctxt "report:sale.sale:"
+msgid "Unit Price"
+msgstr "Cena"
+
+msgctxt "selection:account.invoice,sale_exception_state:"
+msgid "Ignored"
+msgstr "Prezrto"
+
+msgctxt "selection:account.invoice,sale_exception_state:"
+msgid "Recreated"
+msgstr "Ponovno izdelano"
+
+msgctxt "selection:sale.line,type:"
+msgid "Comment"
+msgstr "Opomba"
+
+msgctxt "selection:sale.line,type:"
+msgid "Line"
+msgstr "Postavka"
+
+msgctxt "selection:sale.line,type:"
+msgid "Subtotal"
+msgstr "Vmesna vsota"
+
+msgctxt "selection:sale.line,type:"
+msgid "Title"
+msgstr "Napis"
+
+msgctxt "selection:sale.reporting.context,period:"
+msgid "Day"
+msgstr ""
+
+msgctxt "selection:sale.reporting.context,period:"
+msgid "Month"
+msgstr ""
+
+msgctxt "selection:sale.reporting.context,period:"
+msgid "Year"
+msgstr ""
+
+msgctxt "selection:sale.sale,invoice_method:"
+msgid "Manual"
+msgstr "Ročno"
+
+msgctxt "selection:sale.sale,invoice_method:"
+msgid "On Order Processed"
+msgstr "Po obdelavi naloga"
+
+msgctxt "selection:sale.sale,invoice_method:"
+msgid "On Shipment Sent"
+msgstr "Po izvršeni odpremi"
+
+msgctxt "selection:sale.sale,invoice_state:"
+msgid "Exception"
+msgstr "Pridržano"
+
+msgctxt "selection:sale.sale,invoice_state:"
+msgid "None"
+msgstr "Brez"
+
+msgctxt "selection:sale.sale,invoice_state:"
+msgid "Paid"
+msgstr "Plačano"
+
+msgctxt "selection:sale.sale,invoice_state:"
+msgid "Waiting"
+msgstr "Čakajoče"
+
+msgctxt "selection:sale.sale,shipment_method:"
+msgid "Manual"
+msgstr "Ročno"
+
+msgctxt "selection:sale.sale,shipment_method:"
+msgid "On Invoice Paid"
+msgstr "Po plačilu računa"
+
+msgctxt "selection:sale.sale,shipment_method:"
+msgid "On Order Processed"
+msgstr "Po obdelavi naloga"
+
+msgctxt "selection:sale.sale,shipment_state:"
+msgid "Exception"
+msgstr "Pridržano"
+
+msgctxt "selection:sale.sale,shipment_state:"
+msgid "None"
+msgstr "Brez"
+
+msgctxt "selection:sale.sale,shipment_state:"
+msgid "Sent"
+msgstr "Odpremljeno"
+
+msgctxt "selection:sale.sale,shipment_state:"
+msgid "Waiting"
+msgstr "Čakajoče"
+
+#, fuzzy
+msgctxt "selection:sale.sale,state:"
+msgid "Cancelled"
+msgstr "Preklicano"
+
+msgctxt "selection:sale.sale,state:"
+msgid "Confirmed"
+msgstr "Potrjeno"
+
+msgctxt "selection:sale.sale,state:"
+msgid "Done"
+msgstr "Zaključeno"
+
+msgctxt "selection:sale.sale,state:"
+msgid "Draft"
+msgstr "V pripravi"
+
+msgctxt "selection:sale.sale,state:"
+msgid "Processing"
+msgstr "Obdelava"
+
+msgctxt "selection:sale.sale,state:"
+msgid "Quotation"
+msgstr "Ponudba"
+
+msgctxt "selection:stock.move,sale_exception_state:"
+msgid "Ignored"
+msgstr "Prezrto"
+
+msgctxt "selection:stock.move,sale_exception_state:"
+msgid "Recreated"
+msgstr "Ponovno izdelano"
+
+msgctxt "view:party.party:"
+msgid "Sale"
+msgstr "Prodajni nalog"
+
+msgctxt "view:product.template:"
+msgid "Customers"
+msgstr "Kupci"
+
+#, fuzzy
+msgctxt "view:sale.handle.invoice.exception.ask:"
+msgid "Choose invoices to recreate:"
+msgstr "Izbor računov za ponovno izdelavo"
+
+#, fuzzy
+msgctxt "view:sale.handle.shipment.exception.ask:"
+msgid "Choose move to recreate:"
+msgstr "Izbor prometa za ponovno izdelavo"
+
+msgctxt "view:sale.line:"
+msgid "General"
+msgstr "Splošno"
+
+msgctxt "view:sale.line:"
+msgid "Notes"
+msgstr "Opombe"
+
+msgctxt "view:sale.line:"
+msgid "Taxes"
+msgstr "Davki"
+
+#, fuzzy
+msgctxt "view:sale.return_sale.start:"
+msgid "Are you sure to return these/this sale(s)?"
+msgstr "Ali res želite vrniti to/te prodajo/e?"
+
+msgctxt "view:sale.sale:"
+msgid "Other Info"
+msgstr "Drugo"
+
+msgctxt "view:sale.sale:"
+msgid "Sale"
+msgstr "Prodaja"
+
+msgctxt "wizard_button:sale.handle.invoice.exception,ask,end:"
+msgid "Cancel"
+msgstr "Prekliči"
+
+msgctxt "wizard_button:sale.handle.invoice.exception,ask,handle:"
+msgid "OK"
+msgstr "V redu"
+
+msgctxt "wizard_button:sale.handle.shipment.exception,ask,end:"
+msgid "Cancel"
+msgstr "Prekliči"
+
+msgctxt "wizard_button:sale.handle.shipment.exception,ask,handle:"
+msgid "OK"
+msgstr "V redu"
+
+#, fuzzy
+msgctxt "wizard_button:sale.modify_header,start,end:"
+msgid "Cancel"
+msgstr "Prekliči"
+
+msgctxt "wizard_button:sale.modify_header,start,modify:"
+msgid "Modify"
+msgstr ""
+
+msgctxt "wizard_button:sale.return_sale,start,end:"
+msgid "Cancel"
+msgstr "Prekliči"
+
+msgctxt "wizard_button:sale.return_sale,start,return_:"
+msgid "Return"
+msgstr "Vrni"
diff --git a/modules/sale/locale/tr.po b/modules/sale/locale/tr.po
new file mode 100644
index 0000000000..3f4fa6c49b
--- /dev/null
+++ b/modules/sale/locale/tr.po
@@ -0,0 +1,1382 @@
+#
+msgid ""
+msgstr "Content-Type: text/plain; charset=utf-8\n"
+
+msgctxt "field:account.invoice,sale_exception_state:"
+msgid "Exception State"
+msgstr ""
+
+#, fuzzy
+msgctxt "field:account.invoice,sales:"
+msgid "Sales"
+msgstr "Sales"
+
+msgctxt "field:product.configuration,default_lead_time:"
+msgid "Default Lead Time"
+msgstr ""
+
+msgctxt "field:product.configuration.default_lead_time,company:"
+msgid "Company"
+msgstr ""
+
+msgctxt "field:product.configuration.default_lead_time,default_lead_time:"
+msgid "Default Lead Time"
+msgstr ""
+
+msgctxt "field:product.product,lead_time:"
+msgid "Lead Time"
+msgstr ""
+
+msgctxt "field:product.product,salable:"
+msgid "Salable"
+msgstr ""
+
+msgctxt "field:product.product,sale_price_uom:"
+msgid "Sale Price"
+msgstr ""
+
+msgctxt "field:product.product,sale_uom:"
+msgid "Sale UOM"
+msgstr ""
+
+msgctxt "field:product.sale.context,company:"
+msgid "Company"
+msgstr ""
+
+msgctxt "field:product.sale.context,currency:"
+msgid "Currency"
+msgstr ""
+
+#, fuzzy
+msgctxt "field:product.sale.context,customer:"
+msgid "Customer"
+msgstr "Sales per Customer"
+
+msgctxt "field:product.sale.context,locations:"
+msgid "Warehouses"
+msgstr ""
+
+msgctxt "field:product.sale.context,quantity:"
+msgid "Quantity"
+msgstr ""
+
+#, fuzzy
+msgctxt "field:product.sale.context,sale_date:"
+msgid "Sale Date"
+msgstr "Sales"
+
+msgctxt "field:product.sale.context,stock_date_end:"
+msgid "Stock End Date"
+msgstr ""
+
+msgctxt "field:product.template,lead_time:"
+msgid "Lead Time"
+msgstr ""
+
+msgctxt "field:product.template,salable:"
+msgid "Salable"
+msgstr ""
+
+msgctxt "field:product.template,sale_uom:"
+msgid "Sale UOM"
+msgstr ""
+
+msgctxt "field:sale.configuration,sale_invoice_method:"
+msgid "Sale Invoice Method"
+msgstr ""
+
+msgctxt "field:sale.configuration,sale_process_after:"
+msgid "Process Sale after"
+msgstr ""
+
+msgctxt "field:sale.configuration,sale_sequence:"
+msgid "Sale Sequence"
+msgstr ""
+
+msgctxt "field:sale.configuration,sale_shipment_method:"
+msgid "Sale Shipment Method"
+msgstr ""
+
+msgctxt "field:sale.configuration.sale_method,sale_invoice_method:"
+msgid "Sale Invoice Method"
+msgstr ""
+
+msgctxt "field:sale.configuration.sale_method,sale_shipment_method:"
+msgid "Sale Shipment Method"
+msgstr ""
+
+msgctxt "field:sale.configuration.sequence,company:"
+msgid "Company"
+msgstr ""
+
+msgctxt "field:sale.configuration.sequence,sale_sequence:"
+msgid "Sale Sequence"
+msgstr ""
+
+msgctxt "field:sale.handle.invoice.exception.ask,domain_invoices:"
+msgid "Domain Invoices"
+msgstr ""
+
+msgctxt "field:sale.handle.invoice.exception.ask,recreate_invoices:"
+msgid "Recreate Invoices"
+msgstr ""
+
+msgctxt "field:sale.handle.shipment.exception.ask,domain_moves:"
+msgid "Domain Moves"
+msgstr ""
+
+msgctxt "field:sale.handle.shipment.exception.ask,recreate_moves:"
+msgid "Recreate Moves"
+msgstr ""
+
+msgctxt "field:sale.line,actual_quantity:"
+msgid "Actual Quantity"
+msgstr ""
+
+msgctxt "field:sale.line,amount:"
+msgid "Amount"
+msgstr ""
+
+msgctxt "field:sale.line,company:"
+msgid "Company"
+msgstr ""
+
+msgctxt "field:sale.line,currency:"
+msgid "Currency"
+msgstr ""
+
+msgctxt "field:sale.line,description:"
+msgid "Description"
+msgstr ""
+
+msgctxt "field:sale.line,from_location:"
+msgid "From Location"
+msgstr ""
+
+msgctxt "field:sale.line,invoice_lines:"
+msgid "Invoice Lines"
+msgstr ""
+
+msgctxt "field:sale.line,move_done:"
+msgid "Moves Done"
+msgstr ""
+
+msgctxt "field:sale.line,move_exception:"
+msgid "Moves Exception"
+msgstr ""
+
+msgctxt "field:sale.line,moves:"
+msgid "Moves"
+msgstr ""
+
+msgctxt "field:sale.line,moves_ignored:"
+msgid "Ignored Moves"
+msgstr ""
+
+msgctxt "field:sale.line,moves_recreated:"
+msgid "Recreated Moves"
+msgstr ""
+
+msgctxt "field:sale.line,note:"
+msgid "Note"
+msgstr ""
+
+msgctxt "field:sale.line,product:"
+msgid "Product"
+msgstr ""
+
+msgctxt "field:sale.line,product_uom_category:"
+msgid "Product Uom Category"
+msgstr ""
+
+msgctxt "field:sale.line,quantity:"
+msgid "Quantity"
+msgstr ""
+
+#, fuzzy
+msgctxt "field:sale.line,sale:"
+msgid "Sale"
+msgstr "Sales"
+
+msgctxt "field:sale.line,sale_state:"
+msgid "Sale State"
+msgstr ""
+
+msgctxt "field:sale.line,shipping_date:"
+msgid "Shipping Date"
+msgstr ""
+
+msgctxt "field:sale.line,summary:"
+msgid "Summary"
+msgstr ""
+
+msgctxt "field:sale.line,taxes:"
+msgid "Taxes"
+msgstr ""
+
+msgctxt "field:sale.line,to_location:"
+msgid "To Location"
+msgstr ""
+
+msgctxt "field:sale.line,type:"
+msgid "Type"
+msgstr ""
+
+msgctxt "field:sale.line,unit:"
+msgid "Unit"
+msgstr ""
+
+msgctxt "field:sale.line,unit_digits:"
+msgid "Unit Digits"
+msgstr ""
+
+msgctxt "field:sale.line,unit_price:"
+msgid "Unit Price"
+msgstr ""
+
+msgctxt "field:sale.line,warehouse:"
+msgid "Warehouse"
+msgstr ""
+
+msgctxt "field:sale.line-account.tax,line:"
+msgid "Sale Line"
+msgstr ""
+
+msgctxt "field:sale.line-account.tax,tax:"
+msgid "Tax"
+msgstr ""
+
+msgctxt "field:sale.line-ignored-stock.move,move:"
+msgid "Move"
+msgstr ""
+
+msgctxt "field:sale.line-ignored-stock.move,sale_line:"
+msgid "Sale Line"
+msgstr ""
+
+msgctxt "field:sale.line-recreated-stock.move,move:"
+msgid "Move"
+msgstr ""
+
+msgctxt "field:sale.line-recreated-stock.move,sale_line:"
+msgid "Sale Line"
+msgstr ""
+
+msgctxt "field:sale.reporting.category,category:"
+msgid "Category"
+msgstr ""
+
+msgctxt "field:sale.reporting.category,time_series:"
+msgid "Time Series"
+msgstr ""
+
+msgctxt "field:sale.reporting.category.time_series,category:"
+msgid "Category"
+msgstr ""
+
+msgctxt "field:sale.reporting.category.time_series,date:"
+msgid "Date"
+msgstr ""
+
+msgctxt "field:sale.reporting.category.tree,children:"
+msgid "Children"
+msgstr ""
+
+msgctxt "field:sale.reporting.category.tree,currency_digits:"
+msgid "Currency Digits"
+msgstr ""
+
+msgctxt "field:sale.reporting.category.tree,name:"
+msgid "Name"
+msgstr ""
+
+msgctxt "field:sale.reporting.category.tree,parent:"
+msgid "Parent"
+msgstr ""
+
+msgctxt "field:sale.reporting.category.tree,revenue:"
+msgid "Revenue"
+msgstr ""
+
+msgctxt "field:sale.reporting.context,company:"
+msgid "Company"
+msgstr ""
+
+msgctxt "field:sale.reporting.context,from_date:"
+msgid "From Date"
+msgstr ""
+
+msgctxt "field:sale.reporting.context,period:"
+msgid "Period"
+msgstr ""
+
+msgctxt "field:sale.reporting.context,to_date:"
+msgid "To Date"
+msgstr ""
+
+msgctxt "field:sale.reporting.context,warehouse:"
+msgid "Warehouse"
+msgstr ""
+
+msgctxt "field:sale.reporting.country,country:"
+msgid "Country"
+msgstr ""
+
+msgctxt "field:sale.reporting.country,time_series:"
+msgid "Time Series"
+msgstr ""
+
+msgctxt "field:sale.reporting.country.subdivision,country:"
+msgid "Country"
+msgstr ""
+
+msgctxt "field:sale.reporting.country.subdivision,subdivision:"
+msgid "Subdivision"
+msgstr ""
+
+msgctxt "field:sale.reporting.country.subdivision,time_series:"
+msgid "Time Series"
+msgstr ""
+
+msgctxt "field:sale.reporting.country.subdivision.time_series,country:"
+msgid "Country"
+msgstr ""
+
+msgctxt "field:sale.reporting.country.subdivision.time_series,date:"
+msgid "Date"
+msgstr ""
+
+msgctxt "field:sale.reporting.country.subdivision.time_series,subdivision:"
+msgid "Subdivision"
+msgstr ""
+
+msgctxt "field:sale.reporting.country.time_series,country:"
+msgid "Country"
+msgstr ""
+
+msgctxt "field:sale.reporting.country.time_series,date:"
+msgid "Date"
+msgstr ""
+
+msgctxt "field:sale.reporting.customer,customer:"
+msgid "Customer"
+msgstr ""
+
+msgctxt "field:sale.reporting.customer,time_series:"
+msgid "Time Series"
+msgstr ""
+
+msgctxt "field:sale.reporting.customer.time_series,customer:"
+msgid "Customer"
+msgstr ""
+
+msgctxt "field:sale.reporting.customer.time_series,date:"
+msgid "Date"
+msgstr ""
+
+msgctxt "field:sale.reporting.product,product:"
+msgid "Product"
+msgstr ""
+
+msgctxt "field:sale.reporting.product,time_series:"
+msgid "Time Series"
+msgstr ""
+
+msgctxt "field:sale.reporting.product.time_series,date:"
+msgid "Date"
+msgstr ""
+
+msgctxt "field:sale.reporting.product.time_series,product:"
+msgid "Product"
+msgstr ""
+
+msgctxt "field:sale.reporting.region,children:"
+msgid "Children"
+msgstr ""
+
+msgctxt "field:sale.reporting.region,parent:"
+msgid "Parent"
+msgstr ""
+
+msgctxt "field:sale.reporting.region,region:"
+msgid "Region"
+msgstr ""
+
+msgctxt "field:sale.sale,comment:"
+msgid "Comment"
+msgstr ""
+
+msgctxt "field:sale.sale,company:"
+msgid "Company"
+msgstr ""
+
+#, fuzzy
+msgctxt "field:sale.sale,confirmed_by:"
+msgid "Confirmed By"
+msgstr "Confirmed"
+
+msgctxt "field:sale.sale,contact:"
+msgid "Contact"
+msgstr ""
+
+msgctxt "field:sale.sale,currency:"
+msgid "Currency"
+msgstr ""
+
+msgctxt "field:sale.sale,currency_digits:"
+msgid "Currency Digits"
+msgstr ""
+
+msgctxt "field:sale.sale,description:"
+msgid "Description"
+msgstr ""
+
+msgctxt "field:sale.sale,invoice_address:"
+msgid "Invoice Address"
+msgstr ""
+
+msgctxt "field:sale.sale,invoice_method:"
+msgid "Invoice Method"
+msgstr ""
+
+#, fuzzy
+msgctxt "field:sale.sale,invoice_party:"
+msgid "Invoice Party"
+msgstr "Invoices"
+
+msgctxt "field:sale.sale,invoice_state:"
+msgid "Invoice State"
+msgstr ""
+
+#, fuzzy
+msgctxt "field:sale.sale,invoices:"
+msgid "Invoices"
+msgstr "Invoices"
+
+msgctxt "field:sale.sale,invoices_ignored:"
+msgid "Ignored Invoices"
+msgstr ""
+
+msgctxt "field:sale.sale,invoices_recreated:"
+msgid "Recreated Invoices"
+msgstr ""
+
+msgctxt "field:sale.sale,lines:"
+msgid "Lines"
+msgstr ""
+
+msgctxt "field:sale.sale,moves:"
+msgid "Moves"
+msgstr ""
+
+msgctxt "field:sale.sale,number:"
+msgid "Number"
+msgstr ""
+
+msgctxt "field:sale.sale,origin:"
+msgid "Origin"
+msgstr ""
+
+msgctxt "field:sale.sale,party:"
+msgid "Party"
+msgstr ""
+
+msgctxt "field:sale.sale,party_lang:"
+msgid "Party Language"
+msgstr ""
+
+msgctxt "field:sale.sale,payment_term:"
+msgid "Payment Term"
+msgstr ""
+
+#, fuzzy
+msgctxt "field:sale.sale,quoted_by:"
+msgid "Quoted By"
+msgstr "Quote"
+
+msgctxt "field:sale.sale,reference:"
+msgid "Reference"
+msgstr ""
+
+msgctxt "field:sale.sale,sale_date:"
+msgid "Sale Date"
+msgstr ""
+
+msgctxt "field:sale.sale,shipment_address:"
+msgid "Shipment Address"
+msgstr ""
+
+msgctxt "field:sale.sale,shipment_method:"
+msgid "Shipment Method"
+msgstr ""
+
+msgctxt "field:sale.sale,shipment_party:"
+msgid "Shipment Party"
+msgstr ""
+
+msgctxt "field:sale.sale,shipment_returns:"
+msgid "Shipment Returns"
+msgstr ""
+
+msgctxt "field:sale.sale,shipment_state:"
+msgid "Shipment State"
+msgstr ""
+
+#, fuzzy
+msgctxt "field:sale.sale,shipments:"
+msgid "Shipments"
+msgstr "Shipments"
+
+msgctxt "field:sale.sale,shipping_date:"
+msgid "Shipping Date"
+msgstr ""
+
+msgctxt "field:sale.sale,state:"
+msgid "State"
+msgstr ""
+
+msgctxt "field:sale.sale,tax_amount:"
+msgid "Tax"
+msgstr ""
+
+msgctxt "field:sale.sale,tax_amount_cache:"
+msgid "Tax Cache"
+msgstr ""
+
+msgctxt "field:sale.sale,total_amount:"
+msgid "Total"
+msgstr ""
+
+msgctxt "field:sale.sale,total_amount_cache:"
+msgid "Total Cache"
+msgstr ""
+
+msgctxt "field:sale.sale,untaxed_amount:"
+msgid "Untaxed"
+msgstr ""
+
+msgctxt "field:sale.sale,untaxed_amount_cache:"
+msgid "Untaxed Cache"
+msgstr ""
+
+msgctxt "field:sale.sale,warehouse:"
+msgid "Warehouse"
+msgstr ""
+
+#, fuzzy
+msgctxt "field:sale.sale-ignored-account.invoice,invoice:"
+msgid "Invoice"
+msgstr "Invoices"
+
+#, fuzzy
+msgctxt "field:sale.sale-ignored-account.invoice,sale:"
+msgid "Sale"
+msgstr "Sales"
+
+#, fuzzy
+msgctxt "field:sale.sale-recreated-account.invoice,invoice:"
+msgid "Invoice"
+msgstr "Invoices"
+
+#, fuzzy
+msgctxt "field:sale.sale-recreated-account.invoice,sale:"
+msgid "Sale"
+msgstr "Sales"
+
+#, fuzzy
+msgctxt "field:stock.move,sale:"
+msgid "Sale"
+msgstr "Sales"
+
+msgctxt "field:stock.move,sale_exception_state:"
+msgid "Exception State"
+msgstr ""
+
+msgctxt "help:product.configuration,default_lead_time:"
+msgid ""
+"The time from confirming the sales order to sending the products.\n"
+"Used for products without a lead time."
+msgstr ""
+
+msgctxt "help:product.product,lead_time:"
+msgid ""
+"The time from confirming the sales order to sending the products.\n"
+"If empty the default lead time from the configuration is used."
+msgstr ""
+
+msgctxt "help:product.template,lead_time:"
+msgid ""
+"The time from confirming the sales order to sending the products.\n"
+"If empty the default lead time from the configuration is used."
+msgstr ""
+
+msgctxt "help:sale.configuration,sale_process_after:"
+msgid ""
+"The grace period during which confirmed sale can still be reset to draft.\n"
+"Applied if a worker queue is activated."
+msgstr ""
+
+msgctxt "help:sale.handle.invoice.exception.ask,recreate_invoices:"
+msgid ""
+"The selected invoices will be recreated. The other ones will be ignored."
+msgstr ""
+
+msgctxt "help:sale.sale,shipping_date:"
+msgid "When the shipping of goods should start."
+msgstr ""
+
+msgctxt "model:ir.action,name:act_invoice_form"
+msgid "Invoices"
+msgstr "Invoices"
+
+msgctxt "model:ir.action,name:act_open_customer"
+msgid "Parties associated to Sales"
+msgstr "Parties associated to Sales"
+
+#, fuzzy
+msgctxt "model:ir.action,name:act_product"
+msgid "Products"
+msgstr "Sales per Product"
+
+msgctxt "model:ir.action,name:act_reporting_category"
+msgid "Sales per Category"
+msgstr "Sales per Category"
+
+msgctxt "model:ir.action,name:act_reporting_category_time_series"
+msgid "Sales per Category"
+msgstr "Sales per Category"
+
+msgctxt "model:ir.action,name:act_reporting_category_tree"
+msgid "Sales per Category"
+msgstr "Sales per Category"
+
+msgctxt "model:ir.action,name:act_reporting_country_subdivision_time_series"
+msgid "Sales per Subdivision"
+msgstr "Sales per Subdivision"
+
+msgctxt "model:ir.action,name:act_reporting_country_time_series"
+msgid "Sales per Country"
+msgstr "Sales per Country"
+
+msgctxt "model:ir.action,name:act_reporting_customer"
+msgid "Sales per Customer"
+msgstr "Sales per Customer"
+
+msgctxt "model:ir.action,name:act_reporting_customer_time_series"
+msgid "Sales per Customer"
+msgstr "Sales per Customer"
+
+msgctxt "model:ir.action,name:act_reporting_product"
+msgid "Sales per Product"
+msgstr "Sales per Product"
+
+msgctxt "model:ir.action,name:act_reporting_product_time_series"
+msgid "Sales per Product"
+msgstr "Sales per Product"
+
+msgctxt "model:ir.action,name:act_reporting_region"
+msgid "Sales per Region"
+msgstr "Sales per Region"
+
+msgctxt "model:ir.action,name:act_return_form"
+msgid "Returns"
+msgstr "Returns"
+
+#, fuzzy
+msgctxt "model:ir.action,name:act_sale_configuration_form"
+msgid "Configuration"
+msgstr "Configuration"
+
+msgctxt "model:ir.action,name:act_sale_form"
+msgid "Sales"
+msgstr "Sales"
+
+msgctxt "model:ir.action,name:act_sale_form2"
+msgid "Sales"
+msgstr "Sales"
+
+msgctxt "model:ir.action,name:act_sale_invoice_relate"
+msgid "Sales"
+msgstr "Sales"
+
+msgctxt "model:ir.action,name:act_sale_move_relate"
+msgid "Moves"
+msgstr ""
+
+msgctxt "model:ir.action,name:act_sale_shipment_returns_relate"
+msgid "Sales"
+msgstr "Sales"
+
+msgctxt "model:ir.action,name:act_sale_shipments_relate"
+msgid "Sales"
+msgstr "Sales"
+
+msgctxt "model:ir.action,name:act_shipment_form"
+msgid "Shipments"
+msgstr "Shipments"
+
+#, fuzzy
+msgctxt "model:ir.action,name:report_sale"
+msgid "Sale"
+msgstr "Sale"
+
+msgctxt "model:ir.action,name:wizard_invoice_handle_exception"
+msgid "Handle Invoice Exception"
+msgstr "Handle Invoice Exception"
+
+msgctxt "model:ir.action,name:wizard_modify_header"
+msgid "Modify Header"
+msgstr "Modify Header"
+
+msgctxt "model:ir.action,name:wizard_reporting_region_open"
+msgid "Open Region"
+msgstr "Open Region"
+
+msgctxt "model:ir.action,name:wizard_return_sale"
+msgid "Return Sale"
+msgstr "Return Sale"
+
+msgctxt "model:ir.action,name:wizard_shipment_handle_exception"
+msgid "Handle Shipment Exception"
+msgstr "Handle Shipment Exception"
+
+msgctxt "model:ir.action.act_window.domain,name:act_sale_form_domain_all"
+msgid "All"
+msgstr "All"
+
+#, fuzzy
+msgctxt ""
+"model:ir.action.act_window.domain,name:act_sale_form_domain_confirmed"
+msgid "Confirmed"
+msgstr "Confirmed"
+
+msgctxt "model:ir.action.act_window.domain,name:act_sale_form_domain_draft"
+msgid "Draft"
+msgstr "Draft"
+
+msgctxt ""
+"model:ir.action.act_window.domain,name:act_sale_form_domain_exception"
+msgid "Exception"
+msgstr ""
+
+msgctxt ""
+"model:ir.action.act_window.domain,name:act_sale_form_domain_processing"
+msgid "Processing"
+msgstr "Processing"
+
+msgctxt ""
+"model:ir.action.act_window.domain,name:act_sale_form_domain_quotation"
+msgid "Quotation"
+msgstr "Quotation"
+
+msgctxt "model:ir.message,text:msg_erase_party_pending_sale"
+msgid ""
+"You cannot erase party \"%(party)s\" while they have pending sales with "
+"company \"%(company)s\"."
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_sale_customer_location_required"
+msgid ""
+"To process sale \"%(sale)s\" you must set a customer location on party "
+"\"%(party)s\"."
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_sale_delete_cancel"
+msgid "To delete sale \"%(sale)s\" you must cancel it."
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_sale_invalid_method"
+msgid ""
+"You cannot use together invoice \"%(invoice_method)s\" and shipment "
+"\"%(shipment_method)s\" on sale \"%(sale)s\"."
+msgstr ""
+
+msgctxt ""
+"model:ir.message,text:msg_sale_invoice_address_required_for_quotation"
+msgid "To get a quote for sale \"%(sale)s\" you must enter an invoice address."
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_sale_invoice_reset_draft"
+msgid ""
+"You cannot reset invoice \"%(invoice)s\" to draft because it was generated "
+"by a sale."
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_sale_line_delete_cancel_draft"
+msgid ""
+"To delete line \"%(line)s\" you must cancel or reset to draft sale "
+"\"%(sale)s\"."
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_sale_missing_account_revenue"
+msgid "To invoice sale \"%(sale)s\" you must configure a default account revenue."
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_sale_modify_header_draft"
+msgid "To modify the header of sale \"%(sale)s\", it must be in \"draft\" state."
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_sale_move_reset_draft"
+msgid ""
+"You cannot reset move \"%(move)s\" to draft because it was generated by a "
+"sale."
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_sale_product_missing_account_revenue"
+msgid ""
+"To invoice sale \"%(sale)s\" you must define an account revenue for product "
+"\"%(product)s\"."
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_sale_reporting_company"
+msgid "Company"
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_sale_reporting_currency"
+msgid "Currency"
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_sale_reporting_currency_digits"
+msgid "Currency Digits"
+msgstr ""
+
+#, fuzzy
+msgctxt "model:ir.message,text:msg_sale_reporting_number"
+msgid "#"
+msgstr "#"
+
+msgctxt "model:ir.message,text:msg_sale_reporting_number_help"
+msgid "Number of sales"
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_sale_reporting_revenue"
+msgid "Revenue"
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_sale_reporting_revenue_trend"
+msgid "Revenue Trend"
+msgstr ""
+
+msgctxt ""
+"model:ir.message,text:msg_sale_shipment_address_required_for_quotation"
+msgid "To get a quote for sale \"%(sale)s\" you must enter a shipment address."
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_sale_warehouse_required_for_quotation"
+msgid "To get a quote for sale \"%(sale)s\" you must enter a warehouse."
+msgstr ""
+
+msgctxt "model:ir.model.button,string:sale_cancel_button"
+msgid "Cancel"
+msgstr "Cancel"
+
+msgctxt "model:ir.model.button,string:sale_confirm_button"
+msgid "Confirm"
+msgstr "Confirm"
+
+msgctxt "model:ir.model.button,string:sale_draft_button"
+msgid "Draft"
+msgstr "Draft"
+
+msgctxt "model:ir.model.button,string:sale_handle_invoice_exception_button"
+msgid "Handle Invoice Exception"
+msgstr "Handle Invoice Exception"
+
+msgctxt "model:ir.model.button,string:sale_handle_shipment_exception_button"
+msgid "Handle Shipment Exception"
+msgstr "Handle Shipment Exception"
+
+msgctxt "model:ir.model.button,string:sale_modify_header_button"
+msgid "Modify Header"
+msgstr "Modify Header"
+
+msgctxt "model:ir.model.button,string:sale_process_button"
+msgid "Process"
+msgstr "Process"
+
+msgctxt "model:ir.model.button,string:sale_quote_button"
+msgid "Quote"
+msgstr "Quote"
+
+msgctxt "model:ir.rule.group,name:rule_group_reporting_category_companies"
+msgid "User in companies"
+msgstr ""
+
+msgctxt ""
+"model:ir.rule.group,name:rule_group_reporting_category_time_series_companies"
+msgid "User in companies"
+msgstr ""
+
+msgctxt ""
+"model:ir.rule.group,name:rule_group_reporting_country_subdivision_time_series_companies"
+msgid "User in companies"
+msgstr ""
+
+msgctxt ""
+"model:ir.rule.group,name:rule_group_reporting_country_time_series_companies"
+msgid "User in companies"
+msgstr ""
+
+msgctxt "model:ir.rule.group,name:rule_group_reporting_customer_companies"
+msgid "User in companies"
+msgstr ""
+
+msgctxt ""
+"model:ir.rule.group,name:rule_group_reporting_customer_time_series_companies"
+msgid "User in companies"
+msgstr ""
+
+msgctxt "model:ir.rule.group,name:rule_group_reporting_product_companies"
+msgid "User in companies"
+msgstr ""
+
+msgctxt ""
+"model:ir.rule.group,name:rule_group_reporting_product_time_series_companies"
+msgid "User in companies"
+msgstr ""
+
+msgctxt "model:ir.rule.group,name:rule_group_reporting_region_companies"
+msgid "User in companies"
+msgstr ""
+
+msgctxt "model:ir.rule.group,name:rule_group_sale_companies"
+msgid "User in companies"
+msgstr ""
+
+#, fuzzy
+msgctxt "model:ir.sequence,name:sequence_sale"
+msgid "Sale"
+msgstr "Sale"
+
+#, fuzzy
+msgctxt "model:ir.sequence.type,name:sequence_type_sale"
+msgid "Sale"
+msgstr "Sale"
+
+msgctxt "model:ir.ui.menu,name:menu_configuration"
+msgid "Configuration"
+msgstr "Configuration"
+
+#, fuzzy
+msgctxt "model:ir.ui.menu,name:menu_customer"
+msgid "Associated to Sales"
+msgstr "Parties associated to Sales"
+
+#, fuzzy
+msgctxt "model:ir.ui.menu,name:menu_product"
+msgid "Products"
+msgstr "Sales per Product"
+
+msgctxt "model:ir.ui.menu,name:menu_reporting"
+msgid "Reporting"
+msgstr "Reporting"
+
+msgctxt "model:ir.ui.menu,name:menu_reporting_sale"
+msgid "Sales"
+msgstr "Sales"
+
+msgctxt "model:ir.ui.menu,name:menu_sale"
+msgid "Sales"
+msgstr "Sales"
+
+#, fuzzy
+msgctxt "model:ir.ui.menu,name:menu_sale_configuration"
+msgid "Configuration"
+msgstr "Configuration"
+
+msgctxt "model:ir.ui.menu,name:menu_sale_form"
+msgid "Sales"
+msgstr "Sales"
+
+msgctxt "model:product.configuration.default_lead_time,name:"
+msgid "Product Default Lead Time"
+msgstr ""
+
+msgctxt "model:product.sale.context,name:"
+msgid "Product Sale Context"
+msgstr ""
+
+msgctxt "model:res.group,name:group_sale"
+msgid "Sales"
+msgstr "Sales"
+
+msgctxt "model:res.group,name:group_sale_admin"
+msgid "Sales Administrator"
+msgstr "Sales Administrator"
+
+#, fuzzy
+msgctxt "model:sale.configuration,name:"
+msgid "Sale Configuration"
+msgstr "Sales Configuration"
+
+msgctxt "model:sale.configuration.sale_method,name:"
+msgid "Sale Configuration Sale Method"
+msgstr ""
+
+msgctxt "model:sale.configuration.sequence,name:"
+msgid "Sale Configuration Sequence"
+msgstr ""
+
+#, fuzzy
+msgctxt "model:sale.handle.invoice.exception.ask,name:"
+msgid "Handle Invoice Exception"
+msgstr "Handle Invoice Exception"
+
+#, fuzzy
+msgctxt "model:sale.handle.shipment.exception.ask,name:"
+msgid "Handle Shipment Exception"
+msgstr "Handle Shipment Exception"
+
+msgctxt "model:sale.line,name:"
+msgid "Sale Line"
+msgstr ""
+
+msgctxt "model:sale.line-account.tax,name:"
+msgid "Sale Line - Tax"
+msgstr ""
+
+msgctxt "model:sale.line-ignored-stock.move,name:"
+msgid "Sale Line - Ignored Move"
+msgstr ""
+
+msgctxt "model:sale.line-recreated-stock.move,name:"
+msgid "Sale Line - Recreated Move"
+msgstr ""
+
+msgctxt "model:sale.reporting.category,name:"
+msgid "Sale Reporting per Category"
+msgstr ""
+
+msgctxt "model:sale.reporting.category.time_series,name:"
+msgid "Sale Reporting per Category"
+msgstr ""
+
+msgctxt "model:sale.reporting.category.tree,name:"
+msgid "Sale Reporting per Category"
+msgstr ""
+
+msgctxt "model:sale.reporting.context,name:"
+msgid "Sale Reporting Context"
+msgstr ""
+
+msgctxt "model:sale.reporting.country,name:"
+msgid "Sale Reporting per Country"
+msgstr ""
+
+msgctxt "model:sale.reporting.country.subdivision,name:"
+msgid "Sale Reporting per Subdivision"
+msgstr ""
+
+msgctxt "model:sale.reporting.country.subdivision.time_series,name:"
+msgid "Sale Reporting per Subdivision"
+msgstr ""
+
+msgctxt "model:sale.reporting.country.time_series,name:"
+msgid "Sale Reporting per Country"
+msgstr ""
+
+msgctxt "model:sale.reporting.customer,name:"
+msgid "Sale Reporting per Customer"
+msgstr ""
+
+msgctxt "model:sale.reporting.customer.time_series,name:"
+msgid "Sale Reporting per Customer"
+msgstr ""
+
+msgctxt "model:sale.reporting.product,name:"
+msgid "Sale Reporting per Product"
+msgstr ""
+
+msgctxt "model:sale.reporting.product.time_series,name:"
+msgid "Sale Reporting per Product"
+msgstr ""
+
+msgctxt "model:sale.reporting.region,name:"
+msgid "Sale Reporting per Region"
+msgstr ""
+
+#, fuzzy
+msgctxt "model:sale.return_sale.start,name:"
+msgid "Return Sale"
+msgstr "Return Sale"
+
+#, fuzzy
+msgctxt "model:sale.sale,name:"
+msgid "Sale"
+msgstr "Sales"
+
+msgctxt "model:sale.sale-ignored-account.invoice,name:"
+msgid "Sale - Ignored Invoice"
+msgstr ""
+
+msgctxt "model:sale.sale-recreated-account.invoice,name:"
+msgid "Sale - Recreated Invoice"
+msgstr ""
+
+msgctxt "report:sale.sale:"
+msgid ":"
+msgstr ":"
+
+msgctxt "report:sale.sale:"
+msgid "Amount"
+msgstr ""
+
+msgctxt "report:sale.sale:"
+msgid "Date:"
+msgstr ""
+
+msgctxt "report:sale.sale:"
+msgid "Description"
+msgstr ""
+
+msgctxt "report:sale.sale:"
+msgid "Description:"
+msgstr ""
+
+msgctxt "report:sale.sale:"
+msgid "Draft Sale Order"
+msgstr ""
+
+msgctxt "report:sale.sale:"
+msgid "Quantity"
+msgstr ""
+
+msgctxt "report:sale.sale:"
+msgid "Quotation N°:"
+msgstr ""
+
+msgctxt "report:sale.sale:"
+msgid "Reference:"
+msgstr ""
+
+msgctxt "report:sale.sale:"
+msgid "Sale Order N°:"
+msgstr ""
+
+msgctxt "report:sale.sale:"
+msgid "Taxes"
+msgstr ""
+
+msgctxt "report:sale.sale:"
+msgid "Taxes:"
+msgstr ""
+
+msgctxt "report:sale.sale:"
+msgid "Total (excl. taxes):"
+msgstr ""
+
+msgctxt "report:sale.sale:"
+msgid "Total:"
+msgstr ""
+
+msgctxt "report:sale.sale:"
+msgid "Unit Price"
+msgstr ""
+
+msgctxt "selection:account.invoice,sale_exception_state:"
+msgid "Ignored"
+msgstr ""
+
+msgctxt "selection:account.invoice,sale_exception_state:"
+msgid "Recreated"
+msgstr ""
+
+msgctxt "selection:sale.line,type:"
+msgid "Comment"
+msgstr ""
+
+msgctxt "selection:sale.line,type:"
+msgid "Line"
+msgstr ""
+
+msgctxt "selection:sale.line,type:"
+msgid "Subtotal"
+msgstr ""
+
+msgctxt "selection:sale.line,type:"
+msgid "Title"
+msgstr ""
+
+msgctxt "selection:sale.reporting.context,period:"
+msgid "Day"
+msgstr ""
+
+msgctxt "selection:sale.reporting.context,period:"
+msgid "Month"
+msgstr ""
+
+msgctxt "selection:sale.reporting.context,period:"
+msgid "Year"
+msgstr ""
+
+msgctxt "selection:sale.sale,invoice_method:"
+msgid "Manual"
+msgstr ""
+
+msgctxt "selection:sale.sale,invoice_method:"
+msgid "On Order Processed"
+msgstr ""
+
+msgctxt "selection:sale.sale,invoice_method:"
+msgid "On Shipment Sent"
+msgstr ""
+
+msgctxt "selection:sale.sale,invoice_state:"
+msgid "Exception"
+msgstr ""
+
+msgctxt "selection:sale.sale,invoice_state:"
+msgid "None"
+msgstr ""
+
+msgctxt "selection:sale.sale,invoice_state:"
+msgid "Paid"
+msgstr ""
+
+msgctxt "selection:sale.sale,invoice_state:"
+msgid "Waiting"
+msgstr ""
+
+msgctxt "selection:sale.sale,shipment_method:"
+msgid "Manual"
+msgstr ""
+
+msgctxt "selection:sale.sale,shipment_method:"
+msgid "On Invoice Paid"
+msgstr ""
+
+msgctxt "selection:sale.sale,shipment_method:"
+msgid "On Order Processed"
+msgstr ""
+
+msgctxt "selection:sale.sale,shipment_state:"
+msgid "Exception"
+msgstr ""
+
+msgctxt "selection:sale.sale,shipment_state:"
+msgid "None"
+msgstr ""
+
+msgctxt "selection:sale.sale,shipment_state:"
+msgid "Sent"
+msgstr ""
+
+msgctxt "selection:sale.sale,shipment_state:"
+msgid "Waiting"
+msgstr ""
+
+#, fuzzy
+msgctxt "selection:sale.sale,state:"
+msgid "Cancelled"
+msgstr "Cancel"
+
+#, fuzzy
+msgctxt "selection:sale.sale,state:"
+msgid "Confirmed"
+msgstr "Confirm"
+
+msgctxt "selection:sale.sale,state:"
+msgid "Done"
+msgstr ""
+
+#, fuzzy
+msgctxt "selection:sale.sale,state:"
+msgid "Draft"
+msgstr "Draft"
+
+#, fuzzy
+msgctxt "selection:sale.sale,state:"
+msgid "Processing"
+msgstr "Processing"
+
+#, fuzzy
+msgctxt "selection:sale.sale,state:"
+msgid "Quotation"
+msgstr "Quotation"
+
+msgctxt "selection:stock.move,sale_exception_state:"
+msgid "Ignored"
+msgstr ""
+
+msgctxt "selection:stock.move,sale_exception_state:"
+msgid "Recreated"
+msgstr ""
+
+#, fuzzy
+msgctxt "view:party.party:"
+msgid "Sale"
+msgstr "Sales"
+
+msgctxt "view:product.template:"
+msgid "Customers"
+msgstr ""
+
+msgctxt "view:sale.handle.invoice.exception.ask:"
+msgid "Choose invoices to recreate:"
+msgstr ""
+
+msgctxt "view:sale.handle.shipment.exception.ask:"
+msgid "Choose move to recreate:"
+msgstr ""
+
+msgctxt "view:sale.line:"
+msgid "General"
+msgstr ""
+
+msgctxt "view:sale.line:"
+msgid "Notes"
+msgstr ""
+
+msgctxt "view:sale.line:"
+msgid "Taxes"
+msgstr ""
+
+msgctxt "view:sale.return_sale.start:"
+msgid "Are you sure to return these/this sale(s)?"
+msgstr ""
+
+msgctxt "view:sale.sale:"
+msgid "Other Info"
+msgstr ""
+
+#, fuzzy
+msgctxt "view:sale.sale:"
+msgid "Sale"
+msgstr "Sales"
+
+#, fuzzy
+msgctxt "wizard_button:sale.handle.invoice.exception,ask,end:"
+msgid "Cancel"
+msgstr "Cancel"
+
+msgctxt "wizard_button:sale.handle.invoice.exception,ask,handle:"
+msgid "OK"
+msgstr ""
+
+#, fuzzy
+msgctxt "wizard_button:sale.handle.shipment.exception,ask,end:"
+msgid "Cancel"
+msgstr "Cancel"
+
+msgctxt "wizard_button:sale.handle.shipment.exception,ask,handle:"
+msgid "OK"
+msgstr ""
+
+#, fuzzy
+msgctxt "wizard_button:sale.modify_header,start,end:"
+msgid "Cancel"
+msgstr "Cancel"
+
+msgctxt "wizard_button:sale.modify_header,start,modify:"
+msgid "Modify"
+msgstr ""
+
+#, fuzzy
+msgctxt "wizard_button:sale.return_sale,start,end:"
+msgid "Cancel"
+msgstr "Cancel"
+
+#, fuzzy
+msgctxt "wizard_button:sale.return_sale,start,return_:"
+msgid "Return"
+msgstr "Returns"
diff --git a/modules/sale/locale/zh_CN.po b/modules/sale/locale/zh_CN.po
new file mode 100644
index 0000000000..23a86b8d6e
--- /dev/null
+++ b/modules/sale/locale/zh_CN.po
@@ -0,0 +1,1399 @@
+#
+msgid ""
+msgstr "Content-Type: text/plain; charset=utf-8\n"
+
+msgctxt "field:account.invoice,sale_exception_state:"
+msgid "Exception State"
+msgstr ""
+
+#, fuzzy
+msgctxt "field:account.invoice,sales:"
+msgid "Sales"
+msgstr "Sales"
+
+msgctxt "field:product.configuration,default_lead_time:"
+msgid "Default Lead Time"
+msgstr ""
+
+msgctxt "field:product.configuration.default_lead_time,company:"
+msgid "Company"
+msgstr ""
+
+msgctxt "field:product.configuration.default_lead_time,default_lead_time:"
+msgid "Default Lead Time"
+msgstr ""
+
+msgctxt "field:product.product,lead_time:"
+msgid "Lead Time"
+msgstr ""
+
+msgctxt "field:product.product,salable:"
+msgid "Salable"
+msgstr ""
+
+msgctxt "field:product.product,sale_price_uom:"
+msgid "Sale Price"
+msgstr ""
+
+msgctxt "field:product.product,sale_uom:"
+msgid "Sale UOM"
+msgstr ""
+
+msgctxt "field:product.sale.context,company:"
+msgid "Company"
+msgstr ""
+
+msgctxt "field:product.sale.context,currency:"
+msgid "Currency"
+msgstr ""
+
+#, fuzzy
+msgctxt "field:product.sale.context,customer:"
+msgid "Customer"
+msgstr "Sales per Customer"
+
+msgctxt "field:product.sale.context,locations:"
+msgid "Warehouses"
+msgstr ""
+
+msgctxt "field:product.sale.context,quantity:"
+msgid "Quantity"
+msgstr ""
+
+#, fuzzy
+msgctxt "field:product.sale.context,sale_date:"
+msgid "Sale Date"
+msgstr "写入日期"
+
+msgctxt "field:product.sale.context,stock_date_end:"
+msgid "Stock End Date"
+msgstr ""
+
+msgctxt "field:product.template,lead_time:"
+msgid "Lead Time"
+msgstr ""
+
+msgctxt "field:product.template,salable:"
+msgid "Salable"
+msgstr ""
+
+msgctxt "field:product.template,sale_uom:"
+msgid "Sale UOM"
+msgstr ""
+
+msgctxt "field:sale.configuration,sale_invoice_method:"
+msgid "Sale Invoice Method"
+msgstr ""
+
+msgctxt "field:sale.configuration,sale_process_after:"
+msgid "Process Sale after"
+msgstr ""
+
+msgctxt "field:sale.configuration,sale_sequence:"
+msgid "Sale Sequence"
+msgstr ""
+
+msgctxt "field:sale.configuration,sale_shipment_method:"
+msgid "Sale Shipment Method"
+msgstr ""
+
+msgctxt "field:sale.configuration.sale_method,sale_invoice_method:"
+msgid "Sale Invoice Method"
+msgstr ""
+
+msgctxt "field:sale.configuration.sale_method,sale_shipment_method:"
+msgid "Sale Shipment Method"
+msgstr ""
+
+msgctxt "field:sale.configuration.sequence,company:"
+msgid "Company"
+msgstr ""
+
+msgctxt "field:sale.configuration.sequence,sale_sequence:"
+msgid "Sale Sequence"
+msgstr ""
+
+msgctxt "field:sale.handle.invoice.exception.ask,domain_invoices:"
+msgid "Domain Invoices"
+msgstr ""
+
+msgctxt "field:sale.handle.invoice.exception.ask,recreate_invoices:"
+msgid "Recreate Invoices"
+msgstr ""
+
+msgctxt "field:sale.handle.shipment.exception.ask,domain_moves:"
+msgid "Domain Moves"
+msgstr ""
+
+msgctxt "field:sale.handle.shipment.exception.ask,recreate_moves:"
+msgid "Recreate Moves"
+msgstr ""
+
+msgctxt "field:sale.line,actual_quantity:"
+msgid "Actual Quantity"
+msgstr ""
+
+msgctxt "field:sale.line,amount:"
+msgid "Amount"
+msgstr ""
+
+msgctxt "field:sale.line,company:"
+msgid "Company"
+msgstr ""
+
+msgctxt "field:sale.line,currency:"
+msgid "Currency"
+msgstr ""
+
+#, fuzzy
+msgctxt "field:sale.line,description:"
+msgid "Description"
+msgstr "描述"
+
+msgctxt "field:sale.line,from_location:"
+msgid "From Location"
+msgstr ""
+
+msgctxt "field:sale.line,invoice_lines:"
+msgid "Invoice Lines"
+msgstr ""
+
+msgctxt "field:sale.line,move_done:"
+msgid "Moves Done"
+msgstr ""
+
+msgctxt "field:sale.line,move_exception:"
+msgid "Moves Exception"
+msgstr ""
+
+msgctxt "field:sale.line,moves:"
+msgid "Moves"
+msgstr ""
+
+msgctxt "field:sale.line,moves_ignored:"
+msgid "Ignored Moves"
+msgstr ""
+
+msgctxt "field:sale.line,moves_recreated:"
+msgid "Recreated Moves"
+msgstr ""
+
+#, fuzzy
+msgctxt "field:sale.line,note:"
+msgid "Note"
+msgstr "注释"
+
+msgctxt "field:sale.line,product:"
+msgid "Product"
+msgstr ""
+
+msgctxt "field:sale.line,product_uom_category:"
+msgid "Product Uom Category"
+msgstr ""
+
+msgctxt "field:sale.line,quantity:"
+msgid "Quantity"
+msgstr ""
+
+#, fuzzy
+msgctxt "field:sale.line,sale:"
+msgid "Sale"
+msgstr "Sales"
+
+msgctxt "field:sale.line,sale_state:"
+msgid "Sale State"
+msgstr ""
+
+msgctxt "field:sale.line,shipping_date:"
+msgid "Shipping Date"
+msgstr ""
+
+msgctxt "field:sale.line,summary:"
+msgid "Summary"
+msgstr ""
+
+msgctxt "field:sale.line,taxes:"
+msgid "Taxes"
+msgstr ""
+
+msgctxt "field:sale.line,to_location:"
+msgid "To Location"
+msgstr ""
+
+#, fuzzy
+msgctxt "field:sale.line,type:"
+msgid "Type"
+msgstr "类型"
+
+msgctxt "field:sale.line,unit:"
+msgid "Unit"
+msgstr ""
+
+msgctxt "field:sale.line,unit_digits:"
+msgid "Unit Digits"
+msgstr ""
+
+msgctxt "field:sale.line,unit_price:"
+msgid "Unit Price"
+msgstr ""
+
+msgctxt "field:sale.line,warehouse:"
+msgid "Warehouse"
+msgstr ""
+
+msgctxt "field:sale.line-account.tax,line:"
+msgid "Sale Line"
+msgstr ""
+
+msgctxt "field:sale.line-account.tax,tax:"
+msgid "Tax"
+msgstr ""
+
+msgctxt "field:sale.line-ignored-stock.move,move:"
+msgid "Move"
+msgstr ""
+
+msgctxt "field:sale.line-ignored-stock.move,sale_line:"
+msgid "Sale Line"
+msgstr ""
+
+msgctxt "field:sale.line-recreated-stock.move,move:"
+msgid "Move"
+msgstr ""
+
+msgctxt "field:sale.line-recreated-stock.move,sale_line:"
+msgid "Sale Line"
+msgstr ""
+
+msgctxt "field:sale.reporting.category,category:"
+msgid "Category"
+msgstr ""
+
+msgctxt "field:sale.reporting.category,time_series:"
+msgid "Time Series"
+msgstr ""
+
+msgctxt "field:sale.reporting.category.time_series,category:"
+msgid "Category"
+msgstr ""
+
+msgctxt "field:sale.reporting.category.time_series,date:"
+msgid "Date"
+msgstr ""
+
+msgctxt "field:sale.reporting.category.tree,children:"
+msgid "Children"
+msgstr ""
+
+msgctxt "field:sale.reporting.category.tree,currency_digits:"
+msgid "Currency Digits"
+msgstr ""
+
+#, fuzzy
+msgctxt "field:sale.reporting.category.tree,name:"
+msgid "Name"
+msgstr "纳木"
+
+msgctxt "field:sale.reporting.category.tree,parent:"
+msgid "Parent"
+msgstr ""
+
+msgctxt "field:sale.reporting.category.tree,revenue:"
+msgid "Revenue"
+msgstr ""
+
+msgctxt "field:sale.reporting.context,company:"
+msgid "Company"
+msgstr ""
+
+msgctxt "field:sale.reporting.context,from_date:"
+msgid "From Date"
+msgstr ""
+
+msgctxt "field:sale.reporting.context,period:"
+msgid "Period"
+msgstr ""
+
+msgctxt "field:sale.reporting.context,to_date:"
+msgid "To Date"
+msgstr ""
+
+msgctxt "field:sale.reporting.context,warehouse:"
+msgid "Warehouse"
+msgstr ""
+
+msgctxt "field:sale.reporting.country,country:"
+msgid "Country"
+msgstr ""
+
+msgctxt "field:sale.reporting.country,time_series:"
+msgid "Time Series"
+msgstr ""
+
+msgctxt "field:sale.reporting.country.subdivision,country:"
+msgid "Country"
+msgstr ""
+
+msgctxt "field:sale.reporting.country.subdivision,subdivision:"
+msgid "Subdivision"
+msgstr ""
+
+msgctxt "field:sale.reporting.country.subdivision,time_series:"
+msgid "Time Series"
+msgstr ""
+
+msgctxt "field:sale.reporting.country.subdivision.time_series,country:"
+msgid "Country"
+msgstr ""
+
+msgctxt "field:sale.reporting.country.subdivision.time_series,date:"
+msgid "Date"
+msgstr ""
+
+msgctxt "field:sale.reporting.country.subdivision.time_series,subdivision:"
+msgid "Subdivision"
+msgstr ""
+
+msgctxt "field:sale.reporting.country.time_series,country:"
+msgid "Country"
+msgstr ""
+
+msgctxt "field:sale.reporting.country.time_series,date:"
+msgid "Date"
+msgstr ""
+
+msgctxt "field:sale.reporting.customer,customer:"
+msgid "Customer"
+msgstr ""
+
+msgctxt "field:sale.reporting.customer,time_series:"
+msgid "Time Series"
+msgstr ""
+
+msgctxt "field:sale.reporting.customer.time_series,customer:"
+msgid "Customer"
+msgstr ""
+
+msgctxt "field:sale.reporting.customer.time_series,date:"
+msgid "Date"
+msgstr ""
+
+msgctxt "field:sale.reporting.product,product:"
+msgid "Product"
+msgstr ""
+
+msgctxt "field:sale.reporting.product,time_series:"
+msgid "Time Series"
+msgstr ""
+
+msgctxt "field:sale.reporting.product.time_series,date:"
+msgid "Date"
+msgstr ""
+
+msgctxt "field:sale.reporting.product.time_series,product:"
+msgid "Product"
+msgstr ""
+
+msgctxt "field:sale.reporting.region,children:"
+msgid "Children"
+msgstr ""
+
+msgctxt "field:sale.reporting.region,parent:"
+msgid "Parent"
+msgstr ""
+
+msgctxt "field:sale.reporting.region,region:"
+msgid "Region"
+msgstr ""
+
+msgctxt "field:sale.sale,comment:"
+msgid "Comment"
+msgstr ""
+
+msgctxt "field:sale.sale,company:"
+msgid "Company"
+msgstr ""
+
+#, fuzzy
+msgctxt "field:sale.sale,confirmed_by:"
+msgid "Confirmed By"
+msgstr "Confirmed"
+
+msgctxt "field:sale.sale,contact:"
+msgid "Contact"
+msgstr ""
+
+msgctxt "field:sale.sale,currency:"
+msgid "Currency"
+msgstr ""
+
+msgctxt "field:sale.sale,currency_digits:"
+msgid "Currency Digits"
+msgstr ""
+
+#, fuzzy
+msgctxt "field:sale.sale,description:"
+msgid "Description"
+msgstr "描述"
+
+msgctxt "field:sale.sale,invoice_address:"
+msgid "Invoice Address"
+msgstr ""
+
+msgctxt "field:sale.sale,invoice_method:"
+msgid "Invoice Method"
+msgstr ""
+
+#, fuzzy
+msgctxt "field:sale.sale,invoice_party:"
+msgid "Invoice Party"
+msgstr "Invoices"
+
+msgctxt "field:sale.sale,invoice_state:"
+msgid "Invoice State"
+msgstr ""
+
+#, fuzzy
+msgctxt "field:sale.sale,invoices:"
+msgid "Invoices"
+msgstr "Invoices"
+
+msgctxt "field:sale.sale,invoices_ignored:"
+msgid "Ignored Invoices"
+msgstr ""
+
+msgctxt "field:sale.sale,invoices_recreated:"
+msgid "Recreated Invoices"
+msgstr ""
+
+msgctxt "field:sale.sale,lines:"
+msgid "Lines"
+msgstr ""
+
+msgctxt "field:sale.sale,moves:"
+msgid "Moves"
+msgstr ""
+
+msgctxt "field:sale.sale,number:"
+msgid "Number"
+msgstr ""
+
+msgctxt "field:sale.sale,origin:"
+msgid "Origin"
+msgstr ""
+
+msgctxt "field:sale.sale,party:"
+msgid "Party"
+msgstr ""
+
+msgctxt "field:sale.sale,party_lang:"
+msgid "Party Language"
+msgstr ""
+
+msgctxt "field:sale.sale,payment_term:"
+msgid "Payment Term"
+msgstr ""
+
+#, fuzzy
+msgctxt "field:sale.sale,quoted_by:"
+msgid "Quoted By"
+msgstr "Quote"
+
+msgctxt "field:sale.sale,reference:"
+msgid "Reference"
+msgstr ""
+
+msgctxt "field:sale.sale,sale_date:"
+msgid "Sale Date"
+msgstr ""
+
+msgctxt "field:sale.sale,shipment_address:"
+msgid "Shipment Address"
+msgstr ""
+
+msgctxt "field:sale.sale,shipment_method:"
+msgid "Shipment Method"
+msgstr ""
+
+msgctxt "field:sale.sale,shipment_party:"
+msgid "Shipment Party"
+msgstr ""
+
+msgctxt "field:sale.sale,shipment_returns:"
+msgid "Shipment Returns"
+msgstr ""
+
+msgctxt "field:sale.sale,shipment_state:"
+msgid "Shipment State"
+msgstr ""
+
+#, fuzzy
+msgctxt "field:sale.sale,shipments:"
+msgid "Shipments"
+msgstr "Shipments"
+
+msgctxt "field:sale.sale,shipping_date:"
+msgid "Shipping Date"
+msgstr ""
+
+#, fuzzy
+msgctxt "field:sale.sale,state:"
+msgid "State"
+msgstr "状态"
+
+msgctxt "field:sale.sale,tax_amount:"
+msgid "Tax"
+msgstr ""
+
+msgctxt "field:sale.sale,tax_amount_cache:"
+msgid "Tax Cache"
+msgstr ""
+
+msgctxt "field:sale.sale,total_amount:"
+msgid "Total"
+msgstr ""
+
+msgctxt "field:sale.sale,total_amount_cache:"
+msgid "Total Cache"
+msgstr ""
+
+msgctxt "field:sale.sale,untaxed_amount:"
+msgid "Untaxed"
+msgstr ""
+
+msgctxt "field:sale.sale,untaxed_amount_cache:"
+msgid "Untaxed Cache"
+msgstr ""
+
+msgctxt "field:sale.sale,warehouse:"
+msgid "Warehouse"
+msgstr ""
+
+#, fuzzy
+msgctxt "field:sale.sale-ignored-account.invoice,invoice:"
+msgid "Invoice"
+msgstr "Invoices"
+
+#, fuzzy
+msgctxt "field:sale.sale-ignored-account.invoice,sale:"
+msgid "Sale"
+msgstr "Sales"
+
+#, fuzzy
+msgctxt "field:sale.sale-recreated-account.invoice,invoice:"
+msgid "Invoice"
+msgstr "Invoices"
+
+#, fuzzy
+msgctxt "field:sale.sale-recreated-account.invoice,sale:"
+msgid "Sale"
+msgstr "Sales"
+
+#, fuzzy
+msgctxt "field:stock.move,sale:"
+msgid "Sale"
+msgstr "Sales"
+
+msgctxt "field:stock.move,sale_exception_state:"
+msgid "Exception State"
+msgstr ""
+
+msgctxt "help:product.configuration,default_lead_time:"
+msgid ""
+"The time from confirming the sales order to sending the products.\n"
+"Used for products without a lead time."
+msgstr ""
+
+msgctxt "help:product.product,lead_time:"
+msgid ""
+"The time from confirming the sales order to sending the products.\n"
+"If empty the default lead time from the configuration is used."
+msgstr ""
+
+msgctxt "help:product.template,lead_time:"
+msgid ""
+"The time from confirming the sales order to sending the products.\n"
+"If empty the default lead time from the configuration is used."
+msgstr ""
+
+msgctxt "help:sale.configuration,sale_process_after:"
+msgid ""
+"The grace period during which confirmed sale can still be reset to draft.\n"
+"Applied if a worker queue is activated."
+msgstr ""
+
+msgctxt "help:sale.handle.invoice.exception.ask,recreate_invoices:"
+msgid ""
+"The selected invoices will be recreated. The other ones will be ignored."
+msgstr ""
+
+msgctxt "help:sale.sale,shipping_date:"
+msgid "When the shipping of goods should start."
+msgstr ""
+
+msgctxt "model:ir.action,name:act_invoice_form"
+msgid "Invoices"
+msgstr "发票"
+
+msgctxt "model:ir.action,name:act_open_customer"
+msgid "Parties associated to Sales"
+msgstr "Parties associated to Sales"
+
+#, fuzzy
+msgctxt "model:ir.action,name:act_product"
+msgid "Products"
+msgstr "Sales per Product"
+
+msgctxt "model:ir.action,name:act_reporting_category"
+msgid "Sales per Category"
+msgstr "Sales per Category"
+
+msgctxt "model:ir.action,name:act_reporting_category_time_series"
+msgid "Sales per Category"
+msgstr "Sales per Category"
+
+msgctxt "model:ir.action,name:act_reporting_category_tree"
+msgid "Sales per Category"
+msgstr "Sales per Category"
+
+msgctxt "model:ir.action,name:act_reporting_country_subdivision_time_series"
+msgid "Sales per Subdivision"
+msgstr "Sales per Subdivision"
+
+msgctxt "model:ir.action,name:act_reporting_country_time_series"
+msgid "Sales per Country"
+msgstr "Sales per Country"
+
+msgctxt "model:ir.action,name:act_reporting_customer"
+msgid "Sales per Customer"
+msgstr "Sales per Customer"
+
+msgctxt "model:ir.action,name:act_reporting_customer_time_series"
+msgid "Sales per Customer"
+msgstr "Sales per Customer"
+
+msgctxt "model:ir.action,name:act_reporting_product"
+msgid "Sales per Product"
+msgstr "Sales per Product"
+
+msgctxt "model:ir.action,name:act_reporting_product_time_series"
+msgid "Sales per Product"
+msgstr "Sales per Product"
+
+msgctxt "model:ir.action,name:act_reporting_region"
+msgid "Sales per Region"
+msgstr "Sales per Region"
+
+msgctxt "model:ir.action,name:act_return_form"
+msgid "Returns"
+msgstr "退货"
+
+#, fuzzy
+msgctxt "model:ir.action,name:act_sale_configuration_form"
+msgid "Configuration"
+msgstr "设置"
+
+msgctxt "model:ir.action,name:act_sale_form"
+msgid "Sales"
+msgstr "Sales"
+
+msgctxt "model:ir.action,name:act_sale_form2"
+msgid "Sales"
+msgstr "Sales"
+
+msgctxt "model:ir.action,name:act_sale_invoice_relate"
+msgid "Sales"
+msgstr "Sales"
+
+msgctxt "model:ir.action,name:act_sale_move_relate"
+msgid "Moves"
+msgstr ""
+
+msgctxt "model:ir.action,name:act_sale_shipment_returns_relate"
+msgid "Sales"
+msgstr "Sales"
+
+msgctxt "model:ir.action,name:act_sale_shipments_relate"
+msgid "Sales"
+msgstr "Sales"
+
+msgctxt "model:ir.action,name:act_shipment_form"
+msgid "Shipments"
+msgstr "发货"
+
+#, fuzzy
+msgctxt "model:ir.action,name:report_sale"
+msgid "Sale"
+msgstr "Sale"
+
+msgctxt "model:ir.action,name:wizard_invoice_handle_exception"
+msgid "Handle Invoice Exception"
+msgstr "处理发票异常"
+
+msgctxt "model:ir.action,name:wizard_modify_header"
+msgid "Modify Header"
+msgstr "修改标题"
+
+msgctxt "model:ir.action,name:wizard_reporting_region_open"
+msgid "Open Region"
+msgstr "Open Region"
+
+msgctxt "model:ir.action,name:wizard_return_sale"
+msgid "Return Sale"
+msgstr "Return Sale"
+
+msgctxt "model:ir.action,name:wizard_shipment_handle_exception"
+msgid "Handle Shipment Exception"
+msgstr "处理发货异常"
+
+#, fuzzy
+msgctxt "model:ir.action.act_window.domain,name:act_sale_form_domain_all"
+msgid "All"
+msgstr "全部"
+
+#, fuzzy
+msgctxt ""
+"model:ir.action.act_window.domain,name:act_sale_form_domain_confirmed"
+msgid "Confirmed"
+msgstr "Confirmed"
+
+msgctxt "model:ir.action.act_window.domain,name:act_sale_form_domain_draft"
+msgid "Draft"
+msgstr "Draft"
+
+msgctxt ""
+"model:ir.action.act_window.domain,name:act_sale_form_domain_exception"
+msgid "Exception"
+msgstr ""
+
+msgctxt ""
+"model:ir.action.act_window.domain,name:act_sale_form_domain_processing"
+msgid "Processing"
+msgstr "Processing"
+
+msgctxt ""
+"model:ir.action.act_window.domain,name:act_sale_form_domain_quotation"
+msgid "Quotation"
+msgstr "Quotation"
+
+msgctxt "model:ir.message,text:msg_erase_party_pending_sale"
+msgid ""
+"You cannot erase party \"%(party)s\" while they have pending sales with "
+"company \"%(company)s\"."
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_sale_customer_location_required"
+msgid ""
+"To process sale \"%(sale)s\" you must set a customer location on party "
+"\"%(party)s\"."
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_sale_delete_cancel"
+msgid "To delete sale \"%(sale)s\" you must cancel it."
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_sale_invalid_method"
+msgid ""
+"You cannot use together invoice \"%(invoice_method)s\" and shipment "
+"\"%(shipment_method)s\" on sale \"%(sale)s\"."
+msgstr ""
+
+msgctxt ""
+"model:ir.message,text:msg_sale_invoice_address_required_for_quotation"
+msgid "To get a quote for sale \"%(sale)s\" you must enter an invoice address."
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_sale_invoice_reset_draft"
+msgid ""
+"You cannot reset invoice \"%(invoice)s\" to draft because it was generated "
+"by a sale."
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_sale_line_delete_cancel_draft"
+msgid ""
+"To delete line \"%(line)s\" you must cancel or reset to draft sale "
+"\"%(sale)s\"."
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_sale_missing_account_revenue"
+msgid "To invoice sale \"%(sale)s\" you must configure a default account revenue."
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_sale_modify_header_draft"
+msgid "To modify the header of sale \"%(sale)s\", it must be in \"draft\" state."
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_sale_move_reset_draft"
+msgid ""
+"You cannot reset move \"%(move)s\" to draft because it was generated by a "
+"sale."
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_sale_product_missing_account_revenue"
+msgid ""
+"To invoice sale \"%(sale)s\" you must define an account revenue for product "
+"\"%(product)s\"."
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_sale_reporting_company"
+msgid "Company"
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_sale_reporting_currency"
+msgid "Currency"
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_sale_reporting_currency_digits"
+msgid "Currency Digits"
+msgstr ""
+
+#, fuzzy
+msgctxt "model:ir.message,text:msg_sale_reporting_number"
+msgid "#"
+msgstr "#"
+
+msgctxt "model:ir.message,text:msg_sale_reporting_number_help"
+msgid "Number of sales"
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_sale_reporting_revenue"
+msgid "Revenue"
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_sale_reporting_revenue_trend"
+msgid "Revenue Trend"
+msgstr ""
+
+msgctxt ""
+"model:ir.message,text:msg_sale_shipment_address_required_for_quotation"
+msgid "To get a quote for sale \"%(sale)s\" you must enter a shipment address."
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_sale_warehouse_required_for_quotation"
+msgid "To get a quote for sale \"%(sale)s\" you must enter a warehouse."
+msgstr ""
+
+msgctxt "model:ir.model.button,string:sale_cancel_button"
+msgid "Cancel"
+msgstr "Cancel"
+
+msgctxt "model:ir.model.button,string:sale_confirm_button"
+msgid "Confirm"
+msgstr "Confirm"
+
+msgctxt "model:ir.model.button,string:sale_draft_button"
+msgid "Draft"
+msgstr "Draft"
+
+msgctxt "model:ir.model.button,string:sale_handle_invoice_exception_button"
+msgid "Handle Invoice Exception"
+msgstr "Handle Invoice Exception"
+
+msgctxt "model:ir.model.button,string:sale_handle_shipment_exception_button"
+msgid "Handle Shipment Exception"
+msgstr "Handle Shipment Exception"
+
+msgctxt "model:ir.model.button,string:sale_modify_header_button"
+msgid "Modify Header"
+msgstr "Modify Header"
+
+msgctxt "model:ir.model.button,string:sale_process_button"
+msgid "Process"
+msgstr "Process"
+
+msgctxt "model:ir.model.button,string:sale_quote_button"
+msgid "Quote"
+msgstr "Quote"
+
+msgctxt "model:ir.rule.group,name:rule_group_reporting_category_companies"
+msgid "User in companies"
+msgstr ""
+
+msgctxt ""
+"model:ir.rule.group,name:rule_group_reporting_category_time_series_companies"
+msgid "User in companies"
+msgstr ""
+
+msgctxt ""
+"model:ir.rule.group,name:rule_group_reporting_country_subdivision_time_series_companies"
+msgid "User in companies"
+msgstr ""
+
+msgctxt ""
+"model:ir.rule.group,name:rule_group_reporting_country_time_series_companies"
+msgid "User in companies"
+msgstr ""
+
+msgctxt "model:ir.rule.group,name:rule_group_reporting_customer_companies"
+msgid "User in companies"
+msgstr ""
+
+msgctxt ""
+"model:ir.rule.group,name:rule_group_reporting_customer_time_series_companies"
+msgid "User in companies"
+msgstr ""
+
+msgctxt "model:ir.rule.group,name:rule_group_reporting_product_companies"
+msgid "User in companies"
+msgstr ""
+
+msgctxt ""
+"model:ir.rule.group,name:rule_group_reporting_product_time_series_companies"
+msgid "User in companies"
+msgstr ""
+
+msgctxt "model:ir.rule.group,name:rule_group_reporting_region_companies"
+msgid "User in companies"
+msgstr ""
+
+msgctxt "model:ir.rule.group,name:rule_group_sale_companies"
+msgid "User in companies"
+msgstr ""
+
+#, fuzzy
+msgctxt "model:ir.sequence,name:sequence_sale"
+msgid "Sale"
+msgstr "Sale"
+
+#, fuzzy
+msgctxt "model:ir.sequence.type,name:sequence_type_sale"
+msgid "Sale"
+msgstr "Sale"
+
+msgctxt "model:ir.ui.menu,name:menu_configuration"
+msgid "Configuration"
+msgstr "设置"
+
+#, fuzzy
+msgctxt "model:ir.ui.menu,name:menu_customer"
+msgid "Associated to Sales"
+msgstr "Parties associated to Sales"
+
+#, fuzzy
+msgctxt "model:ir.ui.menu,name:menu_product"
+msgid "Products"
+msgstr "Sales per Product"
+
+msgctxt "model:ir.ui.menu,name:menu_reporting"
+msgid "Reporting"
+msgstr "报表"
+
+msgctxt "model:ir.ui.menu,name:menu_reporting_sale"
+msgid "Sales"
+msgstr "Sales"
+
+msgctxt "model:ir.ui.menu,name:menu_sale"
+msgid "Sales"
+msgstr "Sales"
+
+#, fuzzy
+msgctxt "model:ir.ui.menu,name:menu_sale_configuration"
+msgid "Configuration"
+msgstr "设置"
+
+msgctxt "model:ir.ui.menu,name:menu_sale_form"
+msgid "Sales"
+msgstr "Sales"
+
+msgctxt "model:product.configuration.default_lead_time,name:"
+msgid "Product Default Lead Time"
+msgstr ""
+
+msgctxt "model:product.sale.context,name:"
+msgid "Product Sale Context"
+msgstr ""
+
+msgctxt "model:res.group,name:group_sale"
+msgid "Sales"
+msgstr "Sales"
+
+msgctxt "model:res.group,name:group_sale_admin"
+msgid "Sales Administrator"
+msgstr "Sales Administrator"
+
+#, fuzzy
+msgctxt "model:sale.configuration,name:"
+msgid "Sale Configuration"
+msgstr "Sales Configuration"
+
+msgctxt "model:sale.configuration.sale_method,name:"
+msgid "Sale Configuration Sale Method"
+msgstr ""
+
+msgctxt "model:sale.configuration.sequence,name:"
+msgid "Sale Configuration Sequence"
+msgstr ""
+
+#, fuzzy
+msgctxt "model:sale.handle.invoice.exception.ask,name:"
+msgid "Handle Invoice Exception"
+msgstr "Handle Invoice Exception"
+
+#, fuzzy
+msgctxt "model:sale.handle.shipment.exception.ask,name:"
+msgid "Handle Shipment Exception"
+msgstr "Handle Shipment Exception"
+
+msgctxt "model:sale.line,name:"
+msgid "Sale Line"
+msgstr ""
+
+msgctxt "model:sale.line-account.tax,name:"
+msgid "Sale Line - Tax"
+msgstr ""
+
+msgctxt "model:sale.line-ignored-stock.move,name:"
+msgid "Sale Line - Ignored Move"
+msgstr ""
+
+msgctxt "model:sale.line-recreated-stock.move,name:"
+msgid "Sale Line - Recreated Move"
+msgstr ""
+
+msgctxt "model:sale.reporting.category,name:"
+msgid "Sale Reporting per Category"
+msgstr ""
+
+msgctxt "model:sale.reporting.category.time_series,name:"
+msgid "Sale Reporting per Category"
+msgstr ""
+
+msgctxt "model:sale.reporting.category.tree,name:"
+msgid "Sale Reporting per Category"
+msgstr ""
+
+msgctxt "model:sale.reporting.context,name:"
+msgid "Sale Reporting Context"
+msgstr ""
+
+msgctxt "model:sale.reporting.country,name:"
+msgid "Sale Reporting per Country"
+msgstr ""
+
+msgctxt "model:sale.reporting.country.subdivision,name:"
+msgid "Sale Reporting per Subdivision"
+msgstr ""
+
+msgctxt "model:sale.reporting.country.subdivision.time_series,name:"
+msgid "Sale Reporting per Subdivision"
+msgstr ""
+
+msgctxt "model:sale.reporting.country.time_series,name:"
+msgid "Sale Reporting per Country"
+msgstr ""
+
+msgctxt "model:sale.reporting.customer,name:"
+msgid "Sale Reporting per Customer"
+msgstr ""
+
+msgctxt "model:sale.reporting.customer.time_series,name:"
+msgid "Sale Reporting per Customer"
+msgstr ""
+
+msgctxt "model:sale.reporting.product,name:"
+msgid "Sale Reporting per Product"
+msgstr ""
+
+msgctxt "model:sale.reporting.product.time_series,name:"
+msgid "Sale Reporting per Product"
+msgstr ""
+
+msgctxt "model:sale.reporting.region,name:"
+msgid "Sale Reporting per Region"
+msgstr ""
+
+#, fuzzy
+msgctxt "model:sale.return_sale.start,name:"
+msgid "Return Sale"
+msgstr "Return Sale"
+
+#, fuzzy
+msgctxt "model:sale.sale,name:"
+msgid "Sale"
+msgstr "Sales"
+
+msgctxt "model:sale.sale-ignored-account.invoice,name:"
+msgid "Sale - Ignored Invoice"
+msgstr ""
+
+msgctxt "model:sale.sale-recreated-account.invoice,name:"
+msgid "Sale - Recreated Invoice"
+msgstr ""
+
+#, fuzzy
+msgctxt "report:sale.sale:"
+msgid ":"
+msgstr ":"
+
+msgctxt "report:sale.sale:"
+msgid "Amount"
+msgstr ""
+
+msgctxt "report:sale.sale:"
+msgid "Date:"
+msgstr ""
+
+#, fuzzy
+msgctxt "report:sale.sale:"
+msgid "Description"
+msgstr "描述"
+
+#, fuzzy
+msgctxt "report:sale.sale:"
+msgid "Description:"
+msgstr "描述"
+
+msgctxt "report:sale.sale:"
+msgid "Draft Sale Order"
+msgstr ""
+
+msgctxt "report:sale.sale:"
+msgid "Quantity"
+msgstr ""
+
+msgctxt "report:sale.sale:"
+msgid "Quotation N°:"
+msgstr ""
+
+msgctxt "report:sale.sale:"
+msgid "Reference:"
+msgstr ""
+
+msgctxt "report:sale.sale:"
+msgid "Sale Order N°:"
+msgstr ""
+
+msgctxt "report:sale.sale:"
+msgid "Taxes"
+msgstr ""
+
+msgctxt "report:sale.sale:"
+msgid "Taxes:"
+msgstr ""
+
+msgctxt "report:sale.sale:"
+msgid "Total (excl. taxes):"
+msgstr ""
+
+msgctxt "report:sale.sale:"
+msgid "Total:"
+msgstr ""
+
+msgctxt "report:sale.sale:"
+msgid "Unit Price"
+msgstr ""
+
+msgctxt "selection:account.invoice,sale_exception_state:"
+msgid "Ignored"
+msgstr ""
+
+msgctxt "selection:account.invoice,sale_exception_state:"
+msgid "Recreated"
+msgstr ""
+
+msgctxt "selection:sale.line,type:"
+msgid "Comment"
+msgstr ""
+
+msgctxt "selection:sale.line,type:"
+msgid "Line"
+msgstr ""
+
+msgctxt "selection:sale.line,type:"
+msgid "Subtotal"
+msgstr ""
+
+msgctxt "selection:sale.line,type:"
+msgid "Title"
+msgstr ""
+
+msgctxt "selection:sale.reporting.context,period:"
+msgid "Day"
+msgstr ""
+
+msgctxt "selection:sale.reporting.context,period:"
+msgid "Month"
+msgstr ""
+
+msgctxt "selection:sale.reporting.context,period:"
+msgid "Year"
+msgstr ""
+
+msgctxt "selection:sale.sale,invoice_method:"
+msgid "Manual"
+msgstr ""
+
+msgctxt "selection:sale.sale,invoice_method:"
+msgid "On Order Processed"
+msgstr ""
+
+msgctxt "selection:sale.sale,invoice_method:"
+msgid "On Shipment Sent"
+msgstr ""
+
+msgctxt "selection:sale.sale,invoice_state:"
+msgid "Exception"
+msgstr ""
+
+#, fuzzy
+msgctxt "selection:sale.sale,invoice_state:"
+msgid "None"
+msgstr "注释"
+
+msgctxt "selection:sale.sale,invoice_state:"
+msgid "Paid"
+msgstr ""
+
+msgctxt "selection:sale.sale,invoice_state:"
+msgid "Waiting"
+msgstr ""
+
+msgctxt "selection:sale.sale,shipment_method:"
+msgid "Manual"
+msgstr ""
+
+msgctxt "selection:sale.sale,shipment_method:"
+msgid "On Invoice Paid"
+msgstr ""
+
+msgctxt "selection:sale.sale,shipment_method:"
+msgid "On Order Processed"
+msgstr ""
+
+msgctxt "selection:sale.sale,shipment_state:"
+msgid "Exception"
+msgstr ""
+
+#, fuzzy
+msgctxt "selection:sale.sale,shipment_state:"
+msgid "None"
+msgstr "注释"
+
+msgctxt "selection:sale.sale,shipment_state:"
+msgid "Sent"
+msgstr ""
+
+msgctxt "selection:sale.sale,shipment_state:"
+msgid "Waiting"
+msgstr ""
+
+#, fuzzy
+msgctxt "selection:sale.sale,state:"
+msgid "Cancelled"
+msgstr "取消"
+
+#, fuzzy
+msgctxt "selection:sale.sale,state:"
+msgid "Confirmed"
+msgstr "Confirm"
+
+#, fuzzy
+msgctxt "selection:sale.sale,state:"
+msgid "Done"
+msgstr "完成"
+
+#, fuzzy
+msgctxt "selection:sale.sale,state:"
+msgid "Draft"
+msgstr "Draft"
+
+#, fuzzy
+msgctxt "selection:sale.sale,state:"
+msgid "Processing"
+msgstr "Processing"
+
+#, fuzzy
+msgctxt "selection:sale.sale,state:"
+msgid "Quotation"
+msgstr "Quotation"
+
+msgctxt "selection:stock.move,sale_exception_state:"
+msgid "Ignored"
+msgstr ""
+
+msgctxt "selection:stock.move,sale_exception_state:"
+msgid "Recreated"
+msgstr ""
+
+#, fuzzy
+msgctxt "view:party.party:"
+msgid "Sale"
+msgstr "Sales"
+
+msgctxt "view:product.template:"
+msgid "Customers"
+msgstr ""
+
+msgctxt "view:sale.handle.invoice.exception.ask:"
+msgid "Choose invoices to recreate:"
+msgstr ""
+
+msgctxt "view:sale.handle.shipment.exception.ask:"
+msgid "Choose move to recreate:"
+msgstr ""
+
+#, fuzzy
+msgctxt "view:sale.line:"
+msgid "General"
+msgstr "基本"
+
+#, fuzzy
+msgctxt "view:sale.line:"
+msgid "Notes"
+msgstr "注释"
+
+msgctxt "view:sale.line:"
+msgid "Taxes"
+msgstr ""
+
+msgctxt "view:sale.return_sale.start:"
+msgid "Are you sure to return these/this sale(s)?"
+msgstr ""
+
+msgctxt "view:sale.sale:"
+msgid "Other Info"
+msgstr ""
+
+#, fuzzy
+msgctxt "view:sale.sale:"
+msgid "Sale"
+msgstr "Sales"
+
+#, fuzzy
+msgctxt "wizard_button:sale.handle.invoice.exception,ask,end:"
+msgid "Cancel"
+msgstr "取消"
+
+#, fuzzy
+msgctxt "wizard_button:sale.handle.invoice.exception,ask,handle:"
+msgid "OK"
+msgstr "确定"
+
+#, fuzzy
+msgctxt "wizard_button:sale.handle.shipment.exception,ask,end:"
+msgid "Cancel"
+msgstr "取消"
+
+#, fuzzy
+msgctxt "wizard_button:sale.handle.shipment.exception,ask,handle:"
+msgid "OK"
+msgstr "确定"
+
+#, fuzzy
+msgctxt "wizard_button:sale.modify_header,start,end:"
+msgid "Cancel"
+msgstr "取消"
+
+msgctxt "wizard_button:sale.modify_header,start,modify:"
+msgid "Modify"
+msgstr ""
+
+#, fuzzy
+msgctxt "wizard_button:sale.return_sale,start,end:"
+msgid "Cancel"
+msgstr "取消"
+
+#, fuzzy
+msgctxt "wizard_button:sale.return_sale,start,return_:"
+msgid "Return"
+msgstr "Returns"
diff --git a/modules/sale/message.xml b/modules/sale/message.xml
new file mode 100644
index 0000000000..97da2872d1
--- /dev/null
+++ b/modules/sale/message.xml
@@ -0,0 +1,67 @@
+
+
+
+
+
+ You cannot erase party "%(party)s" while they have pending sales with company "%(company)s".
+
+
+ You cannot reset invoice "%(invoice)s" to draft because it was generated by a sale.
+
+
+ You cannot reset move "%(move)s" to draft because it was generated by a sale.
+
+
+ You cannot use together invoice "%(invoice_method)s" and shipment "%(shipment_method)s" on sale "%(sale)s".
+
+
+ To get a quote for sale "%(sale)s" you must enter an invoice address.
+
+
+ To get a quote for sale "%(sale)s" you must enter a shipment address.
+
+
+ To get a quote for sale "%(sale)s" you must enter a warehouse.
+
+
+ To delete sale "%(sale)s" you must cancel it.
+
+
+ To process sale "%(sale)s" you must set a customer location on party "%(party)s".
+
+
+ To invoice sale "%(sale)s" you must define an account revenue for product "%(product)s".
+
+
+ To invoice sale "%(sale)s" you must configure a default account revenue.
+
+
+ To delete line "%(line)s" you must cancel or reset to draft sale "%(sale)s".
+
+
+ To modify the header of sale "%(sale)s", it must be in "draft" state.
+
+
+ Company
+
+
+ #
+
+
+ Number of sales
+
+
+ Revenue
+
+
+ Revenue Trend
+
+
+ Currency
+
+
+ Currency Digits
+
+
+
diff --git a/modules/sale/party.py b/modules/sale/party.py
new file mode 100644
index 0000000000..4503778dd6
--- /dev/null
+++ b/modules/sale/party.py
@@ -0,0 +1,41 @@
+# This file is part of Tryton. The COPYRIGHT file at the top level of
+# this repository contains the full copyright notices and license terms.
+from trytond.i18n import gettext
+from trytond.pool import PoolMeta, Pool
+
+from trytond.modules.party.exceptions import EraseError
+
+
+class Replace(metaclass=PoolMeta):
+ __name__ = 'party.replace'
+
+ @classmethod
+ def fields_to_replace(cls):
+ return super().fields_to_replace() + [
+ ('sale.sale', 'party'),
+ ('sale.sale', 'invoice_party'),
+ ('sale.sale', 'shipment_party'),
+ ]
+
+
+class Erase(metaclass=PoolMeta):
+ __name__ = 'party.erase'
+
+ def check_erase_company(self, party, company):
+ pool = Pool()
+ Sale = pool.get('sale.sale')
+ super().check_erase_company(party, company)
+
+ sales = Sale.search([
+ ['OR',
+ ('party', '=', party.id),
+ ('shipment_party', '=', party.id),
+ ],
+ ('company', '=', company.id),
+ ('state', 'not in', ['done', 'cancelled']),
+ ])
+ if sales:
+ raise EraseError(
+ gettext('sale.msg_erase_party_pending_sale',
+ party=party.rec_name,
+ company=company.rec_name))
diff --git a/modules/sale/party.xml b/modules/sale/party.xml
new file mode 100644
index 0000000000..12d70909b0
--- /dev/null
+++ b/modules/sale/party.xml
@@ -0,0 +1,26 @@
+
+
+
+
+
+ Sales
+ sale.sale
+
+
+
+
+ form_relate
+ party.party,-1
+
+
+
+
+
+
+
+
diff --git a/modules/sale/product.py b/modules/sale/product.py
new file mode 100644
index 0000000000..e6f2ffd71c
--- /dev/null
+++ b/modules/sale/product.py
@@ -0,0 +1,236 @@
+# This file is part of Tryton. The COPYRIGHT file at the top level of
+# this repository contains the full copyright notices and license terms.
+import datetime
+
+from trytond.model import ModelSQL, ModelView, fields
+from trytond.pyson import Eval
+from trytond.pool import Pool, PoolMeta
+from trytond.transaction import Transaction
+from trytond.modules.company.model import CompanyValueMixin
+from trytond.modules.product import price_digits
+
+
+class Configuration(metaclass=PoolMeta):
+ __name__ = 'product.configuration'
+
+ default_lead_time = fields.MultiValue(
+ fields.TimeDelta(
+ "Default Lead Time",
+ help="The time from confirming the sales order to sending the "
+ "products.\n"
+ "Used for products without a lead time."))
+
+ @classmethod
+ def default_default_lead_time(cls, **pattern):
+ return datetime.timedelta(0)
+
+
+class DefaultLeadTime(ModelSQL, CompanyValueMixin):
+ "Product Default Lead Time"
+ __name__ = 'product.configuration.default_lead_time'
+ default_lead_time = fields.TimeDelta("Default Lead Time")
+
+
+class Template(metaclass=PoolMeta):
+ __name__ = 'product.template'
+ salable = fields.Boolean("Salable")
+ sale_uom = fields.Many2One(
+ 'product.uom', "Sale UOM",
+ states={
+ 'invisible': ~Eval('salable', False),
+ 'required': Eval('salable', False),
+ },
+ domain=[
+ ('category', '=', Eval('default_uom_category')),
+ ],
+ depends=['salable', 'default_uom_category'])
+ lead_time = fields.TimeDelta(
+ "Lead Time",
+ states={
+ 'invisible': ~Eval('salable', False),
+ },
+ depends=['salable'],
+ help="The time from confirming the sales order to sending the "
+ "products.\n"
+ "If empty the default lead time from the configuration is used.")
+
+ @classmethod
+ def __register__(cls, module_name):
+ transaction = Transaction()
+ cursor = transaction.connection.cursor()
+ update = transaction.connection.cursor()
+ table = cls.__table_handler__(module_name)
+ sql_table = cls.__table__()
+
+ super(Template, cls).__register__(module_name)
+
+ # Migration from 3.8: change delivery_time into timedelta lead_time
+ if table.column_exist('delivery_time'):
+ cursor.execute(*sql_table.select(
+ sql_table.id, sql_table.delivery_time))
+ for id_, delivery_time in cursor:
+ if delivery_time is None:
+ continue
+ lead_time = datetime.timedelta(days=delivery_time)
+ update.execute(*sql_table.update(
+ [sql_table.lead_time],
+ [lead_time],
+ where=sql_table.id == id_))
+ table.drop_column('delivery_time')
+
+ @fields.depends('default_uom', 'sale_uom', 'salable')
+ def on_change_default_uom(self):
+ try:
+ super(Template, self).on_change_default_uom()
+ except AttributeError:
+ pass
+ if self.default_uom:
+ if self.sale_uom:
+ if self.default_uom.category != self.sale_uom.category:
+ self.sale_uom = self.default_uom
+ else:
+ self.sale_uom = self.default_uom
+
+ @classmethod
+ def view_attributes(cls):
+ return super(Template, cls).view_attributes() + [
+ ('//page[@id="customers"]', 'states', {
+ 'invisible': ~Eval('salable'),
+ })]
+
+
+class Product(metaclass=PoolMeta):
+ __name__ = 'product.product'
+
+ sale_price_uom = fields.Function(fields.Numeric(
+ "Sale Price", digits=price_digits), 'get_sale_price_uom')
+
+ @classmethod
+ def get_sale_price_uom(cls, products, name):
+ quantity = Transaction().context.get('quantity') or 0
+ return cls.get_sale_price(products, quantity=quantity)
+
+ def _get_sale_unit_price(self, quantity=0):
+ return self.list_price_used
+
+ @classmethod
+ def get_sale_price(cls, products, quantity=0):
+ '''
+ Return the sale price for products and quantity.
+ It uses if exists from the context:
+ uom: the unit of measure or the sale uom of the product
+ currency: the currency id for the returned price
+ '''
+ pool = Pool()
+ Uom = pool.get('product.uom')
+ User = pool.get('res.user')
+ Currency = pool.get('currency.currency')
+ Date = pool.get('ir.date')
+
+ today = Date.today()
+ prices = {}
+
+ assert len(products) == len(set(products)), "Duplicate products"
+
+ uom = None
+ if Transaction().context.get('uom'):
+ uom = Uom(Transaction().context.get('uom'))
+
+ currency = None
+ if Transaction().context.get('currency'):
+ currency = Currency(Transaction().context.get('currency'))
+
+ user = User(Transaction().user)
+
+ for product in products:
+ prices[product.id] = product._get_sale_unit_price(
+ quantity=quantity)
+ if uom and product.default_uom.category == uom.category:
+ prices[product.id] = Uom.compute_price(
+ product.default_uom, prices[product.id], uom)
+ else:
+ prices[product.id] = Uom.compute_price(
+ product.default_uom, prices[product.id], product.sale_uom)
+ if currency and user.company:
+ if user.company.currency != currency:
+ date = Transaction().context.get('sale_date') or today
+ with Transaction().set_context(date=date):
+ prices[product.id] = Currency.compute(
+ user.company.currency, prices[product.id],
+ currency, round=False)
+ return prices
+
+ @property
+ def lead_time_used(self):
+ pool = Pool()
+ Configuration = pool.get('product.configuration')
+ if self.lead_time is None:
+ with Transaction().set_context(self._context):
+ config = Configuration(1)
+ return config.get_multivalue('default_lead_time')
+ else:
+ return self.lead_time
+
+ def compute_shipping_date(self, date=None):
+ '''
+ Compute the shipping date at the given date
+ '''
+ Date = Pool().get('ir.date')
+
+ if not date:
+ date = Date.today()
+
+ lead_time = self.lead_time_used
+ if lead_time is None:
+ return datetime.date.max
+ return date + lead_time
+
+
+class SaleContext(ModelView):
+ "Product Sale Context"
+ __name__ = 'product.sale.context'
+
+ locations = fields.Many2Many(
+ 'stock.location', None, None, "Warehouses",
+ domain=[('type', '=', 'warehouse')])
+ company = fields.Many2One('company.company', "Company")
+ currency = fields.Many2One('currency.currency', "Currency")
+ customer = fields.Many2One(
+ 'party.party', "Customer",
+ context={
+ 'company': Eval('company', -1),
+ },
+ depends=['company'])
+ sale_date = fields.Date("Sale Date")
+ quantity = fields.Float("Quantity")
+
+ stock_date_end = fields.Function(
+ fields.Date("Stock End Date"),
+ 'on_change_with_stock_date_end')
+
+ @classmethod
+ def default_locations(cls):
+ pool = Pool()
+ Location = pool.get('stock.location')
+ locations = []
+ warehouse = Location.get_default_warehouse()
+ if warehouse:
+ locations.append(warehouse)
+ return locations
+
+ @classmethod
+ def default_company(cls):
+ return Transaction().context.get('company')
+
+ @classmethod
+ def default_currency(cls):
+ pool = Pool()
+ Company = pool.get('company.company')
+ company_id = cls.default_company()
+ if company_id:
+ company = Company(company_id)
+ return company.currency.id
+
+ @fields.depends('sale_date')
+ def on_change_with_stock_date_end(self, name=None):
+ return self.sale_date
diff --git a/modules/sale/product.xml b/modules/sale/product.xml
new file mode 100644
index 0000000000..26a2e5d77b
--- /dev/null
+++ b/modules/sale/product.xml
@@ -0,0 +1,48 @@
+
+
+
+
+
+ product.product
+ tree
+
+ product_list_sale_line
+
+
+
+ Products
+ product.product
+
+ product.sale.context
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ product.sale.context
+ form
+ product_sale_context_form
+
+
+
+ product.configuration
+
+ product_configuration_form
+
+
+
diff --git a/modules/sale/sale.fodt b/modules/sale/sale.fodt
new file mode 100644
index 0000000000..17cb9aa547
--- /dev/null
+++ b/modules/sale/sale.fodt
@@ -0,0 +1,801 @@
+
+
+
+ LibreOffice/6.4.6.2$Linux_X86_64 LibreOffice_project/40$Build-22008-06-07T15:28:222009-01-10T16:03:331PT0S
+
+
+ 24977
+ 0
+ 26301
+ 24026
+ true
+ false
+
+
+ view2
+ 4355
+ 33754
+ 0
+ 24977
+ 26300
+ 49001
+ 0
+ 0
+ false
+ 100
+ false
+ false
+
+
+
+
+ false
+ true
+ true
+ true
+ 0
+ true
+ true
+
+ false
+ false
+ false
+ false
+ false
+ false
+ false
+ false
+ true
+ true
+ true
+ false
+ false
+ false
+ false
+ false
+ false
+ false
+ false
+ false
+ true
+ false
+ true
+ true
+ 204959
+ false
+
+ false
+ true
+ false
+ false
+ false
+ true
+ false
+ false
+ false
+ true
+ 1744494
+
+ true
+ false
+ true
+ false
+ false
+ true
+ true
+ false
+ true
+ false
+ false
+ false
+ 0
+ false
+ true
+ high-resolution
+ false
+ false
+ false
+ false
+ false
+ false
+ true
+ true
+ true
+
+ true
+ false
+ false
+ true
+ false
+ false
+ false
+
+ false
+ false
+ false
+ 1
+ true
+ false
+ false
+ 0
+ false
+ false
+
+
+ false
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ <if test="company and company.header">
+ <for each="line in company.header.split('\n')">
+ <line>
+ </for>
+ </if>
+ <company.rec_name if company else ''>
+
+
+ <if test="company and company.footer">
+ <for each="line in company.footer.split('\n')">
+ <line>
+ </for>
+ </if>
+
+
+
+
+
+
+
+
+
+
+
+
+
+ <for each="sale in records">
+
+ <replace text:p="set_lang(sale.party.lang)">
+ <replace text:p="sale.set_lang(sale.party.lang)">
+ <for each="line in sale.report_address.splitlines()">
+ <line>
+ </for>
+ <if test="sale.party.tax_identifier">
+ <sale.party.tax_identifier.type_string>: <sale.party.tax_identifier.code>
+ </if>
+ <choose test="">
+ <when test="sale.state == 'draft'">
+ Draft Sale Order
+ </when>
+ <when test="sale.state == 'quotation'">
+ Quotation N°: <sale.full_number>
+ </when>
+ <otherwise test="">
+ Sale Order N°: <sale.full_number>
+ </otherwise>
+ </choose>
+ Description: <sale.description or ''>
+ Reference: <sale.reference or ''>
+ Date: <format_date(sale.sale_date or today, sale.party.lang)>
+
+
+
+
+
+
+ Description
+
+
+ Quantity
+
+
+ Unit Price
+
+
+ Taxes
+
+
+ Amount
+
+
+
+
+
+ <for each="line in sale.lines">
+
+
+
+
+
+
+
+
+ <choose test="">
+
+
+
+
+
+
+
+
+ <when test="line.type == 'line'">
+
+
+
+
+
+
+
+
+ <if test="line.product">
+ <line.product.rec_name>
+ </if>
+ <if test="line.description">
+ <for each="description in line.description.split('\n')">
+ <description>
+ </for>
+ </if>
+
+
+ <(format_number(line.quantity, sale.party.lang, digits=line.unit_digits) + (line.unit and (' ' + line.unit.symbol) or '')) or ''>
+
+
+ <format_currency(line.unit_price, sale.party.lang, sale.currency, digits=line.__class__.unit_price.digits[1])>
+
+
+ <for each="tax in line.taxes">
+ <tax.description>
+ </for>
+
+
+ <format_currency(line.amount, sale.party.lang, sale.currency)>
+
+
+
+
+ </when>
+
+
+
+
+
+
+
+
+ <when test="line.type == 'subtotal'">
+
+
+
+
+
+
+
+
+ <for each="description in (line.description or '').split('\n')">
+ <description>
+ </for>
+
+
+
+
+
+ <format_currency(line.amount, sale.party.lang, sale.currency)>
+
+
+
+
+ </when>
+
+
+
+
+
+
+
+
+ <when test="line.type == 'title'">
+
+
+
+
+
+
+
+
+ <for each="description in (line.description or '').split('\n')">
+ <description>
+ </for>
+
+
+
+
+
+
+
+
+ </when>
+
+
+
+
+
+
+
+
+ <otherwise test="">
+
+
+
+
+
+
+
+
+ <for each="description in (line.description or '').split('\n')">
+ <description>
+ </for>
+
+
+
+
+
+
+
+
+ </otherwise>
+
+
+
+
+
+
+
+
+ </choose>
+
+
+
+
+
+
+
+
+ </for>
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Total (excl. taxes):
+
+
+ <format_currency(sale.untaxed_amount, sale.party.lang, sale.currency)>
+
+
+
+
+ Taxes:
+
+
+ <format_currency(sale.tax_amount, sale.party.lang, sale.currency)>
+
+
+
+
+ Total:
+
+
+ <format_currency(sale.total_amount, sale.party.lang, sale.currency)>
+
+
+
+
+
+
+
+ <for each="comment in (sale.comment or '').split('\n')">
+ <comment>
+ </for>
+ </for>
+
+
+
diff --git a/modules/sale/sale.py b/modules/sale/sale.py
new file mode 100644
index 0000000000..238daee9ed
--- /dev/null
+++ b/modules/sale/sale.py
@@ -0,0 +1,2025 @@
+# This file is part of Tryton. The COPYRIGHT file at the top level of
+# this repository contains the full copyright notices and license terms.
+import datetime
+from decimal import Decimal
+from itertools import groupby, chain
+from functools import partial
+
+from trytond.i18n import gettext
+from trytond.model import Workflow, Model, ModelView, ModelSQL, fields, \
+ sequence_ordered
+from trytond.model.exceptions import AccessError
+from trytond.modules.company import CompanyReport
+from trytond.wizard import Wizard, StateAction, StateView, StateTransition, \
+ Button
+from trytond.pyson import If, Eval, Bool, PYSONEncoder
+from trytond.transaction import Transaction
+from trytond.tools import sortable_values, firstline
+from trytond.pool import Pool
+
+from trytond.ir.attachment import AttachmentCopyMixin
+from trytond.ir.note import NoteCopyMixin
+from trytond.modules.account.tax import TaxableMixin
+from trytond.modules.account_product.exceptions import AccountError
+from trytond.modules.company.model import (
+ employee_field, set_employee, reset_employee)
+from trytond.modules.product import price_digits, round_price
+
+from .exceptions import (
+ SaleValidationError, SaleQuotationError, PartyLocationError)
+
+
+def get_shipments_returns(model_name):
+ "Computes the returns or shipments"
+ def method(self, name):
+ Model = Pool().get(model_name)
+ shipments = set()
+ for line in self.lines:
+ for move in line.moves:
+ if isinstance(move.shipment, Model):
+ shipments.add(move.shipment.id)
+ return list(shipments)
+ return method
+
+
+def search_shipments_returns(model_name):
+ "Search on shipments or returns"
+ def method(self, name, clause):
+ nested = clause[0].lstrip(name)
+ if nested:
+ return [('lines.moves.shipment' + nested,)
+ + tuple(clause[1:3]) + (model_name,) + tuple(clause[3:])]
+ else:
+ if isinstance(clause[2], str):
+ target = 'rec_name'
+ else:
+ target = 'id'
+ return [('lines.moves.shipment.' + target,)
+ + tuple(clause[1:3]) + (model_name,)]
+ return classmethod(method)
+
+
+class Sale(
+ Workflow, ModelSQL, ModelView, TaxableMixin,
+ AttachmentCopyMixin, NoteCopyMixin):
+ 'Sale'
+ __name__ = 'sale.sale'
+ _rec_name = 'number'
+ company = fields.Many2One(
+ 'company.company', 'Company', required=True, select=True,
+ states={
+ 'readonly': (
+ (Eval('state') != 'draft')
+ | Eval('lines', [0])
+ | Eval('party', True)
+ | Eval('invoice_party', True)
+ | Eval('shipment_party', True)),
+ },
+ depends=['state'])
+ number = fields.Char('Number', readonly=True, select=True)
+ reference = fields.Char('Reference', select=True)
+ description = fields.Char('Description',
+ states={
+ 'readonly': Eval('state') != 'draft',
+ },
+ depends=['state'])
+ sale_date = fields.Date('Sale Date',
+ states={
+ 'readonly': ~Eval('state').in_(['draft', 'quotation']),
+ 'required': ~Eval('state').in_(
+ ['draft', 'quotation', 'cancelled']),
+ },
+ depends=['state'])
+ payment_term = fields.Many2One('account.invoice.payment_term',
+ 'Payment Term',
+ states={
+ 'readonly': Eval('state') != 'draft',
+ },
+ depends=['state'])
+ party = fields.Many2One('party.party', 'Party', required=True, select=True,
+ states={
+ 'readonly': ((Eval('state') != 'draft')
+ | (Eval('lines', [0]) & Eval('party'))),
+ },
+ context={
+ 'company': Eval('company', -1),
+ },
+ depends=['state', 'company'])
+ party_lang = fields.Function(fields.Char('Party Language'),
+ 'on_change_with_party_lang')
+ contact = fields.Many2One(
+ 'party.contact_mechanism', "Contact",
+ context={
+ 'company': Eval('company', -1),
+ },
+ search_context={
+ 'related_party': Eval('party'),
+ },
+ depends=['party', 'company'])
+ invoice_party = fields.Many2One('party.party', "Invoice Party",
+ states={
+ 'readonly': ((Eval('state') != 'draft')
+ | Eval('lines', [0])),
+ },
+ context={
+ 'company': Eval('company', -1),
+ },
+ search_context={
+ 'related_party': Eval('party'),
+ },
+ depends=['state', 'party', 'company'])
+ invoice_address = fields.Many2One('party.address', 'Invoice Address',
+ domain=[
+ ('party', '=', If(Bool(Eval('invoice_party')),
+ Eval('invoice_party'), Eval('party'))),
+ ],
+ states={
+ 'readonly': Eval('state') != 'draft',
+ 'required': ~Eval('state').in_(
+ ['draft', 'quotation', 'cancelled']),
+ }, depends=['party', 'invoice_party', 'state'])
+ shipment_party = fields.Many2One('party.party', 'Shipment Party',
+ states={
+ 'readonly': (Eval('state') != 'draft'),
+ },
+ context={
+ 'company': Eval('company', -1),
+ },
+ search_context={
+ 'related_party': Eval('party'),
+ },
+ depends=['state', 'party', 'company'])
+ shipment_address = fields.Many2One('party.address', 'Shipment Address',
+ domain=[
+ ('party', '=', If(Bool(Eval('shipment_party')),
+ Eval('shipment_party'), Eval('party'))),
+ ],
+ states={
+ 'readonly': Eval('state') != 'draft',
+ 'required': ~Eval('state').in_(
+ ['draft', 'quotation', 'cancelled']),
+ },
+ depends=['party', 'shipment_party', 'state'])
+ warehouse = fields.Many2One('stock.location', 'Warehouse',
+ domain=[('type', '=', 'warehouse')], states={
+ 'readonly': Eval('state') != 'draft',
+ },
+ depends=['state'])
+ currency = fields.Many2One('currency.currency', 'Currency', required=True,
+ states={
+ 'readonly': ((Eval('state') != 'draft')
+ | (Eval('lines', [0]) & Eval('currency', 0))),
+ },
+ depends=['state'])
+ currency_digits = fields.Function(fields.Integer('Currency Digits'),
+ 'on_change_with_currency_digits')
+ lines = fields.One2Many('sale.line', 'sale', 'Lines', states={
+ 'readonly': Eval('state') != 'draft',
+ },
+ depends=['party', 'state'])
+ comment = fields.Text('Comment')
+ untaxed_amount = fields.Function(fields.Numeric('Untaxed',
+ digits=(16, Eval('currency_digits', 2)),
+ depends=['currency_digits']), 'get_amount')
+ untaxed_amount_cache = fields.Numeric('Untaxed Cache',
+ digits=(16, Eval('currency_digits', 2)),
+ readonly=True,
+ depends=['currency_digits'])
+ tax_amount = fields.Function(fields.Numeric('Tax',
+ digits=(16, Eval('currency_digits', 2)),
+ depends=['currency_digits']), 'get_amount')
+ tax_amount_cache = fields.Numeric('Tax Cache',
+ digits=(16, Eval('currency_digits', 2)),
+ readonly=True,
+ depends=['currency_digits'])
+ total_amount = fields.Function(fields.Numeric('Total',
+ digits=(16, Eval('currency_digits', 2)),
+ depends=['currency_digits']), 'get_amount')
+ total_amount_cache = fields.Numeric('Total Cache',
+ digits=(16, Eval('currency_digits', 2)),
+ readonly=True,
+ depends=['currency_digits'])
+ invoice_method = fields.Selection([
+ ('manual', 'Manual'),
+ ('order', 'On Order Processed'),
+ ('shipment', 'On Shipment Sent'),
+ ],
+ 'Invoice Method', required=True, states={
+ 'readonly': Eval('state') != 'draft',
+ },
+ depends=['state'])
+ invoice_method_string = invoice_method.translated('invoice_method')
+ invoice_state = fields.Selection([
+ ('none', 'None'),
+ ('waiting', 'Waiting'),
+ ('paid', 'Paid'),
+ ('exception', 'Exception'),
+ ], 'Invoice State', readonly=True, required=True)
+ invoices = fields.Function(fields.Many2Many(
+ 'account.invoice', None, None, "Invoices"),
+ 'get_invoices', searcher='search_invoices')
+ invoices_ignored = fields.Many2Many('sale.sale-ignored-account.invoice',
+ 'sale', 'invoice', 'Ignored Invoices', readonly=True)
+ invoices_recreated = fields.Many2Many(
+ 'sale.sale-recreated-account.invoice', 'sale', 'invoice',
+ 'Recreated Invoices', readonly=True)
+ shipment_method = fields.Selection([
+ ('manual', 'Manual'),
+ ('order', 'On Order Processed'),
+ ('invoice', 'On Invoice Paid'),
+ ], 'Shipment Method', required=True,
+ states={
+ 'readonly': Eval('state') != 'draft',
+ },
+ depends=['state'])
+ shipment_method_string = shipment_method.translated('shipment_method')
+ shipment_state = fields.Selection([
+ ('none', 'None'),
+ ('waiting', 'Waiting'),
+ ('sent', 'Sent'),
+ ('exception', 'Exception'),
+ ], 'Shipment State', readonly=True, required=True)
+ shipments = fields.Function(fields.Many2Many(
+ 'stock.shipment.out', None, None, "Shipments"),
+ 'get_shipments', searcher='search_shipments')
+ shipment_returns = fields.Function(fields.Many2Many(
+ 'stock.shipment.out.return', None, None, "Shipment Returns"),
+ 'get_shipment_returns', searcher='search_shipment_returns')
+ moves = fields.One2Many('stock.move', 'sale', 'Moves', readonly=True)
+ origin = fields.Reference('Origin', selection='get_origin', select=True,
+ states={
+ 'readonly': Eval('state') != 'draft',
+ },
+ depends=['state'])
+ shipping_date = fields.Date(
+ "Shipping Date",
+ domain=[If(Bool(Eval('sale_date')) & Bool(Eval('shipping_date')),
+ ('shipping_date', '>=', Eval('sale_date')),
+ ()),
+ ],
+ states={
+ 'readonly': Eval('state').in_(['processing', 'done', 'cancelled']),
+ },
+ depends=['state', 'sale_date'],
+ help="When the shipping of goods should start.")
+
+ quoted_by = employee_field(
+ "Quoted By",
+ states=['quotation', 'confirmed', 'processing', 'done', 'cancelled'])
+ confirmed_by = employee_field(
+ "Confirmed By",
+ states=['confirmed', 'processing', 'done', 'cancelled'])
+ state = fields.Selection([
+ ('draft', "Draft"),
+ ('quotation', "Quotation"),
+ ('confirmed', "Confirmed"),
+ ('processing', "Processing"),
+ ('done', "Done"),
+ ('cancelled', "Cancelled"),
+ ], "State", readonly=True, required=True)
+ state_string = state.translated('state')
+
+ @classmethod
+ def __setup__(cls):
+ super(Sale, cls).__setup__()
+ cls.create_date.select = True
+ cls._order = [
+ ('sale_date', 'DESC NULLS FIRST'),
+ ('id', 'DESC'),
+ ]
+ cls._transitions |= set((
+ ('draft', 'quotation'),
+ ('quotation', 'confirmed'),
+ ('confirmed', 'processing'),
+ ('confirmed', 'draft'),
+ ('processing', 'processing'),
+ ('processing', 'done'),
+ ('done', 'processing'),
+ ('draft', 'cancelled'),
+ ('quotation', 'cancelled'),
+ ('quotation', 'draft'),
+ ('cancelled', 'draft'),
+ ))
+ cls._buttons.update({
+ 'cancel': {
+ 'invisible': ~Eval('state').in_(['draft', 'quotation']),
+ 'depends': ['state'],
+ },
+ 'draft': {
+ 'invisible': ~Eval('state').in_(
+ ['cancelled', 'quotation', 'confirmed']),
+ 'icon': If(Eval('state') == 'cancelled',
+ 'tryton-undo',
+ 'tryton-back'),
+ 'depends': ['state'],
+ },
+ 'quote': {
+ 'invisible': Eval('state') != 'draft',
+ 'readonly': ~Eval('lines', Eval('untaxed_amount', 0)),
+ 'depends': ['state'],
+ },
+ 'confirm': {
+ 'invisible': Eval('state') != 'quotation',
+ 'depends': ['state'],
+ },
+ 'process': {
+ 'invisible': ~Eval('state').in_(
+ ['confirmed', 'processing']),
+ 'icon': If(Eval('state') == 'confirmed',
+ 'tryton-forward', 'tryton-refresh'),
+ 'depends': ['state'],
+ },
+ 'handle_invoice_exception': {
+ 'invisible': ((Eval('invoice_state') != 'exception')
+ | (Eval('state') == 'cancelled')),
+ 'depends': ['state', 'invoice_state'],
+ },
+ 'handle_shipment_exception': {
+ 'invisible': ((Eval('shipment_state') != 'exception')
+ | (Eval('state') == 'cancelled')),
+ 'depends': ['state', 'shipment_state'],
+ },
+ 'modify_header': {
+ 'invisible': ((Eval('state') != 'draft')
+ | ~Eval('lines', [-1])),
+ 'depends': ['state'],
+ },
+ })
+ # The states where amounts are cached
+ cls._states_cached = ['confirmed', 'processing', 'done', 'cancelled']
+
+ @classmethod
+ def __register__(cls, module_name):
+ cursor = Transaction().connection.cursor()
+ table = cls.__table_handler__(module_name)
+ sql_table = cls.__table__()
+
+ # Migration from 3.8: rename reference into number
+ if (table.column_exist('reference')
+ and not table.column_exist('number')):
+ table.column_rename('reference', 'number')
+
+ super(Sale, cls).__register__(module_name)
+ table = cls.__table_handler__(module_name)
+
+ # Migration from 4.0: Drop not null on payment_term
+ table.not_null_action('payment_term', 'remove')
+
+ # Migration from 5.6: rename state cancel to cancelled
+ cursor.execute(*sql_table.update(
+ [sql_table.state], ['cancelled'],
+ where=sql_table.state == 'cancel'))
+
+ @classmethod
+ def default_payment_term(cls, **pattern):
+ pool = Pool()
+ Configuration = pool.get('account.configuration')
+ config = Configuration(1)
+ payment_term = config.get_multivalue(
+ 'default_customer_payment_term', **pattern)
+ return payment_term.id if payment_term else None
+
+ @classmethod
+ def default_warehouse(cls):
+ Location = Pool().get('stock.location')
+ return Location.get_default_warehouse()
+
+ @staticmethod
+ def default_company():
+ return Transaction().context.get('company')
+
+ @fields.depends('company')
+ def on_change_company(self):
+ self.payment_term = self.default_payment_term(
+ company=self.company.id if self.company else None)
+ self.invoice_method = self.default_invoice_method(
+ company=self.company.id if self.company else None)
+ self.shipment_method = self.default_shipment_method(
+ company=self.company.id if self.company else None)
+
+ @staticmethod
+ def default_state():
+ return 'draft'
+
+ @staticmethod
+ def default_currency():
+ Company = Pool().get('company.company')
+ company = Transaction().context.get('company')
+ if company:
+ return Company(company).currency.id
+
+ @staticmethod
+ def default_currency_digits():
+ Company = Pool().get('company.company')
+ company = Transaction().context.get('company')
+ if company:
+ return Company(company).currency.digits
+ return 2
+
+ @classmethod
+ def default_invoice_method(cls, **pattern):
+ Config = Pool().get('sale.configuration')
+ config = Config(1)
+ return config.get_multivalue('sale_invoice_method', **pattern)
+
+ @staticmethod
+ def default_invoice_state():
+ return 'none'
+
+ @classmethod
+ def default_shipment_method(cls, **pattern):
+ Config = Pool().get('sale.configuration')
+ config = Config(1)
+ return config.get_multivalue('sale_shipment_method', **pattern)
+
+ @staticmethod
+ def default_shipment_state():
+ return 'none'
+
+ @fields.depends('party', 'invoice_party', 'shipment_party', 'payment_term')
+ def on_change_party(self):
+ if not self.invoice_party:
+ self.invoice_address = None
+ if not self.shipment_party:
+ self.shipment_address = None
+ self.payment_term = self.default_payment_term()
+ if self.party:
+ if not self.invoice_party:
+ self.invoice_address = self.party.address_get(type='invoice')
+ if not self.shipment_party:
+ self.shipment_address = self.party.address_get(type='delivery')
+ if self.party.customer_payment_term:
+ self.payment_term = self.party.customer_payment_term
+
+ @fields.depends('party', 'invoice_party')
+ def on_change_invoice_party(self):
+ if self.invoice_party:
+ self.invoice_address = self.invoice_party.address_get(
+ type='invoice')
+ elif self.party:
+ self.invoice_address = self.party.address_get(type='invoice')
+
+ @fields.depends('party', 'shipment_party')
+ def on_change_shipment_party(self):
+ if self.shipment_party:
+ self.shipment_address = self.shipment_party.address_get(
+ type='delivery')
+ elif self.party:
+ self.shipment_address = self.party.address_get(type='delivery')
+
+ @fields.depends('currency')
+ def on_change_with_currency_digits(self, name=None):
+ if self.currency:
+ return self.currency.digits
+ return 2
+
+ @fields.depends('party', 'company')
+ def _get_tax_context(self):
+ context = {}
+ if self.party and self.party.lang:
+ context['language'] = self.party.lang.code
+ if self.company:
+ context['company'] = self.company.id
+ return context
+
+ @fields.depends('party')
+ def on_change_with_party_lang(self, name=None):
+ Config = Pool().get('ir.configuration')
+ if self.party and self.party.lang:
+ return self.party.lang.code
+ return Config.get_language()
+
+ @fields.depends('lines', 'currency', methods=['get_tax_amount'])
+ def on_change_lines(self):
+ self.untaxed_amount = Decimal('0.0')
+ self.tax_amount = Decimal('0.0')
+ self.total_amount = Decimal('0.0')
+
+ if self.lines:
+ for line in self.lines:
+ self.untaxed_amount += getattr(line, 'amount', None) or 0
+ self.tax_amount = self.get_tax_amount()
+ if self.currency:
+ self.untaxed_amount = self.currency.round(self.untaxed_amount)
+ self.tax_amount = self.currency.round(self.tax_amount)
+ self.total_amount = self.untaxed_amount + self.tax_amount
+ if self.currency:
+ self.total_amount = self.currency.round(self.total_amount)
+
+ @property
+ def taxable_lines(self):
+ taxable_lines = []
+ for line in self.lines:
+ taxable_lines.extend(line.taxable_lines)
+ return taxable_lines
+
+ @fields.depends(methods=['_get_taxes'])
+ def get_tax_amount(self):
+ return sum(
+ (v['amount'] for v in self._get_taxes().values()), Decimal(0))
+
+ @classmethod
+ def get_amount(cls, sales, names):
+ untaxed_amount = {}
+ tax_amount = {}
+ total_amount = {}
+
+ if {'tax_amount', 'total_amount'} & set(names):
+ compute_taxes = True
+ else:
+ compute_taxes = False
+ # Sort cached first and re-instanciate to optimize cache management
+ sales = sorted(sales, key=lambda s: s.state in cls._states_cached,
+ reverse=True)
+ sales = cls.browse(sales)
+ for sale in sales:
+ if (sale.state in cls._states_cached
+ and sale.untaxed_amount_cache is not None
+ and sale.tax_amount_cache is not None
+ and sale.total_amount_cache is not None):
+ untaxed_amount[sale.id] = sale.untaxed_amount_cache
+ if compute_taxes:
+ tax_amount[sale.id] = sale.tax_amount_cache
+ total_amount[sale.id] = sale.total_amount_cache
+ else:
+ untaxed_amount[sale.id] = sum(
+ (line.amount for line in sale.lines
+ if line.type == 'line'), Decimal(0))
+ if compute_taxes:
+ tax_amount[sale.id] = sale.get_tax_amount()
+ total_amount[sale.id] = (
+ untaxed_amount[sale.id] + tax_amount[sale.id])
+
+ result = {
+ 'untaxed_amount': untaxed_amount,
+ 'tax_amount': tax_amount,
+ 'total_amount': total_amount,
+ }
+ for key in list(result.keys()):
+ if key not in names:
+ del result[key]
+ return result
+
+ def get_invoices(self, name):
+ invoices = set()
+ for line in self.lines:
+ for invoice_line in line.invoice_lines:
+ if invoice_line.invoice:
+ invoices.add(invoice_line.invoice.id)
+ return list(invoices)
+
+ @classmethod
+ def search_invoices(cls, name, clause):
+ return [('lines.invoice_lines.invoice' + clause[0].lstrip(name),)
+ + tuple(clause[1:])]
+
+ def get_invoice_state(self):
+ '''
+ Return the invoice state for the sale.
+ '''
+ skip_ids = set(x.id for x in self.invoices_ignored)
+ skip_ids.update(x.id for x in self.invoices_recreated)
+ invoices = [i for i in self.invoices if i.id not in skip_ids]
+ if invoices:
+ if any(i.state == 'cancelled' for i in invoices):
+ return 'exception'
+ elif all(i.state == 'paid' for i in invoices):
+ return 'paid'
+ else:
+ return 'waiting'
+ return 'none'
+
+ def set_invoice_state(self):
+ '''
+ Set the invoice state.
+ '''
+ state = self.get_invoice_state()
+ if self.invoice_state != state:
+ self.write([self], {
+ 'invoice_state': state,
+ })
+
+ get_shipments = get_shipments_returns('stock.shipment.out')
+ get_shipment_returns = get_shipments_returns('stock.shipment.out.return')
+
+ search_shipments = search_shipments_returns('stock.shipment.out')
+ search_shipment_returns = search_shipments_returns(
+ 'stock.shipment.out.return')
+
+ def get_shipment_state(self):
+ '''
+ Return the shipment state for the sale.
+ '''
+ if self.moves:
+ if any(l.move_exception for l in self.lines):
+ return 'exception'
+ elif all(l.move_done for l in self.lines):
+ return 'sent'
+ else:
+ return 'waiting'
+ return 'none'
+
+ def set_shipment_state(self):
+ '''
+ Set the shipment state.
+ '''
+ state = self.get_shipment_state()
+ if self.shipment_state != state:
+ self.write([self], {
+ 'shipment_state': state,
+ })
+
+ @classmethod
+ def _get_origin(cls):
+ 'Return list of Model names for origin Reference'
+ return ['sale.sale']
+
+ @classmethod
+ def get_origin(cls):
+ Model = Pool().get('ir.model')
+ get_name = Model.get_name
+ models = cls._get_origin()
+ return [(None, '')] + [(m, get_name(m)) for m in models]
+
+ @property
+ def report_address(self):
+ if self.invoice_address:
+ return self.invoice_address.full_address
+ else:
+ return ''
+
+ @classmethod
+ def validate(cls, sales):
+ super(Sale, cls).validate(sales)
+ for sale in sales:
+ sale.check_method()
+
+ def check_method(self):
+ '''
+ Check the methods.
+ '''
+ if (self.invoice_method == 'shipment'
+ and self.shipment_method in ('invoice', 'manual')):
+ raise SaleValidationError(
+ gettext('sale.msg_sale_invalid_method',
+ invoice_method=self.invoice_method_string,
+ shipment_method=self.shipment_method_string,
+ sale=self.rec_name))
+ if (self.shipment_method == 'invoice'
+ and self.invoice_method in ('shipment', 'manual')):
+ raise SaleValidationError(
+ gettext('sale.msg_sale_invalid_method',
+ invoice_method=self.invoice_method_string,
+ shipment_method=self.shipment_method_string,
+ sale=self.rec_name))
+
+ @property
+ def full_number(self):
+ return self.number
+
+ def get_rec_name(self, name):
+ items = []
+ if self.full_number:
+ items.append(self.full_number)
+ if self.reference:
+ items.append('[%s]' % self.reference)
+ if not items:
+ items.append('(%s)' % self.id)
+ return ' '.join(items)
+
+ @classmethod
+ def search_rec_name(cls, name, clause):
+ _, operator, value = clause
+ if operator.startswith('!') or operator.startswith('not '):
+ bool_op = 'AND'
+ else:
+ bool_op = 'OR'
+ domain = [bool_op,
+ ('number', operator, value),
+ ('reference', operator, value),
+ ]
+ return domain
+
+ @classmethod
+ def view_attributes(cls):
+ attributes = super().view_attributes() + [
+ ('/form//field[@name="comment"]', 'spell', Eval('party_lang')),
+ ('/tree', 'visual', If(Eval('state') == 'cancelled', 'muted', '')),
+ ('/tree/field[@name="invoice_state"]', 'visual',
+ If(Eval('invoice_state') == 'exception', 'danger', '')),
+ ('/tree/field[@name="shipment_state"]', 'visual',
+ If(Eval('shipment_state') == 'exception', 'danger', '')),
+ ]
+ if Transaction().context.get('modify_header'):
+ attributes.extend([
+ ('//group[@id="states"]', 'states', {'invisible': True}),
+ ('//group[@id="amount"]', 'states', {'invisible': True}),
+ ('//group[@id="links"]', 'states', {'invisible': True}),
+ ('//group[@id="buttons"]', 'states', {'invisible': True}),
+ ])
+ return attributes
+
+ @classmethod
+ def get_resources_to_copy(cls, name):
+ return {
+ 'stock.shipment.out',
+ 'stock.shipment.out.return',
+ 'account.invoice',
+ }
+
+ @classmethod
+ def copy(cls, sales, default=None):
+ if default is None:
+ default = {}
+ else:
+ default = default.copy()
+ default.setdefault('number', None)
+ default.setdefault('invoice_state', 'none')
+ default.setdefault('invoices_ignored', None)
+ default.setdefault('moves', None)
+ default.setdefault('shipment_state', 'none')
+ default.setdefault('sale_date', None)
+ default.setdefault('quoted_by')
+ default.setdefault('confirmed_by')
+ return super(Sale, cls).copy(sales, default=default)
+
+ def check_for_quotation(self):
+ if not self.invoice_address:
+ raise SaleQuotationError(
+ gettext('sale.msg_sale_invoice_address_required_for_quotation',
+ sale=self.rec_name))
+ if not self.shipment_address:
+ raise SaleQuotationError(
+ gettext('sale'
+ '.msg_sale_shipment_address_required_for_quotation',
+ sale=self.rec_name))
+ for line in self.lines:
+ if (line.quantity or 0) >= 0:
+ location = line.from_location
+ else:
+ location = line.to_location
+ if ((not location or not line.warehouse)
+ and line.product
+ and line.product.type in ('goods', 'assets')):
+ raise SaleQuotationError(
+ gettext('sale.msg_sale_warehouse_required_for_quotation',
+ sale=self.rec_name))
+
+ @classmethod
+ def set_number(cls, sales):
+ '''
+ Fill the number field with the sale sequence
+ '''
+ pool = Pool()
+ Config = pool.get('sale.configuration')
+
+ config = Config(1)
+ for sale in sales:
+ if sale.number:
+ continue
+ sale.number = config.get_multivalue(
+ 'sale_sequence', company=sale.company.id).get()
+ cls.save(sales)
+
+ @classmethod
+ def set_sale_date(cls, sales):
+ Date = Pool().get('ir.date')
+ for sale in sales:
+ if not sale.sale_date:
+ cls.write([sale], {
+ 'sale_date': Date.today(),
+ })
+
+ @classmethod
+ def store_cache(cls, sales):
+ for sale in sales:
+ sale.untaxed_amount_cache = sale.untaxed_amount
+ sale.tax_amount_cache = sale.tax_amount
+ sale.total_amount_cache = sale.total_amount
+ cls.save(sales)
+
+ def _get_invoice_sale(self):
+ 'Return invoice'
+ pool = Pool()
+ Invoice = pool.get('account.invoice')
+ party = self.invoice_party or self.party
+ invoice = Invoice(
+ company=self.company,
+ type='out',
+ party=party,
+ invoice_address=self.invoice_address,
+ currency=self.currency,
+ account=party.account_receivable_used,
+ )
+ invoice.on_change_type()
+ invoice.payment_term = self.payment_term
+ return invoice
+
+ def create_invoice(self):
+ 'Create and return an invoice'
+ if self.invoice_method == 'manual':
+ return
+
+ invoice_lines = []
+ for line in self.lines:
+ invoice_lines.append(line.get_invoice_line())
+ invoice_lines = list(chain(*invoice_lines))
+ if not invoice_lines:
+ return
+
+ invoice = self._get_invoice_sale()
+ if getattr(invoice, 'lines', None):
+ invoice_lines = list(invoice.lines) + invoice_lines
+ invoice.lines = invoice_lines
+ invoice.save()
+
+ invoice.update_taxes()
+ self.copy_resources_to(invoice)
+ return invoice
+
+ def _group_shipment_key(self, moves, move):
+ '''
+ The key to group moves by shipments
+
+ move is a tuple of line and a move
+ '''
+ line, move = move
+
+ if any(m.planned_date is None for m in moves):
+ planned_date = None
+ else:
+ planned_date = max(m.planned_date for m in moves)
+ return (
+ ('planned_date', planned_date),
+ ('warehouse', line.warehouse.id),
+ )
+
+ _group_return_key = _group_shipment_key
+
+ def _get_shipment_sale(self, Shipment, key):
+ values = {
+ 'customer': self.shipment_party or self.party,
+ 'delivery_address': self.shipment_address,
+ 'company': self.company,
+ }
+ values.update(dict(key))
+ return Shipment(**values)
+
+ def _get_shipment_moves(self, shipment_type):
+ moves = {}
+ for line in self.lines:
+ move = line.get_move(shipment_type)
+ if move:
+ moves[line] = move
+ return moves
+
+ def create_shipment(self, shipment_type):
+ '''
+ Create and return shipments of type shipment_type
+ '''
+ pool = Pool()
+
+ if self.shipment_method == 'manual':
+ return
+
+ moves = self._get_shipment_moves(shipment_type)
+ if not moves:
+ return
+ if shipment_type == 'out':
+ keyfunc = partial(self._group_shipment_key, list(moves.values()))
+ Shipment = pool.get('stock.shipment.out')
+ elif shipment_type == 'return':
+ keyfunc = partial(self._group_return_key, list(moves.values()))
+ Shipment = pool.get('stock.shipment.out.return')
+ moves = moves.items()
+ moves = sorted(moves, key=sortable_values(keyfunc))
+
+ shipments = []
+ for key, grouped_moves in groupby(moves, key=keyfunc):
+ shipment = self._get_shipment_sale(Shipment, key)
+ shipment.moves = (list(getattr(shipment, 'moves', []))
+ + [x[1] for x in grouped_moves])
+ shipment.save()
+ self.copy_resources_to(shipment)
+ shipments.append(shipment)
+ if shipment_type == 'out':
+ Shipment.wait(shipments)
+ return shipments
+
+ def is_done(self):
+ return ((self.invoice_state == 'paid'
+ or self.invoice_state == 'none')
+ and (self.shipment_state == 'sent'
+ or self.shipment_state == 'none'
+ or all(l.product.type == 'service'
+ for l in self.lines if l.product)))
+
+ @classmethod
+ def delete(cls, sales):
+ # Cancel before delete
+ cls.cancel(sales)
+ for sale in sales:
+ if sale.state != 'cancelled':
+ raise AccessError(
+ gettext('sale.msg_sale_delete_cancel',
+ sale=sale.rec_name))
+ super(Sale, cls).delete(sales)
+
+ def on_change(self, fieldnames):
+ pool = Pool()
+ ModelData = pool.get('ir.model.data')
+ context = Transaction().context
+ wizard_modify_header_id = ModelData.get_id(
+ 'sale', 'wizard_modify_header')
+ if (len(fieldnames) > 1
+ and context.get('action_id') == wizard_modify_header_id):
+ return []
+ return super().on_change(fieldnames)
+
+ @classmethod
+ @ModelView.button
+ @Workflow.transition('cancelled')
+ def cancel(cls, sales):
+ cls.store_cache(sales)
+
+ @classmethod
+ @ModelView.button
+ @Workflow.transition('draft')
+ @reset_employee('quoted_by', 'confirmed_by')
+ def draft(cls, sales):
+ pass
+
+ @classmethod
+ @ModelView.button
+ @Workflow.transition('quotation')
+ @set_employee('quoted_by')
+ def quote(cls, sales):
+ for sale in sales:
+ sale.check_for_quotation()
+ cls.set_number(sales)
+
+ @classmethod
+ @ModelView.button
+ @Workflow.transition('confirmed')
+ @set_employee('confirmed_by')
+ def confirm(cls, sales):
+ pool = Pool()
+ Configuration = pool.get('sale.configuration')
+ cls.set_sale_date(sales)
+ cls.store_cache(sales)
+ config = Configuration(1)
+ with Transaction().set_context(
+ queue_name='sale',
+ queue_scheduled_at=config.sale_process_after):
+ cls.__queue__.process(sales)
+
+ @classmethod
+ @ModelView.button_action('sale.wizard_invoice_handle_exception')
+ def handle_invoice_exception(cls, sales):
+ pass
+
+ @classmethod
+ @ModelView.button_action('sale.wizard_shipment_handle_exception')
+ def handle_shipment_exception(cls, sales):
+ pass
+
+ @classmethod
+ @Workflow.transition('processing')
+ def proceed(cls, sales):
+ pass
+
+ @classmethod
+ @Workflow.transition('done')
+ def do(cls, sales):
+ pass
+
+ @classmethod
+ @ModelView.button
+ def process(cls, sales):
+ pool = Pool()
+ Line = pool.get('sale.line')
+ lines = []
+ done = []
+ process = []
+ cls.lock(sales)
+ for sale in sales:
+ if sale.state not in ('confirmed', 'processing', 'done'):
+ continue
+ sale.create_invoice()
+ sale.set_invoice_state()
+ sale.create_shipment('out')
+ sale.create_shipment('return')
+ sale.set_shipment_state()
+
+ for line in sale.lines:
+ line.set_actual_quantity()
+ lines.append(line)
+
+ if sale.is_done():
+ if sale.state != 'done':
+ if sale.state == 'confirmed':
+ process.append(sale)
+ done.append(sale)
+ elif sale.state != 'processing':
+ process.append(sale)
+ Line.save(lines)
+ if process:
+ cls.proceed(process)
+ if done:
+ cls.do(done)
+
+ @classmethod
+ @ModelView.button_action('sale.wizard_modify_header')
+ def modify_header(cls, sales):
+ pass
+
+
+class SaleIgnoredInvoice(ModelSQL):
+ 'Sale - Ignored Invoice'
+ __name__ = 'sale.sale-ignored-account.invoice'
+ _table = 'sale_invoice_ignored_rel'
+ sale = fields.Many2One('sale.sale', 'Sale', ondelete='CASCADE',
+ select=True, required=True)
+ invoice = fields.Many2One('account.invoice', 'Invoice',
+ ondelete='RESTRICT', select=True, required=True)
+
+
+class SaleRecreatedInvoice(ModelSQL):
+ 'Sale - Recreated Invoice'
+ __name__ = 'sale.sale-recreated-account.invoice'
+ _table = 'sale_invoice_recreated_rel'
+ sale = fields.Many2One('sale.sale', 'Sale', ondelete='CASCADE',
+ select=True, required=True)
+ invoice = fields.Many2One('account.invoice', 'Invoice',
+ ondelete='RESTRICT', select=True, required=True)
+
+
+class SaleLine(TaxableMixin, sequence_ordered(), ModelSQL, ModelView):
+ 'Sale Line'
+ __name__ = 'sale.line'
+ sale = fields.Many2One('sale.sale', 'Sale', ondelete='CASCADE',
+ select=True, required=True,
+ states={
+ 'readonly': ((Eval('sale_state') != 'draft')
+ & Bool(Eval('sale'))),
+ },
+ depends=['sale_state'])
+ type = fields.Selection([
+ ('line', 'Line'),
+ ('subtotal', 'Subtotal'),
+ ('title', 'Title'),
+ ('comment', 'Comment'),
+ ], 'Type', select=True, required=True,
+ states={
+ 'readonly': Eval('sale_state') != 'draft',
+ },
+ depends=['sale_state'])
+ quantity = fields.Float('Quantity',
+ digits=(16, Eval('unit_digits', 2)),
+ states={
+ 'invisible': Eval('type') != 'line',
+ 'required': Eval('type') == 'line',
+ 'readonly': Eval('sale_state') != 'draft',
+ },
+ depends=['type', 'unit_digits', 'sale_state'])
+ actual_quantity = fields.Float(
+ "Actual Quantity", digits=(16, Eval('unit_digits', 2)), readonly=True,
+ states={
+ 'invisible': Eval('type') != 'line',
+ },
+ depends=['unit_digits', 'type'])
+ unit = fields.Many2One('product.uom', 'Unit', ondelete='RESTRICT',
+ states={
+ 'required': Bool(Eval('product')),
+ 'invisible': Eval('type') != 'line',
+ 'readonly': Eval('sale_state') != 'draft',
+ },
+ domain=[
+ If(Bool(Eval('product_uom_category')),
+ ('category', '=', Eval('product_uom_category')),
+ ('category', '!=', -1)),
+ ],
+ depends=['product', 'type', 'product_uom_category', 'sale_state'])
+ unit_digits = fields.Function(fields.Integer('Unit Digits'),
+ 'on_change_with_unit_digits')
+ product = fields.Many2One('product.product', 'Product',
+ ondelete='RESTRICT',
+ domain=[
+ If(Eval('sale_state').in_(['draft', 'quotation']),
+ ('salable', '=', True),
+ ()),
+ ],
+ states={
+ 'invisible': Eval('type') != 'line',
+ 'readonly': Eval('sale_state') != 'draft',
+ },
+ context={
+ 'company': Eval('company', None),
+ },
+ search_context={
+ 'locations': If(Bool(Eval('_parent_sale', {}).get('warehouse')),
+ [Eval('_parent_sale', {}).get('warehouse', 0)], []),
+ 'stock_date_end': Eval('_parent_sale', {}).get('sale_date'),
+ 'stock_skip_warehouse': True,
+ 'currency': Eval('_parent_sale', {}).get('currency'),
+ 'customer': Eval('_parent_sale', {}).get('party'),
+ 'sale_date': Eval('_parent_sale', {}).get('sale_date'),
+ 'uom': Eval('unit'),
+ 'taxes': Eval('taxes', []),
+ 'quantity': Eval('quantity'),
+ },
+ depends=['type', 'sale_state', 'company'])
+ product_uom_category = fields.Function(
+ fields.Many2One('product.uom.category', 'Product Uom Category'),
+ 'on_change_with_product_uom_category')
+ unit_price = fields.Numeric('Unit Price', digits=price_digits,
+ states={
+ 'invisible': Eval('type') != 'line',
+ 'required': Eval('type') == 'line',
+ 'readonly': Eval('sale_state') != 'draft'
+ }, depends=['type', 'sale_state'])
+ amount = fields.Function(fields.Numeric('Amount',
+ digits=(16, Eval('_parent_sale', {}).get('currency_digits', 2)),
+ states={
+ 'invisible': ~Eval('type').in_(['line', 'subtotal']),
+ },
+ depends=['type', 'sale_state']), 'get_amount')
+ currency = fields.Function(
+ fields.Many2One('currency.currency', 'Currency'),
+ 'on_change_with_currency')
+ description = fields.Text('Description', size=None,
+ states={
+ 'readonly': Eval('sale_state') != 'draft',
+ },
+ depends=['sale_state'])
+ summary = fields.Function(fields.Char('Summary'), 'on_change_with_summary')
+ note = fields.Text('Note')
+ taxes = fields.Many2Many('sale.line-account.tax', 'line', 'tax', 'Taxes',
+ order=[('tax.sequence', 'ASC'), ('tax.id', 'ASC')],
+ domain=[('parent', '=', None), ['OR',
+ ('group', '=', None),
+ ('group.kind', 'in', ['sale', 'both'])],
+ ('company', '=',
+ Eval('_parent_sale', {}).get('company', -1)),
+ ],
+ states={
+ 'invisible': Eval('type') != 'line',
+ 'readonly': Eval('sale_state') != 'draft',
+ }, depends=['type', 'sale_state'])
+ invoice_lines = fields.One2Many('account.invoice.line', 'origin',
+ 'Invoice Lines', readonly=True)
+ moves = fields.One2Many('stock.move', 'origin', 'Moves', readonly=True)
+ moves_ignored = fields.Many2Many('sale.line-ignored-stock.move',
+ 'sale_line', 'move', 'Ignored Moves', readonly=True)
+ moves_recreated = fields.Many2Many('sale.line-recreated-stock.move',
+ 'sale_line', 'move', 'Recreated Moves', readonly=True)
+ move_done = fields.Function(fields.Boolean('Moves Done'), 'get_move_done')
+ move_exception = fields.Function(fields.Boolean('Moves Exception'),
+ 'get_move_exception')
+ warehouse = fields.Function(fields.Many2One('stock.location',
+ 'Warehouse'), 'get_warehouse')
+ from_location = fields.Function(fields.Many2One('stock.location',
+ 'From Location'), 'get_from_location')
+ to_location = fields.Function(fields.Many2One('stock.location',
+ 'To Location'), 'get_to_location')
+ shipping_date = fields.Function(fields.Date('Shipping Date',
+ states={
+ 'invisible': Eval('type') != 'line',
+ },
+ depends=['type']),
+ 'on_change_with_shipping_date')
+ sale_state = fields.Function(
+ fields.Selection('get_sale_states', "Sale State"),
+ 'on_change_with_sale_state')
+ company = fields.Function(
+ fields.Many2One('company.company', "Company"),
+ 'on_change_with_company')
+
+ @classmethod
+ def __setup__(cls):
+ super().__setup__()
+ cls.__access__.add('sale')
+
+ @classmethod
+ def __register__(cls, module_name):
+ super(SaleLine, cls).__register__(module_name)
+ table = cls.__table_handler__(module_name)
+
+ # Migration from 4.6: drop required on description
+ table.not_null_action('description', action='remove')
+
+ @staticmethod
+ def default_type():
+ return 'line'
+
+ @staticmethod
+ def default_unit_digits():
+ return 2
+
+ @fields.depends('unit')
+ def on_change_with_unit_digits(self, name=None):
+ if self.unit:
+ return self.unit.digits
+ return 2
+
+ @property
+ def _move_remaining_quantity(self):
+ "Compute the remaining quantity to ship"
+ pool = Pool()
+ Uom = pool.get('product.uom')
+ if self.type != 'line' or not self.product:
+ return
+ if self.product.type == 'service':
+ return
+ skip_ids = set(x.id for x in self.moves_ignored)
+ quantity = abs(self.quantity)
+ for move in self.moves:
+ if move.state == 'done' or move.id in skip_ids:
+ quantity -= Uom.compute_qty(move.uom, move.quantity, self.unit)
+ return quantity
+
+ def get_move_done(self, name):
+ quantity = self._move_remaining_quantity
+ if quantity is None:
+ return True
+ else:
+ return self.unit.round(quantity) <= 0
+
+ def get_move_exception(self, name):
+ skip_ids = set(x.id for x in self.moves_ignored)
+ skip_ids.update(x.id for x in self.moves_recreated)
+ for move in self.moves:
+ if move.state == 'cancelled' \
+ and move.id not in skip_ids:
+ return True
+ return False
+
+ @property
+ def taxable_lines(self):
+ # In case we're called from an on_change
+ # we have to use some sensible defaults
+ if getattr(self, 'type', None) == 'line':
+ return [(
+ getattr(self, 'taxes', None) or [],
+ getattr(self, 'unit_price', None) or Decimal(0),
+ getattr(self, 'quantity', None) or 0,
+ None,
+ )]
+ else:
+ return []
+
+ def _get_tax_context(self):
+ return self.sale._get_tax_context()
+
+ def _get_tax_rule_pattern(self):
+ '''
+ Get tax rule pattern
+ '''
+ return {}
+
+ @fields.depends(
+ 'sale', '_parent_sale.currency', '_parent_sale.party',
+ '_parent_sale.sale_date', 'company',
+ 'unit', 'product', 'taxes')
+ def _get_context_sale_price(self):
+ context = {}
+ if self.sale:
+ if self.sale.currency:
+ context['currency'] = self.sale.currency.id
+ if self.sale.party:
+ context['customer'] = self.sale.party.id
+ context['sale_date'] = self.sale.sale_date
+ if self.company:
+ context['company'] = self.company.id
+ if self.unit:
+ context['uom'] = self.unit.id
+ elif self.product:
+ context['uom'] = self.product.sale_uom.id
+ context['taxes'] = [t.id for t in self.taxes or []]
+ return context
+
+ @fields.depends('product', 'unit', 'sale',
+ '_parent_sale.party', '_parent_sale.invoice_party',
+ methods=['compute_taxes', 'compute_unit_price',
+ 'on_change_with_amount'])
+ def on_change_product(self):
+ if not self.product:
+ return
+
+ party = None
+ if self.sale:
+ party = self.sale.invoice_party or self.sale.party
+
+ # Set taxes before unit_price to have taxes in context of sale price
+ self.taxes = self.compute_taxes(party)
+
+ category = self.product.sale_uom.category
+ if not self.unit or self.unit.category != category:
+ self.unit = self.product.sale_uom
+ self.unit_digits = self.product.sale_uom.digits
+
+ self.unit_price = self.compute_unit_price()
+
+ self.type = 'line'
+ self.amount = self.on_change_with_amount()
+
+ @fields.depends('product', methods=['_get_tax_rule_pattern'])
+ def compute_taxes(self, party):
+ taxes = set()
+ pattern = self._get_tax_rule_pattern()
+ for tax in self.product.customer_taxes_used:
+ if party and party.customer_tax_rule:
+ tax_ids = party.customer_tax_rule.apply(tax, pattern)
+ if tax_ids:
+ taxes.update(tax_ids)
+ continue
+ taxes.add(tax.id)
+ if party and party.customer_tax_rule:
+ tax_ids = party.customer_tax_rule.apply(None, pattern)
+ if tax_ids:
+ taxes.update(tax_ids)
+ return list(taxes)
+
+ @fields.depends('product', 'quantity', methods=['_get_context_sale_price'])
+ def compute_unit_price(self):
+ pool = Pool()
+ Product = pool.get('product.product')
+
+ if not self.product:
+ return
+
+ with Transaction().set_context(
+ self._get_context_sale_price()):
+ unit_price = Product.get_sale_price([self.product],
+ self.quantity or 0)[self.product.id]
+ if unit_price:
+ unit_price = round_price(unit_price)
+ return unit_price
+
+ @fields.depends('product')
+ def on_change_with_product_uom_category(self, name=None):
+ if self.product:
+ return self.product.default_uom_category.id
+
+ @fields.depends(methods=['compute_unit_price'])
+ def on_change_quantity(self):
+ self.unit_price = self.compute_unit_price()
+
+ @fields.depends(methods=['on_change_quantity'])
+ def on_change_unit(self):
+ self.on_change_quantity()
+
+ @fields.depends(methods=['on_change_quantity'])
+ def on_change_taxes(self):
+ self.on_change_quantity()
+
+ @fields.depends('description')
+ def on_change_with_summary(self, name=None):
+ return firstline(self.description or '')
+
+ @fields.depends('type', 'quantity', 'unit_price', 'unit', 'sale',
+ '_parent_sale.currency')
+ def on_change_with_amount(self):
+ if self.type == 'line':
+ currency = self.sale.currency if self.sale else None
+ amount = Decimal(str(self.quantity or '0.0')) * \
+ (self.unit_price or Decimal('0.0'))
+ if currency:
+ return currency.round(amount)
+ return amount
+ return Decimal('0.0')
+
+ def get_amount(self, name):
+ if self.type == 'line':
+ return self.on_change_with_amount()
+ elif self.type == 'subtotal':
+ amount = Decimal('0.0')
+ for line2 in self.sale.lines:
+ if line2.type == 'line':
+ amount += line2.sale.currency.round(
+ Decimal(str(line2.quantity)) * line2.unit_price)
+ elif line2.type == 'subtotal':
+ if self == line2:
+ break
+ amount = Decimal('0.0')
+ return amount
+ return Decimal('0.0')
+
+ def get_warehouse(self, name):
+ return self.sale.warehouse.id if self.sale.warehouse else None
+
+ def get_from_location(self, name):
+ if (self.quantity or 0) >= 0:
+ if self.warehouse:
+ return self.warehouse.output_location.id
+ else:
+ party = self.sale.shipment_party or self.sale.party
+ return party.customer_location.id
+
+ def get_to_location(self, name):
+ if (self.quantity or 0) >= 0:
+ party = self.sale.shipment_party or self.sale.party
+ return party.customer_location.id
+ else:
+ if self.warehouse:
+ return self.warehouse.input_location.id
+
+ @fields.depends('moves', methods=['planned_shipping_date'])
+ def on_change_with_shipping_date(self, name=None):
+ moves = [m for m in self.moves if m.state != 'cancelled']
+ if moves:
+ dates = filter(
+ None, (m.effective_date or m.planned_date for m in moves))
+ return min(dates, default=None)
+ return self.planned_shipping_date
+
+ @property
+ @fields.depends(
+ 'product', 'quantity', 'sale',
+ '_parent_sale.sale_date', '_parent_sale.shipping_date')
+ def planned_shipping_date(self):
+ pool = Pool()
+ Date = pool.get('ir.date')
+ if self.product and self.quantity is not None and self.quantity > 0:
+ date = self.sale.sale_date if self.sale else None
+ shipping_date = self.product.compute_shipping_date(date=date)
+ if shipping_date == datetime.date.max:
+ shipping_date = None
+ elif self.sale and self.sale.shipping_date:
+ shipping_date = max(shipping_date, self.sale.shipping_date)
+ if shipping_date:
+ shipping_date = max(shipping_date, Date.today())
+ return shipping_date
+
+ @fields.depends('sale', '_parent_sale.currency')
+ def on_change_with_currency(self, name=None):
+ if self.sale and self.sale.currency:
+ return self.sale.currency.id
+
+ @classmethod
+ def get_sale_states(cls):
+ pool = Pool()
+ Sale = pool.get('sale.sale')
+ return Sale.fields_get(['state'])['state']['selection']
+
+ @fields.depends('sale', '_parent_sale.state')
+ def on_change_with_sale_state(self, name=None):
+ if self.sale:
+ return self.sale.state
+
+ @fields.depends('sale', '_parent_sale.company')
+ def on_change_with_company(self, name=None):
+ if self.sale and self.sale.company:
+ return self.sale.company.id
+
+ def get_invoice_line(self):
+ 'Return a list of invoice lines for sale line'
+ pool = Pool()
+ InvoiceLine = pool.get('account.invoice.line')
+ AccountConfiguration = pool.get('account.configuration')
+ account_config = AccountConfiguration(1)
+
+ invoice_line = InvoiceLine()
+ invoice_line.type = self.type
+ invoice_line.currency = self.currency
+ invoice_line.company = self.company
+ invoice_line.description = self.description
+ invoice_line.note = self.note
+ invoice_line.origin = self
+ if self.type != 'line':
+ if self._get_invoice_not_line():
+ return [invoice_line]
+ else:
+ return []
+
+ quantity = (self._get_invoice_line_quantity()
+ - self._get_invoiced_quantity())
+
+ if self.unit:
+ quantity = self.unit.round(quantity)
+ invoice_line.quantity = quantity
+
+ if not invoice_line.quantity:
+ return []
+
+ invoice_line.unit = self.unit
+ invoice_line.product = self.product
+ invoice_line.unit_price = self.unit_price
+ invoice_line.taxes = self.taxes
+ invoice_line.invoice_type = 'out'
+ if self.product:
+ invoice_line.account = self.product.account_revenue_used
+ if not invoice_line.account:
+ raise AccountError(
+ gettext('sale.msg_sale_product_missing_account_revenue',
+ sale=self.sale.rec_name,
+ product=self.product.rec_name))
+ else:
+ invoice_line.account = account_config.get_multivalue(
+ 'default_category_account_revenue', company=self.company.id)
+ if not invoice_line.account:
+ raise AccountError(
+ gettext('sale.msg_sale_missing_account_revenue',
+ sale=self.sale.rec_name))
+ invoice_line.stock_moves = self._get_invoice_line_moves()
+ return [invoice_line]
+
+ def _get_invoice_not_line(self):
+ 'Return if the not line should be invoiced'
+ return self.sale.invoice_method == 'order' and not self.invoice_lines
+
+ def _get_invoice_line_quantity(self):
+ 'Return the quantity that should be invoiced'
+ pool = Pool()
+ Uom = pool.get('product.uom')
+
+ if (self.sale.invoice_method == 'order'
+ or not self.product
+ or self.product.type == 'service'):
+ return self.quantity
+ elif self.sale.invoice_method == 'shipment':
+ quantity = 0.0
+ for move in self.moves:
+ if move.state != 'done':
+ continue
+ qty = Uom.compute_qty(move.uom, move.quantity, self.unit)
+ # Test only against to_location
+ # as it is what matters for sale
+ dest_type = self.to_location.type
+ if (move.to_location.type == dest_type
+ and move.from_location.type != dest_type):
+ quantity += qty
+ elif (move.from_location.type == dest_type
+ and move.to_location.type != dest_type):
+ quantity -= qty
+ if self.quantity < 0:
+ quantity *= -1
+ return quantity
+
+ def _get_invoiced_quantity(self):
+ 'Return the quantity already invoiced'
+ pool = Pool()
+ Uom = pool.get('product.uom')
+
+ quantity = 0
+ skips = {l for i in self.sale.invoices_recreated for l in i.lines}
+ for invoice_line in self.invoice_lines:
+ if invoice_line.type != 'line':
+ continue
+ if invoice_line not in skips:
+ quantity += Uom.compute_qty(invoice_line.unit,
+ invoice_line.quantity, self.unit)
+ return quantity
+
+ def _get_invoice_line_moves(self):
+ 'Return the stock moves that should be invoiced'
+ moves = []
+ if self.sale.invoice_method == 'order':
+ if self.sale.shipment_method != 'order':
+ moves.extend(self.moves)
+ elif self.sale.invoice_method == 'shipment':
+ for move in self.moves:
+ if move.state == 'done':
+ if move.invoiced_quantity < move.quantity:
+ moves.append(move)
+ return moves
+
+ def get_move(self, shipment_type):
+ '''
+ Return moves for the sale line according to shipment_type
+ '''
+ pool = Pool()
+ Move = pool.get('stock.move')
+ Date = pool.get('ir.date')
+
+ if self.type != 'line':
+ return
+ if not self.product:
+ return
+ if self.product.type not in Move.get_product_types():
+ return
+
+ if (shipment_type == 'out') != (self.quantity >= 0):
+ return
+
+ quantity = (self._get_move_quantity(shipment_type)
+ - self._get_shipped_quantity(shipment_type))
+
+ quantity = self.unit.round(quantity)
+ if quantity <= 0:
+ return
+
+ if not self.sale.party.customer_location:
+ raise PartyLocationError(
+ gettext('sale.msg_sale_customer_location_required',
+ sale=self.sale.rec_name,
+ party=self.sale.party.rec_name))
+ move = Move()
+ move.quantity = quantity
+ move.uom = self.unit
+ move.product = self.product
+ move.from_location = self.from_location
+ move.to_location = self.to_location
+ move.state = 'draft'
+ move.company = self.sale.company
+ if move.on_change_with_unit_price_required():
+ move.unit_price = self.unit_price
+ move.currency = self.sale.currency
+ move.planned_date = self.planned_shipping_date
+ move.invoice_lines = self._get_move_invoice_lines(shipment_type)
+ move.origin = self
+ return move
+
+ def _get_move_quantity(self, shipment_type):
+ 'Return the quantity that should be shipped'
+ pool = Pool()
+ Uom = pool.get('product.uom')
+
+ if self.sale.shipment_method == 'order':
+ return abs(self.quantity)
+ elif self.sale.shipment_method == 'invoice':
+ quantity = 0.0
+ for invoice_line in self.invoice_lines:
+ if (invoice_line.invoice
+ and invoice_line.invoice.state == 'paid'):
+ quantity += Uom.compute_qty(invoice_line.unit,
+ invoice_line.quantity, self.unit)
+ return quantity
+
+ def _get_shipped_quantity(self, shipment_type):
+ 'Return the quantity already shipped'
+ pool = Pool()
+ Uom = pool.get('product.uom')
+
+ quantity = 0
+ skips = set(m for m in self.moves_recreated)
+ for move in self.moves:
+ if move not in skips:
+ quantity += Uom.compute_qty(move.uom, move.quantity,
+ self.unit)
+ return quantity
+
+ def _get_move_invoice_lines(self, shipment_type):
+ 'Return the invoice lines that should be shipped'
+ invoice_lines = []
+ if self.sale.shipment_method == 'order':
+ if self.sale.invoice_method == 'order':
+ invoice_lines.extend(self.invoice_lines)
+ elif self.sale.shipment_method == 'invoice':
+ for invoice_line in self.invoice_lines:
+ if (invoice_line.invoice
+ and invoice_line.invoice.state == 'paid'):
+ if invoice_line.moved_quantity < invoice_line.quantity:
+ invoice_lines.append(invoice_line)
+ return invoice_lines
+
+ def set_actual_quantity(self):
+ pool = Pool()
+ Uom = pool.get('product.uom')
+ if self.type != 'line':
+ return
+ moved_quantity = 0
+ for move in self.moves:
+ if move.state != 'cancelled' and self.unit:
+ moved_quantity += Uom.compute_qty(
+ move.uom, move.quantity, self.unit, round=False)
+ if self.quantity < 0:
+ moved_quantity *= -1
+ invoiced_quantity = 0
+ for invoice_line in self.invoice_lines:
+ if (
+ (not invoice_line.invoice
+ or invoice_line.invoice.state != 'cancelled')
+ and self.unit and invoice_line.unit):
+ invoiced_quantity += Uom.compute_qty(
+ invoice_line.unit, invoice_line.quantity, self.unit,
+ round=False)
+ actual_quantity = max(moved_quantity, invoiced_quantity, key=abs)
+ if self.unit:
+ actual_quantity = self.unit.round(actual_quantity)
+ if self.actual_quantity != actual_quantity:
+ self.actual_quantity = actual_quantity
+
+ def get_rec_name(self, name):
+ pool = Pool()
+ Lang = pool.get('ir.lang')
+ if self.product:
+ lang = Lang.get()
+ return (lang.format(
+ '%.*f', (self.unit.digits, self.quantity or 0))
+ + '%s %s @ %s' % (
+ self.unit.symbol, self.product.rec_name,
+ self.sale.rec_name))
+ else:
+ return self.sale.rec_name
+
+ @classmethod
+ def search_rec_name(cls, name, clause):
+ return ['OR',
+ ('sale.rec_name',) + tuple(clause[1:]),
+ ('product.rec_name',) + tuple(clause[1:]),
+ ]
+
+ @classmethod
+ def view_attributes(cls):
+ return super().view_attributes() + [
+ ('/form//field[@name="note"]|/form//field[@name="description"]',
+ 'spell', Eval('_parent_sale', {}).get('party_lang'))]
+
+ @classmethod
+ def delete(cls, lines):
+ for line in lines:
+ if line.sale_state not in {'cancelled', 'draft'}:
+ raise AccessError(
+ gettext('sale.msg_sale_line_delete_cancel_draft',
+ line=line.rec_name,
+ sale=line.sale.rec_name))
+ super(SaleLine, cls).delete(lines)
+
+ @classmethod
+ def copy(cls, lines, default=None):
+ if default is None:
+ default = {}
+ else:
+ default = default.copy()
+ default.setdefault('moves', None)
+ default.setdefault('moves_ignored', None)
+ default.setdefault('moves_recreated', None)
+ default.setdefault('invoice_lines', None)
+ default.setdefault('actual_quantity')
+ return super(SaleLine, cls).copy(lines, default=default)
+
+
+class SaleLineTax(ModelSQL):
+ 'Sale Line - Tax'
+ __name__ = 'sale.line-account.tax'
+ _table = 'sale_line_account_tax'
+ line = fields.Many2One('sale.line', 'Sale Line', ondelete='CASCADE',
+ select=True, required=True)
+ tax = fields.Many2One('account.tax', 'Tax', ondelete='RESTRICT',
+ select=True, required=True)
+
+
+class SaleLineIgnoredMove(ModelSQL):
+ 'Sale Line - Ignored Move'
+ __name__ = 'sale.line-ignored-stock.move'
+ _table = 'sale_line_moves_ignored_rel'
+ sale_line = fields.Many2One('sale.line', 'Sale Line', ondelete='CASCADE',
+ select=True, required=True)
+ move = fields.Many2One('stock.move', 'Move', ondelete='RESTRICT',
+ select=True, required=True)
+
+
+class SaleLineRecreatedMove(ModelSQL):
+ 'Sale Line - Recreated Move'
+ __name__ = 'sale.line-recreated-stock.move'
+ _table = 'sale_line_moves_recreated_rel'
+ sale_line = fields.Many2One('sale.line', 'Sale Line', ondelete='CASCADE',
+ select=True, required=True)
+ move = fields.Many2One('stock.move', 'Move', ondelete='RESTRICT',
+ select=True, required=True)
+
+
+class SaleReport(CompanyReport):
+ __name__ = 'sale.sale'
+
+ @classmethod
+ def execute(cls, ids, data):
+ with Transaction().set_context(address_with_party=True):
+ return super(SaleReport, cls).execute(ids, data)
+
+ @classmethod
+ def get_context(cls, records, header, data):
+ pool = Pool()
+ Date = pool.get('ir.date')
+ context = super().get_context(records, header, data)
+ context['today'] = Date.today()
+ return context
+
+
+class OpenCustomer(Wizard):
+ 'Open Customers'
+ __name__ = 'sale.open_customer'
+ start_state = 'open_'
+ open_ = StateAction('party.act_party_form')
+
+ def do_open_(self, action):
+ pool = Pool()
+ ModelData = pool.get('ir.model.data')
+ Wizard = pool.get('ir.action.wizard')
+ Sale = pool.get('sale.sale')
+ cursor = Transaction().connection.cursor()
+ sale = Sale.__table__()
+
+ cursor.execute(*sale.select(sale.party, group_by=sale.party))
+ customer_ids = [line[0] for line in cursor]
+ action['pyson_domain'] = PYSONEncoder().encode(
+ [('id', 'in', customer_ids)])
+ wizard = Wizard(ModelData.get_id('sale', 'act_open_customer'))
+ action['name'] = wizard.name
+ return action, {}
+
+ def transition_open_(self):
+ return 'end'
+
+
+class HandleShipmentExceptionAsk(ModelView):
+ 'Handle Shipment Exception'
+ __name__ = 'sale.handle.shipment.exception.ask'
+ recreate_moves = fields.Many2Many(
+ 'stock.move', None, None, 'Recreate Moves',
+ domain=[('id', 'in', Eval('domain_moves'))], depends=['domain_moves'])
+ domain_moves = fields.Many2Many(
+ 'stock.move', None, None, 'Domain Moves')
+
+
+class HandleShipmentException(Wizard):
+ 'Handle Shipment Exception'
+ __name__ = 'sale.handle.shipment.exception'
+ start_state = 'ask'
+ ask = StateView('sale.handle.shipment.exception.ask',
+ 'sale.handle_shipment_exception_ask_view_form', [
+ Button('Cancel', 'end', 'tryton-cancel'),
+ Button('OK', 'handle', 'tryton-ok', default=True),
+ ])
+ handle = StateTransition()
+
+ def default_ask(self, fields):
+ moves = []
+ for line in self.record.lines:
+ skips = set(line.moves_ignored)
+ skips.update(line.moves_recreated)
+ for move in line.moves:
+ if move.state == 'cancelled' and move not in skips:
+ moves.append(move.id)
+ return {
+ 'recreate_moves': moves,
+ 'domain_moves': moves,
+ }
+
+ def transition_handle(self):
+ pool = Pool()
+ SaleLine = pool.get('sale.line')
+
+ for line in self.record.lines:
+ moves_ignored = []
+ moves_recreated = []
+ skips = set(line.moves_ignored)
+ skips.update(line.moves_recreated)
+ for move in line.moves:
+ if move not in self.ask.domain_moves or move in skips:
+ continue
+ if move in self.ask.recreate_moves:
+ moves_recreated.append(move.id)
+ else:
+ moves_ignored.append(move.id)
+
+ SaleLine.write([line], {
+ 'moves_ignored': [('add', moves_ignored)],
+ 'moves_recreated': [('add', moves_recreated)],
+ })
+ self.model.__queue__.process([self.record])
+ return 'end'
+
+
+class HandleInvoiceExceptionAsk(ModelView):
+ 'Handle Invoice Exception'
+ __name__ = 'sale.handle.invoice.exception.ask'
+ recreate_invoices = fields.Many2Many(
+ 'account.invoice', None, None, 'Recreate Invoices',
+ domain=[('id', 'in', Eval('domain_invoices'))],
+ depends=['domain_invoices'],
+ help='The selected invoices will be recreated. '
+ 'The other ones will be ignored.')
+ domain_invoices = fields.Many2Many(
+ 'account.invoice', None, None, 'Domain Invoices')
+
+
+class HandleInvoiceException(Wizard):
+ 'Handle Invoice Exception'
+ __name__ = 'sale.handle.invoice.exception'
+ start_state = 'ask'
+ ask = StateView('sale.handle.invoice.exception.ask',
+ 'sale.handle_invoice_exception_ask_view_form', [
+ Button('Cancel', 'end', 'tryton-cancel'),
+ Button('OK', 'handle', 'tryton-ok', default=True),
+ ])
+ handle = StateTransition()
+
+ def default_ask(self, fields):
+ skips = set(self.record.invoices_ignored)
+ skips.update(self.record.invoices_recreated)
+ invoices = []
+ for invoice in self.record.invoices:
+ if invoice.state == 'cancelled' and invoice not in skips:
+ invoices.append(invoice.id)
+ return {
+ 'recreate_invoices': invoices,
+ 'domain_invoices': invoices,
+ }
+
+ def transition_handle(self):
+ invoices_ignored = []
+ invoices_recreated = []
+ for invoice in self.ask.domain_invoices:
+ if invoice in self.ask.recreate_invoices:
+ invoices_recreated.append(invoice.id)
+ else:
+ invoices_ignored.append(invoice.id)
+
+ self.model.write([self.record], {
+ 'invoices_ignored': [('add', invoices_ignored)],
+ 'invoices_recreated': [('add', invoices_recreated)],
+ })
+ self.model.__queue__.process([self.record])
+ return 'end'
+
+
+class ReturnSaleStart(ModelView):
+ 'Return Sale'
+ __name__ = 'sale.return_sale.start'
+
+
+class ReturnSale(Wizard):
+ 'Return Sale'
+ __name__ = 'sale.return_sale'
+ start = StateView('sale.return_sale.start',
+ 'sale.return_sale_start_view_form', [
+ Button('Cancel', 'end', 'tryton-cancel'),
+ Button('Return', 'return_', 'tryton-ok', default=True),
+ ])
+ return_ = StateAction('sale.act_sale_form')
+
+ def do_return_(self, action):
+ sales = self.records
+ return_sales = self.model.copy(sales)
+ for return_sale, sale in zip(return_sales, sales):
+ return_sale.origin = sale
+ for line in return_sale.lines:
+ if line.type == 'line':
+ line.quantity *= -1
+ return_sale.lines = return_sale.lines # Force saving
+ self.model.save(return_sales)
+
+ data = {'res_id': [s.id for s in return_sales]}
+ if len(return_sales) == 1:
+ action['views'].reverse()
+ return action, data
+
+
+class ModifyHeaderStateView(StateView):
+ def get_view(self, wizard, state_name):
+ with Transaction().set_context(modify_header=True):
+ return super(ModifyHeaderStateView, self).get_view(
+ wizard, state_name)
+
+
+class ModifyHeader(Wizard):
+ "Modify Header"
+ __name__ = 'sale.modify_header'
+ start = ModifyHeaderStateView('sale.sale',
+ 'sale.modify_header_form', [
+ Button("Cancel", 'end', 'tryton-cancel'),
+ Button("Modify", 'modify', 'tryton-ok', default=True),
+ ])
+ modify = StateTransition()
+
+ def get_sale(self):
+ if self.record.state != 'draft':
+ raise AccessError(
+ gettext('sale.msg_sale_modify_header_draft',
+ sale=self.record.rec_name))
+ return self.record
+
+ def default_start(self, fields):
+ sale = self.get_sale()
+ defaults = {}
+ for fieldname in fields:
+ value = getattr(sale, fieldname)
+ if isinstance(value, Model):
+ if getattr(sale.__class__, fieldname)._type == 'reference':
+ value = str(value)
+ else:
+ value = value.id
+ elif isinstance(value, (list, tuple)):
+ value = [r.id for r in value]
+ defaults[fieldname] = value
+
+ # Mimic an empty sale in draft state to get the fields' states right
+ defaults['lines'] = []
+ return defaults
+
+ def transition_modify(self):
+ pool = Pool()
+ Line = pool.get('sale.line')
+
+ sale = self.get_sale()
+ self.model.write([sale], self.start._save_values)
+
+ # Call on_change after the save to ensure parent sale
+ # has the modified values
+ for line in sale.lines:
+ line.on_change_product()
+ Line.save(sale.lines)
+
+ return 'end'
diff --git a/modules/sale/sale.xml b/modules/sale/sale.xml
new file mode 100644
index 0000000000..d832b6686a
--- /dev/null
+++ b/modules/sale/sale.xml
@@ -0,0 +1,531 @@
+
+
+
+
+
+ Sales
+
+
+ Sales Administrator
+
+
+
+
+
+
+
+
+
+
+
+
+ tryton-sale
+ icons/tryton-sale.svg
+
+
+
+
+
+
+
+
+
+ Handle Shipment Exception
+ sale.handle.shipment.exception
+ sale.sale
+
+
+
+ Handle Invoice Exception
+ sale.handle.invoice.exception
+ sale.sale
+
+
+
+ sale.sale
+ form
+ sale_form
+
+
+ sale.sale
+ tree
+ sale_tree
+
+
+
+ sale.handle.shipment.exception.ask
+ form
+ handle_shipment_exception_ask_form
+
+
+
+ sale.handle.invoice.exception.ask
+ form
+ handle_invoice_exception_ask_form
+
+
+
+ Shipments
+ stock.shipment.out
+
+
+
+ form_relate
+ sale.sale,-1
+
+
+
+ Returns
+ stock.shipment.out.return
+
+
+
+ form_relate
+ sale.sale,-1
+
+
+
+ Invoices
+ account.invoice
+
+
+
+ form_relate
+ sale.sale,-1
+
+
+
+
+ Sales
+ sale.sale
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Draft
+
+
+
+
+
+
+ Quotation
+
+
+
+
+
+
+ Confirmed
+
+
+
+
+
+
+ Processing
+
+
+
+
+
+
+ Exception
+
+
+
+
+
+
+ All
+
+
+
+
+
+
+
+
+
+
+
+
+ Sales
+ sale.sale
+
+
+
+
+
+
+
+
+
+
+
+
+
+ form_relate
+ account.invoice,-1
+
+
+
+
+ Sales
+ sale.sale
+
+
+
+
+
+
+
+
+
+
+
+
+
+ form_relate
+ stock.shipment.out,-1
+
+
+
+
+ Sales
+ sale.sale
+
+
+
+
+
+
+
+
+
+
+
+
+
+ form_relate
+ stock.shipment.out.return,-1
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ cancel
+ Cancel
+
+
+
+
+
+
+
+
+ draft
+ Draft
+
+
+
+
+
+
+
+
+ quote
+ Quote
+
+
+
+
+
+
+
+
+ confirm
+ Confirm
+
+
+
+
+
+
+
+
+ process
+ Process
+
+
+
+
+
+
+
+ modify_header
+ Modify Header
+
+
+
+
+
+
+
+
+ handle_shipment_exception
+ Handle Shipment Exception
+
+
+
+
+
+
+
+
+ handle_invoice_exception
+ Handle Invoice Exception
+
+
+
+
+
+
+
+
+ Sale
+
+
+
+
+
+
+
+
+
+
+
+ Sale
+
+
+
+
+ Sale
+ sale.sale
+ sale.sale
+ sale/sale.fodt
+
+
+ form_print
+ sale.sale,-1
+
+
+
+
+ sale.line
+ form
+ sale_line_form
+
+
+
+ sale.line
+ tree
+
+ sale_line_tree
+
+
+
+ sale.line
+ tree
+
+ sale_line_tree_sequence
+
+
+
+ product.template
+
+ template_form
+
+
+ product.template
+
+ template_tree
+
+
+
+ party.party
+
+ party_form
+
+
+ Parties associated to Sales
+ sale.open_customer
+
+
+
+
+ sale.return_sale.start
+ form
+ return_sale_start_form
+
+
+
+ Return Sale
+ sale.return_sale
+ sale.sale
+
+
+ form_action
+ sale.sale,-1
+
+
+
+
+ Modify Header
+ sale.modify_header
+ sale.sale
+
+
+ sale.sale
+
+ modify_header_form
+
+
+
+
+ User in companies
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/modules/sale/sale_reporting.py b/modules/sale/sale_reporting.py
new file mode 100644
index 0000000000..8df510254f
--- /dev/null
+++ b/modules/sale/sale_reporting.py
@@ -0,0 +1,763 @@
+# This file is part of Tryton. The COPYRIGHT file at the top level of
+# this repository contains the full copyright notices and license terms.
+from collections import defaultdict
+from itertools import tee, zip_longest
+
+try:
+ import pygal
+except ImportError:
+ pygal = None
+from dateutil.relativedelta import relativedelta
+from sql import Null, Literal, Column, With
+from sql.aggregate import Sum, Max, Min, Count
+from sql.conditionals import Coalesce
+from sql.functions import CurrentTimestamp, DateTrunc, Power, Ceil, Log
+
+from trytond.pool import Pool
+from trytond.model import ModelSQL, ModelView, UnionMixin, fields
+from trytond.tools import grouped_slice, reduce_ids
+from trytond.transaction import Transaction
+from trytond.pyson import Eval, If
+from trytond.wizard import Wizard, StateTransition, StateAction
+from trytond.i18n import lazy_gettext
+
+
+def pairwise(iterable):
+ a, b = tee(iterable)
+ next(b)
+ return zip_longest(a, b)
+
+
+class Abstract(ModelSQL):
+
+ company = fields.Many2One(
+ 'company.company', lazy_gettext("sale.msg_sale_reporting_company"))
+ number = fields.Integer(lazy_gettext("sale.msg_sale_reporting_number"),
+ help=lazy_gettext("sale.msg_sale_reporting_number_help"))
+ revenue = fields.Numeric(
+ lazy_gettext("sale.msg_sale_reporting_revenue"),
+ digits=(16, Eval('currency_digits', 2)),
+ depends=['currency_digits'])
+ revenue_trend = fields.Function(
+ fields.Char(lazy_gettext("sale.msg_sale_reporting_revenue_trend")),
+ 'get_trend')
+ time_series = None
+
+ currency = fields.Function(fields.Many2One(
+ 'currency.currency',
+ lazy_gettext("sale.msg_sale_reporting_currency")),
+ 'get_currency')
+ currency_digits = fields.Function(
+ fields.Integer(
+ lazy_gettext("sale.msg_sale_reporting_currency_digits")),
+ 'get_currency_digits')
+
+ @classmethod
+ def table_query(cls):
+ from_item, tables, withs = cls._joins()
+ return from_item.select(*cls._columns(tables, withs),
+ where=cls._where(tables, withs),
+ group_by=cls._group_by(tables, withs),
+ with_=withs.values())
+
+ @classmethod
+ def _joins(cls):
+ pool = Pool()
+ Company = pool.get('company.company')
+ Currency = pool.get('currency.currency')
+ Line = pool.get('sale.line')
+ Sale = pool.get('sale.sale')
+
+ tables = {}
+ tables['line'] = line = Line.__table__()
+ tables['line.sale'] = sale = Sale.__table__()
+ tables['line.sale.company'] = company = Company.__table__()
+ withs = {}
+ currency_sale = With(query=Currency.currency_rate_sql())
+ withs['currency_sale'] = currency_sale
+ currency_company = With(query=Currency.currency_rate_sql())
+ withs['currency_company'] = currency_company
+
+ from_item = (line
+ .join(sale, condition=line.sale == sale.id)
+ .join(currency_sale,
+ condition=(sale.currency == currency_sale.currency)
+ & (currency_sale.start_date <= sale.sale_date)
+ & ((currency_sale.end_date == Null)
+ | (currency_sale.end_date > sale.sale_date))
+ )
+ .join(company, condition=sale.company == company.id)
+ .join(currency_company,
+ condition=(company.currency == currency_company.currency)
+ & (currency_company.start_date <= sale.sale_date)
+ & ((currency_company.end_date == Null)
+ | (currency_company.end_date > sale.sale_date))
+ ))
+ return from_item, tables, withs
+
+ @classmethod
+ def _columns(cls, tables, withs):
+ line = tables['line']
+ sale = tables['line.sale']
+ currency_company = withs['currency_company']
+ currency_sale = withs['currency_sale']
+
+ quantity = Coalesce(line.actual_quantity, line.quantity)
+ revenue = cls.revenue.sql_cast(
+ Sum(quantity * line.unit_price
+ * currency_company.rate / currency_sale.rate))
+ return [
+ cls._column_id(tables, withs).as_('id'),
+ Literal(0).as_('create_uid'),
+ CurrentTimestamp().as_('create_date'),
+ cls.write_uid.sql_cast(Literal(Null)).as_('write_uid'),
+ cls.write_date.sql_cast(Literal(Null)).as_('write_date'),
+ sale.company.as_('company'),
+ revenue.as_('revenue'),
+ Count(sale.id, distinct=True).as_('number'),
+ ]
+
+ @classmethod
+ def _column_id(cls, tables, withs):
+ line = tables['line']
+ return Min(line.id)
+
+ @classmethod
+ def _group_by(cls, tables, withs):
+ sale = tables['line.sale']
+ return [sale.company]
+
+ @classmethod
+ def _where(cls, tables, withs):
+ context = Transaction().context
+ sale = tables['line.sale']
+
+ where = sale.company == context.get('company')
+ where &= sale.state.in_(cls._sale_states())
+ from_date = context.get('from_date')
+ if from_date:
+ where &= sale.sale_date >= from_date
+ to_date = context.get('to_date')
+ if to_date:
+ where &= sale.sale_date <= to_date
+ warehouse = context.get('warehouse')
+ if warehouse:
+ where &= sale.warehouse == warehouse
+ return where
+
+ @classmethod
+ def _sale_states(cls):
+ return ['confirmed', 'processing', 'done']
+
+ @property
+ def time_series_all(self):
+ delta = self._period_delta()
+ for ts, next_ts in pairwise(self.time_series or []):
+ yield ts
+ if delta and next_ts:
+ date = ts.date + delta
+ while date < next_ts.date:
+ yield None
+ date += delta
+
+ @classmethod
+ def _period_delta(cls):
+ context = Transaction().context
+ return {
+ 'year': relativedelta(years=1),
+ 'month': relativedelta(months=1),
+ 'day': relativedelta(days=1),
+ }.get(context.get('period'))
+
+ def get_trend(self, name):
+ name = name[:-len('_trend')]
+ if pygal:
+ chart = pygal.Line()
+ chart.add('', [getattr(ts, name) if ts else 0
+ for ts in self.time_series_all])
+ return chart.render_sparktext()
+
+ def get_currency(self, name):
+ return self.company.currency.id
+
+ def get_currency_digits(self, name):
+ return self.company.currency.digits
+
+
+class AbstractTimeseries(Abstract):
+
+ date = fields.Date("Date")
+
+ @classmethod
+ def __setup__(cls):
+ super(AbstractTimeseries, cls).__setup__()
+ cls._order = [('date', 'ASC')]
+
+ @classmethod
+ def _columns(cls, tables, withs):
+ return super(AbstractTimeseries, cls)._columns(tables, withs) + [
+ cls._column_date(tables, withs).as_('date')]
+
+ @classmethod
+ def _column_date(cls, tables, withs):
+ context = Transaction().context
+ sale = tables['line.sale']
+ date = DateTrunc(context.get('period'), sale.sale_date)
+ date = cls.date.sql_cast(date)
+ return date
+
+ @classmethod
+ def _group_by(cls, tables, withs):
+ return super(AbstractTimeseries, cls)._group_by(tables, withs) + [
+ cls._column_date(tables, withs)]
+
+
+class Context(ModelView):
+ "Sale Reporting Context"
+ __name__ = 'sale.reporting.context'
+
+ company = fields.Many2One('company.company', "Company", required=True)
+ from_date = fields.Date("From Date",
+ domain=[
+ If(Eval('to_date') & Eval('from_date'),
+ ('from_date', '<=', Eval('to_date')),
+ ()),
+ ],
+ depends=['to_date'])
+ to_date = fields.Date("To Date",
+ domain=[
+ If(Eval('from_date') & Eval('to_date'),
+ ('to_date', '>=', Eval('from_date')),
+ ()),
+ ],
+ depends=['from_date'])
+ period = fields.Selection([
+ ('year', "Year"),
+ ('month', "Month"),
+ ('day', "Day"),
+ ], "Period", required=True)
+ warehouse = fields.Many2One(
+ 'stock.location', "Warehouse",
+ domain=[
+ ('type', '=', 'warehouse'),
+ ])
+
+ @classmethod
+ def default_company(cls):
+ return Transaction().context.get('company')
+
+ @classmethod
+ def default_from_date(cls):
+ pool = Pool()
+ Date = pool.get('ir.date')
+ context = Transaction().context
+ if 'from_date' in context:
+ return context['from_date']
+ return Date.today() - relativedelta(years=1)
+
+ @classmethod
+ def default_to_date(cls):
+ pool = Pool()
+ Date = pool.get('ir.date')
+ context = Transaction().context
+ if 'to_date' in context:
+ return context['to_date']
+ return Date.today()
+
+ @classmethod
+ def default_period(cls):
+ return Transaction().context.get('period', 'month')
+
+ @classmethod
+ def default_warehouse(cls):
+ return Transaction().context.get('warehouse')
+
+
+class CustomerMixin(object):
+ __slots__ = ()
+ customer = fields.Many2One(
+ 'party.party', "Customer",
+ context={
+ 'company': Eval('company', -1),
+ },
+ depends=['company'])
+
+ @classmethod
+ def _columns(cls, tables, withs):
+ sale = tables['line.sale']
+ return super(CustomerMixin, cls)._columns(tables, withs) + [
+ sale.party.as_('customer')]
+
+ @classmethod
+ def _group_by(cls, tables, withs):
+ sale = tables['line.sale']
+ return super(CustomerMixin, cls)._group_by(tables, withs) + [
+ sale.party]
+
+ def get_rec_name(self, name):
+ return self.customer.rec_name
+
+
+class Customer(CustomerMixin, Abstract, ModelView):
+ "Sale Reporting per Customer"
+ __name__ = 'sale.reporting.customer'
+
+ time_series = fields.One2Many(
+ 'sale.reporting.customer.time_series', 'customer', "Time Series")
+
+ @classmethod
+ def __setup__(cls):
+ super().__setup__()
+ cls._order.insert(0, ('customer', 'ASC'))
+
+ @classmethod
+ def _column_id(cls, tables, withs):
+ sale = tables['line.sale']
+ return sale.party
+
+
+class CustomerTimeseries(CustomerMixin, AbstractTimeseries, ModelView):
+ "Sale Reporting per Customer"
+ __name__ = 'sale.reporting.customer.time_series'
+
+
+class ProductMixin(object):
+ __slots__ = ()
+ product = fields.Many2One(
+ 'product.product', "Product",
+ context={
+ 'company': Eval('company', -1),
+ },
+ depends=['company'])
+
+ @classmethod
+ def _columns(cls, tables, withs):
+ line = tables['line']
+ return super(ProductMixin, cls)._columns(tables, withs) + [
+ line.product.as_('product')]
+
+ @classmethod
+ def _group_by(cls, tables, withs):
+ line = tables['line']
+ return super(ProductMixin, cls)._group_by(tables, withs) + [
+ line.product]
+
+ @classmethod
+ def _where(cls, tables, withs):
+ line = tables['line']
+ where = super(ProductMixin, cls)._where(tables, withs)
+ where &= line.product != Null
+ return where
+
+ def get_rec_name(self, name):
+ return self.product.rec_name if self.product else None
+
+
+class Product(ProductMixin, Abstract, ModelView):
+ "Sale Reporting per Product"
+ __name__ = 'sale.reporting.product'
+
+ time_series = fields.One2Many(
+ 'sale.reporting.product.time_series', 'product', "Time Series")
+
+ @classmethod
+ def __setup__(cls):
+ super().__setup__()
+ cls._order.insert(0, ('product', 'ASC'))
+
+ @classmethod
+ def _column_id(cls, tables, withs):
+ line = tables['line']
+ return line.product
+
+
+class ProductTimeseries(ProductMixin, AbstractTimeseries, ModelView):
+ "Sale Reporting per Product"
+ __name__ = 'sale.reporting.product.time_series'
+
+
+class CategoryMixin(object):
+ __slots__ = ()
+ category = fields.Many2One(
+ 'product.category', "Category",
+ context={
+ 'company': Eval('company', -1),
+ },
+ depends=['company'])
+
+ @classmethod
+ def _joins(cls):
+ pool = Pool()
+ Product = pool.get('product.product')
+ TemplateCategory = pool.get('product.template-product.category.all')
+ from_item, tables, withs = super(CategoryMixin, cls)._joins()
+ if 'line.product' not in tables:
+ product = Product.__table__()
+ tables['line.product'] = product
+ line = tables['line']
+ from_item = (from_item
+ .join(product, condition=line.product == product.id))
+ if 'line.product.template_category' not in tables:
+ template_category = TemplateCategory.__table__()
+ tables['line.product.template_category'] = template_category
+ product = tables['line.product']
+ from_item = (from_item
+ .join(template_category,
+ condition=product.template == template_category.template))
+ return from_item, tables, withs
+
+ @classmethod
+ def _columns(cls, tables, withs):
+ template_category = tables['line.product.template_category']
+ return super(CategoryMixin, cls)._columns(tables, withs) + [
+ template_category.category.as_('category')]
+
+ @classmethod
+ def _column_id(cls, tables, withs):
+ pool = Pool()
+ Category = pool.get('product.category')
+ category = Category.__table__()
+ line = tables['line']
+ template_category = tables['line.product.template_category']
+ # Get a stable number of category over time
+ # by using number one order bigger.
+ nb_category = category.select(
+ Power(10, (Ceil(Log(Max(category.id))) + Literal(1))))
+ return Min(line.id * nb_category + template_category.id)
+
+ @classmethod
+ def _group_by(cls, tables, withs):
+ template_category = tables['line.product.template_category']
+ return super(CategoryMixin, cls)._group_by(tables, withs) + [
+ template_category.category]
+
+ @classmethod
+ def _where(cls, tables, withs):
+ template_category = tables['line.product.template_category']
+ where = super(CategoryMixin, cls)._where(tables, withs)
+ where &= template_category.category != Null
+ return where
+
+ def get_rec_name(self, name):
+ return self.category.rec_name if self.category else None
+
+
+class Category(CategoryMixin, Abstract, ModelView):
+ "Sale Reporting per Category"
+ __name__ = 'sale.reporting.category'
+
+ time_series = fields.One2Many(
+ 'sale.reporting.category.time_series', 'category', "Time Series")
+
+ @classmethod
+ def __setup__(cls):
+ super().__setup__()
+ cls._order.insert(0, ('category', 'ASC'))
+
+ @classmethod
+ def _column_id(cls, tables, withs):
+ template_category = tables['line.product.template_category']
+ return template_category.category
+
+
+class CategoryTimeseries(CategoryMixin, AbstractTimeseries, ModelView):
+ "Sale Reporting per Category"
+ __name__ = 'sale.reporting.category.time_series'
+
+
+class CategoryTree(ModelSQL, ModelView):
+ "Sale Reporting per Category"
+ __name__ = 'sale.reporting.category.tree'
+
+ name = fields.Function(fields.Char("Name"), 'get_name')
+ parent = fields.Many2One('sale.reporting.category.tree', "Parent")
+ children = fields.One2Many(
+ 'sale.reporting.category.tree', 'parent', "Children")
+ revenue = fields.Function(
+ fields.Numeric("Revenue", digits=(16, Eval('currency_digits', 2)),
+ depends=['currency_digits']), 'get_total')
+
+ currency_digits = fields.Function(
+ fields.Integer("Currency Digits"), 'get_currency_digits')
+
+ @classmethod
+ def __setup__(cls):
+ super().__setup__()
+ cls._order.insert(0, ('name', 'ASC'))
+
+ @classmethod
+ def table_query(cls):
+ pool = Pool()
+ Category = pool.get('product.category')
+ return Category.__table__()
+
+ @classmethod
+ def get_name(cls, categories, name):
+ pool = Pool()
+ Category = pool.get('product.category')
+ categories = Category.browse(categories)
+ return {c.id: c.name for c in categories}
+
+ @classmethod
+ def order_name(cls, tables):
+ pool = Pool()
+ Category = pool.get('product.category')
+ table, _ = tables[None]
+ if 'category' not in tables:
+ category = Category.__table__()
+ tables['category'] = {
+ None: (category, table.id == category.id),
+ }
+ return Category.name.convert_order(
+ 'name', tables['category'], Category)
+
+ def time_series_all(self):
+ return []
+
+ @classmethod
+ def get_total(cls, categories, names):
+ pool = Pool()
+ ReportingCategory = pool.get('sale.reporting.category')
+ table = cls.__table__()
+ reporting_category = ReportingCategory.__table__()
+ cursor = Transaction().connection.cursor()
+
+ categories = cls.search([
+ ('parent', 'child_of', [c.id for c in categories]),
+ ])
+ ids = [c.id for c in categories]
+ parents = {}
+ reporting_categories = []
+ for sub_ids in grouped_slice(ids):
+ sub_ids = list(sub_ids)
+ where = reduce_ids(table.id, sub_ids)
+ cursor.execute(*table.select(table.id, table.parent, where=where))
+ parents.update(cursor)
+
+ where = reduce_ids(reporting_category.id, sub_ids)
+ cursor.execute(
+ *reporting_category.select(reporting_category.id, where=where))
+ reporting_categories.extend(r for r, in cursor)
+
+ result = {}
+ reporting_categories = ReportingCategory.browse(reporting_categories)
+ for name in names:
+ values = dict.fromkeys(ids, 0)
+ values.update(
+ (c.id, getattr(c, name)) for c in reporting_categories)
+ result[name] = cls._sum_tree(categories, values, parents)
+ return result
+
+ @classmethod
+ def _sum_tree(cls, categories, values, parents):
+ result = values.copy()
+ categories = set((c.id for c in categories))
+ leafs = categories - set(parents.values())
+ while leafs:
+ for category in leafs:
+ categories.remove(category)
+ parent = parents.get(category)
+ if parent in result:
+ result[parent] += result[category]
+ next_leafs = set(categories)
+ for category in categories:
+ parent = parents.get(category)
+ if not parent:
+ continue
+ if parent in next_leafs and parent in categories:
+ next_leafs.remove(parent)
+ leafs = next_leafs
+ return result
+
+ def get_currency_digits(self, name):
+ pool = Pool()
+ Company = pool.get('company.company')
+ company = Transaction().context.get('company')
+ if company:
+ return Company(company).currency.digits
+
+
+class CountryMixin(object):
+ __slots__ = ()
+ country = fields.Many2One('country.country', "Country")
+
+ @classmethod
+ def _joins(cls):
+ pool = Pool()
+ Address = pool.get('party.address')
+ from_item, tables, withs = super(CountryMixin, cls)._joins()
+ if 'line.sale.shipment_address' not in tables:
+ address = Address.__table__()
+ tables['line.sale.shipment_address'] = address
+ sale = tables['line.sale']
+ from_item = (from_item
+ .join(address, condition=sale.shipment_address == address.id))
+ return from_item, tables, withs
+
+ @classmethod
+ def _columns(cls, tables, withs):
+ address = tables['line.sale.shipment_address']
+ return super(CountryMixin, cls)._columns(tables, withs) + [
+ address.country.as_('country')]
+
+ @classmethod
+ def _group_by(cls, tables, withs):
+ address = tables['line.sale.shipment_address']
+ return super(CountryMixin, cls)._group_by(tables, withs) + [
+ address.country]
+
+ @classmethod
+ def _where(cls, tables, withs):
+ address = tables['line.sale.shipment_address']
+ where = super(CountryMixin, cls)._where(tables, withs)
+ where &= address.country != Null
+ return where
+
+
+class Country(CountryMixin, Abstract):
+ "Sale Reporting per Country"
+ __name__ = 'sale.reporting.country'
+
+ time_series = fields.One2Many(
+ 'sale.reporting.country.time_series', 'country', "Time Series")
+
+ @classmethod
+ def __setup__(cls):
+ super().__setup__()
+ cls._order.insert(0, ('country', 'ASC'))
+
+ @classmethod
+ def _column_id(cls, tables, withs):
+ address = tables['line.sale.shipment_address']
+ return address.country
+
+ def get_rec_name(self, name):
+ return self.country.rec_name
+
+
+class CountryTimeseries(CountryMixin, AbstractTimeseries, ModelView):
+ "Sale Reporting per Country"
+ __name__ = 'sale.reporting.country.time_series'
+
+
+class SubdivisionMixin(CountryMixin):
+ __slots__ = ()
+ subdivision = fields.Many2One('country.subdivision', "Subdivision")
+
+ @classmethod
+ def _columns(cls, tables, withs):
+ address = tables['line.sale.shipment_address']
+ return super(SubdivisionMixin, cls)._columns(tables, withs) + [
+ address.subdivision.as_('subdivision')]
+
+ @classmethod
+ def _group_by(cls, tables, withs):
+ address = tables['line.sale.shipment_address']
+ return super(SubdivisionMixin, cls)._group_by(tables, withs) + [
+ address.subdivision]
+
+ @classmethod
+ def _where(cls, tables, withs):
+ address = tables['line.sale.shipment_address']
+ where = super(SubdivisionMixin, cls)._where(tables, withs)
+ where &= address.subdivision != Null
+ return where
+
+
+class Subdivision(SubdivisionMixin, Abstract):
+ "Sale Reporting per Subdivision"
+ __name__ = 'sale.reporting.country.subdivision'
+
+ time_series = fields.One2Many(
+ 'sale.reporting.country.subdivision.time_series', 'subdivision',
+ "Time Series")
+
+ @classmethod
+ def __setup__(cls):
+ super().__setup__()
+ cls._order.insert(0, ('subdivision', 'ASC'))
+
+ @classmethod
+ def _column_id(cls, tables, withs):
+ address = tables['line.sale.shipment_address']
+ return address.subdivision
+
+ def get_rec_name(self, name):
+ return self.subdivision.rec_name
+
+
+class SubdivisionTimeseries(SubdivisionMixin, AbstractTimeseries, ModelView):
+ "Sale Reporting per Subdivision"
+ __name__ = 'sale.reporting.country.subdivision.time_series'
+
+
+class Region(UnionMixin, Abstract, ModelView):
+ "Sale Reporting per Region"
+ __name__ = 'sale.reporting.region'
+
+ region = fields.Function(fields.Char("Region"), 'get_rec_name')
+ parent = fields.Many2One('sale.reporting.region', "Parent")
+ children = fields.One2Many('sale.reporting.region', 'parent', "Children")
+
+ @classmethod
+ def union_models(cls):
+ return ['sale.reporting.country', 'sale.reporting.country.subdivision']
+
+ @classmethod
+ def union_column(cls, name, field, table, Model):
+ column = super(Region, cls).union_column(
+ name, field, table, Model)
+ if (name == 'parent'
+ and Model.__name__ == 'sale.reporting.country.subdivision'):
+ column = cls.union_shard(
+ Column(table, 'country'), 'sale.reporting.country')
+ return column
+
+ @classmethod
+ def get_rec_name(cls, records, name):
+ names = {}
+ classes = defaultdict(list)
+ for record in records:
+ record = cls.union_unshard(record.id)
+ classes[record.__class__].append(record)
+ for klass, records in classes.items():
+ for record in klass.browse(records):
+ names[cls.union_shard(record.id, klass.__name__)] = (
+ record.rec_name)
+ return names
+
+ @property
+ def time_series(self):
+ record = self.union_unshard(self.id)
+ return record.time_series
+
+
+class OpenRegion(Wizard):
+ "Open Region"
+ __name__ = 'sale.reporting.region.open'
+
+ start = StateTransition()
+ country = StateAction('sale.act_reporting_country_time_series')
+ subdivision = StateAction(
+ 'sale.act_reporting_country_subdivision_time_series')
+
+ def transition_start(self):
+ pool = Pool()
+ Country = pool.get('sale.reporting.country')
+ Subdivision = pool.get('sale.reporting.country.subdivision')
+ record = self.model.union_unshard(self.record.id)
+ if isinstance(record, Country):
+ return 'country'
+ elif isinstance(record, Subdivision):
+ return 'subdivision'
+
+ def _do_action(self, action):
+ record = self.model.union_unshard(self.record.id)
+ data = {
+ 'id': record.id,
+ 'ids': [record.id],
+ }
+ action['name'] += ' (%s)' % record.rec_name
+ return action, data
+ do_country = _do_action
+ do_subdivision = _do_action
diff --git a/modules/sale/sale_reporting.xml b/modules/sale/sale_reporting.xml
new file mode 100644
index 0000000000..9857a7fc3e
--- /dev/null
+++ b/modules/sale/sale_reporting.xml
@@ -0,0 +1,692 @@
+
+
+
+
+
+
+
+
+
+ sale.reporting.context
+ form
+ sale_reporting_context_form
+
+
+
+
+
+ sale.reporting.customer
+ tree
+ sale_reporting_customer_list
+
+
+
+ sale.reporting.customer
+ graph
+ sale_reporting_customer_graph_revenue
+
+
+
+ sale.reporting.customer
+ graph
+ sale_reporting_customer_graph_number
+
+
+
+ Sales per Customer
+ sale.reporting.customer
+ sale.reporting.context
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ tree_open
+
+
+
+
+
+ User in companies
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ sale.reporting.customer.time_series
+ tree
+ sale_reporting_customer_time_series_list
+
+
+
+ sale.reporting.customer.time_series
+ graph
+ sale_reporting_customer_time_series_graph_revenue
+
+
+
+ sale.reporting.customer.time_series
+ graph
+ sale_reporting_customer_time_series_graph_number
+
+
+
+ Sales per Customer
+ sale.reporting.customer.time_series
+ sale.reporting.context
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ tree_open
+ sale.reporting.customer,-1
+
+
+
+
+ User in companies
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ sale.reporting.product
+ tree
+ sale_reporting_product_list
+
+
+
+ sale.reporting.product
+ graph
+ sale_reporting_product_graph_revenue
+
+
+
+ sale.reporting.product
+ graph
+ sale_reporting_product_graph_number
+
+
+
+ Sales per Product
+ sale.reporting.product
+ sale.reporting.context
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ tree_open
+
+
+
+
+
+ User in companies
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ sale.reporting.product.time_series
+ tree
+ sale_reporting_product_time_series_list
+
+
+
+ sale.reporting.product.time_series
+ graph
+ sale_reporting_product_time_series_graph_revenue
+
+
+
+ sale.reporting.product.time_series
+ graph
+ sale_reporting_product_time_series_graph_number
+
+
+
+ Sales per Product
+ sale.reporting.product.time_series
+ sale.reporting.context
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ tree_open
+ sale.reporting.product,-1
+
+
+
+
+ User in companies
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ sale.reporting.category.tree
+ tree
+ children
+ sale_reporting_category_tree
+
+
+
+ Sales per Category
+ sale.reporting.category.tree
+ sale.reporting.context
+
+
+
+
+
+
+
+
+ tree_open
+
+
+
+
+
+ sale.reporting.category
+ tree
+ sale_reporting_category_list
+
+
+
+ Sales per Category
+ sale.reporting.category
+ sale.reporting.context
+
+
+
+
+
+
+
+
+ tree_open
+ sale.reporting.category.tree,-1
+
+
+
+
+ User in companies
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ sale.reporting.category.time_series
+ tree
+ sale_reporting_category_time_series_list
+
+
+
+ sale.reporting.category.time_series
+ graph
+ sale_reporting_category_time_series_graph_revenue
+
+
+
+ sale.reporting.category.time_series
+ graph
+ sale_reporting_category_time_series_graph_number
+
+
+
+ Sales per Category
+ sale.reporting.category.time_series
+ sale.reporting.context
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ tree_open
+ sale.reporting.category,-1
+
+
+
+
+ User in companies
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ sale.reporting.region
+ tree
+ sale_reporting_region_tree
+ children
+
+
+
+ Sales per Region
+ sale.reporting.region
+ sale.reporting.context
+
+
+
+
+
+
+
+
+ tree_open
+
+
+
+
+
+ User in companies
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ sale.reporting.country.time_series
+ tree
+ sale_reporting_country_time_series_list
+
+
+
+ sale.reporting.country.time_series
+ graph
+ sale_reporting_country_time_series_graph_revenue
+
+
+
+ sale.reporting.country.time_series
+ graph
+ sale_reporting_country_time_series_graph_number
+
+
+
+ Sales per Country
+ sale.reporting.country.time_series
+ sale.reporting.context
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ User in companies
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ sale.reporting.country.subdivision.time_series
+ tree
+ sale_reporting_country_subdivision_time_series_list
+
+
+
+ sale.reporting.country.subdivision.time_series
+ graph
+ sale_reporting_country_subdivision_time_series_graph_revenue
+
+
+
+ sale.reporting.country.subdivision.time_series
+ graph
+ sale_reporting_country_subdivision_time_series_graph_number
+
+
+
+ Sales per Subdivision
+ sale.reporting.country.subdivision.time_series
+ sale.reporting.context
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ User in companies
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Open Region
+ sale.reporting.region.open
+ sale.reporting.region
+
+
+ tree_open
+ sale.reporting.region,-1
+
+
+
+
+
diff --git a/modules/sale/setup.py b/modules/sale/setup.py
new file mode 100755
index 0000000000..bff76c956b
--- /dev/null
+++ b/modules/sale/setup.py
@@ -0,0 +1,156 @@
+#!/usr/bin/env python3
+# This file is part of Tryton. The COPYRIGHT file at the top level of
+# this repository contains the full copyright notices and license terms.
+
+import io
+import os
+import re
+from configparser import ConfigParser
+from setuptools import setup, find_packages
+
+
+def read(fname):
+ content = io.open(
+ os.path.join(os.path.dirname(__file__), fname),
+ 'r', encoding='utf-8').read()
+ content = re.sub(
+ r'(?m)^\.\. toctree::\r?\n((^$|^\s.*$)\r?\n)*', '', content)
+ return content
+
+
+def get_require_version(name):
+ if minor_version % 2:
+ require = '%s >= %s.%s.dev0, < %s.%s'
+ else:
+ require = '%s >= %s.%s, < %s.%s'
+ require %= (name, major_version, minor_version,
+ major_version, minor_version + 1)
+ return require
+
+
+config = ConfigParser()
+config.read_file(open(os.path.join(os.path.dirname(__file__), 'tryton.cfg')))
+info = dict(config.items('tryton'))
+for key in ('depends', 'extras_depend', 'xml'):
+ if key in info:
+ info[key] = info[key].strip().splitlines()
+version = info.get('version', '0.0.1')
+major_version, minor_version, _ = version.split('.', 2)
+major_version = int(major_version)
+minor_version = int(minor_version)
+name = 'trytond_sale'
+
+download_url = 'http://downloads.tryton.org/%s.%s/' % (
+ major_version, minor_version)
+if minor_version % 2:
+ version = '%s.%s.dev0' % (major_version, minor_version)
+ download_url = (
+ 'hg+http://hg.tryton.org/modules/%s#egg=%s-%s' % (
+ name[8:], name, version))
+local_version = []
+if os.environ.get('CI_JOB_ID'):
+ local_version.append(os.environ['CI_JOB_ID'])
+else:
+ for build in ['CI_BUILD_NUMBER', 'CI_JOB_NUMBER']:
+ if os.environ.get(build):
+ local_version.append(os.environ[build])
+ else:
+ local_version = []
+ break
+if local_version:
+ version += '+' + '.'.join(local_version)
+
+requires = ['python-sql >= 0.4', 'python-dateutil']
+for dep in info.get('depends', []):
+ if not re.match(r'(ir|res)(\W|$)', dep):
+ requires.append(get_require_version('trytond_%s' % dep))
+requires.append(get_require_version('trytond'))
+
+tests_require = [get_require_version('proteus')]
+dependency_links = []
+if minor_version % 2:
+ dependency_links.append(
+ 'https://trydevpi.tryton.org/?local_version='
+ + '.'.join(local_version))
+
+setup(name=name,
+ version=version,
+ description='Tryton module for sale',
+ long_description=read('README.rst'),
+ author='Tryton',
+ author_email='bugs@tryton.org',
+ url='http://www.tryton.org/',
+ download_url=download_url,
+ project_urls={
+ "Bug Tracker": 'https://bugs.tryton.org/',
+ "Documentation": 'https://docs.tryton.org/projects/modules-sale/',
+ "Forum": 'https://www.tryton.org/forum',
+ "Source Code": 'https://hg.tryton.org/modules/sale',
+ },
+ keywords='tryton sale',
+ package_dir={'trytond.modules.sale': '.'},
+ packages=(
+ ['trytond.modules.sale']
+ + ['trytond.modules.sale.%s' % p for p in find_packages()]
+ ),
+ package_data={
+ 'trytond.modules.sale': (info.get('xml', [])
+ + ['tryton.cfg', 'view/*.xml', 'locale/*.po', '*.fodt',
+ 'tests/*.rst', 'icons/*.svg']),
+ },
+ classifiers=[
+ 'Development Status :: 5 - Production/Stable',
+ 'Environment :: Plugins',
+ 'Framework :: Tryton',
+ 'Intended Audience :: Developers',
+ 'Intended Audience :: Financial and Insurance Industry',
+ 'Intended Audience :: Legal Industry',
+ 'License :: OSI Approved :: '
+ 'GNU General Public License v3 or later (GPLv3+)',
+ 'Natural Language :: Bulgarian',
+ 'Natural Language :: Catalan',
+ 'Natural Language :: Chinese (Simplified)',
+ 'Natural Language :: Czech',
+ 'Natural Language :: Dutch',
+ 'Natural Language :: English',
+ 'Natural Language :: Finnish',
+ 'Natural Language :: French',
+ 'Natural Language :: German',
+ 'Natural Language :: Hungarian',
+ 'Natural Language :: Indonesian',
+ 'Natural Language :: Italian',
+ 'Natural Language :: Persian',
+ 'Natural Language :: Polish',
+ 'Natural Language :: Portuguese (Brazilian)',
+ 'Natural Language :: Romanian',
+ 'Natural Language :: Russian',
+ 'Natural Language :: Slovenian',
+ 'Natural Language :: Spanish',
+ 'Natural Language :: Turkish',
+ 'Operating System :: OS Independent',
+ 'Programming Language :: Python :: 3',
+ 'Programming Language :: Python :: 3.6',
+ 'Programming Language :: Python :: 3.7',
+ 'Programming Language :: Python :: 3.8',
+ 'Programming Language :: Python :: 3.9',
+ 'Programming Language :: Python :: Implementation :: CPython',
+ 'Programming Language :: Python :: Implementation :: PyPy',
+ 'Topic :: Office/Business',
+ 'Topic :: Office/Business :: Financial :: Accounting',
+ ],
+ license='GPL-3',
+ python_requires='>=3.6',
+ install_requires=requires,
+ extras_require={
+ 'sparklines': ['pygal'],
+ },
+ dependency_links=dependency_links,
+ zip_safe=False,
+ entry_points="""
+ [trytond.modules]
+ sale = trytond.modules.sale
+ """,
+ test_suite='tests',
+ test_loader='trytond.test_loader:Loader',
+ tests_require=tests_require,
+ )
diff --git a/modules/sale/stock.py b/modules/sale/stock.py
new file mode 100644
index 0000000000..b461142a04
--- /dev/null
+++ b/modules/sale/stock.py
@@ -0,0 +1,205 @@
+# This file is part of Tryton. The COPYRIGHT file at the top level of
+# this repository contains the full copyright notices and license terms.
+from decimal import Decimal
+from functools import wraps
+
+from trytond.i18n import gettext
+from trytond.model import Workflow, ModelView, fields
+from trytond.model.exceptions import AccessError
+from trytond.transaction import Transaction
+from trytond.pool import Pool, PoolMeta
+
+from trytond.modules.product import round_price
+
+
+def process_sale(moves_field):
+ def _process_sale(func):
+ @wraps(func)
+ def wrapper(cls, shipments):
+ pool = Pool()
+ Sale = pool.get('sale.sale')
+ with Transaction().set_context(_check_access=False):
+ sales = set(m.sale for s in cls.browse(shipments)
+ for m in getattr(s, moves_field) if m.sale)
+ func(cls, shipments)
+ if sales:
+ Sale.__queue__.process(sales)
+ return wrapper
+ return _process_sale
+
+
+class ShipmentOut(metaclass=PoolMeta):
+ __name__ = 'stock.shipment.out'
+
+ @classmethod
+ @ModelView.button
+ @Workflow.transition('draft')
+ def draft(cls, shipments):
+ SaleLine = Pool().get('sale.line')
+ for shipment in shipments:
+ for move in shipment.outgoing_moves:
+ if (move.state == 'cancelled'
+ and isinstance(move.origin, SaleLine)):
+ raise AccessError(
+ gettext('sale.msg_sale_move_reset_draft',
+ move=move.rec_name))
+
+ return super(ShipmentOut, cls).draft(shipments)
+
+ @classmethod
+ @ModelView.button
+ @Workflow.transition('done')
+ @process_sale('outgoing_moves')
+ def done(cls, shipments):
+ super(ShipmentOut, cls).done(shipments)
+
+ @classmethod
+ @ModelView.button
+ @Workflow.transition('cancelled')
+ @process_sale('outgoing_moves')
+ def cancel(cls, shipments):
+ super(ShipmentOut, cls).cancel(shipments)
+
+
+class ShipmentOutReturn(metaclass=PoolMeta):
+ __name__ = 'stock.shipment.out.return'
+
+ @classmethod
+ @ModelView.button
+ @Workflow.transition('draft')
+ def draft(cls, shipments):
+ SaleLine = Pool().get('sale.line')
+ for shipment in shipments:
+ for move in shipment.incoming_moves:
+ if (move.state == 'cancelled'
+ and isinstance(move.origin, SaleLine)):
+ raise AccessError(
+ gettext('sale.msg_sale_move_reset_draft',
+ move=move.rec_name))
+
+ return super(ShipmentOutReturn, cls).draft(shipments)
+
+ @classmethod
+ @ModelView.button
+ @Workflow.transition('received')
+ @process_sale('incoming_moves')
+ def receive(cls, shipments):
+ super(ShipmentOutReturn, cls).receive(shipments)
+
+
+def process_sale_move(func):
+ @wraps(func)
+ def wrapper(cls, moves):
+ pool = Pool()
+ Sale = pool.get('sale.sale')
+ with Transaction().set_context(_check_access=False):
+ sales = set(m.sale for m in cls.browse(moves) if m.sale)
+ func(cls, moves)
+ if sales:
+ Sale.__queue__.process(sales)
+ return wrapper
+
+
+class Move(metaclass=PoolMeta):
+ __name__ = 'stock.move'
+ sale = fields.Function(fields.Many2One('sale.sale', 'Sale', select=True),
+ 'get_sale', searcher='search_sale')
+ sale_exception_state = fields.Function(fields.Selection([
+ ('', ''),
+ ('ignored', 'Ignored'),
+ ('recreated', 'Recreated'),
+ ], 'Exception State'), 'get_sale_exception_state')
+
+ @classmethod
+ def _get_origin(cls):
+ models = super(Move, cls)._get_origin()
+ models.append('sale.line')
+ return models
+
+ @classmethod
+ def check_origin_types(cls):
+ types = super(Move, cls).check_origin_types()
+ types.add('customer')
+ return types
+
+ def get_sale(self, name):
+ SaleLine = Pool().get('sale.line')
+ if isinstance(self.origin, SaleLine):
+ return self.origin.sale.id
+
+ @classmethod
+ def search_sale(cls, name, clause):
+ return [('origin.' + clause[0],) + tuple(clause[1:3])
+ + ('sale.line',) + tuple(clause[3:])]
+
+ def get_sale_exception_state(self, name):
+ SaleLine = Pool().get('sale.line')
+ if not isinstance(self.origin, SaleLine):
+ return ''
+ if self in self.origin.moves_recreated:
+ return 'recreated'
+ if self in self.origin.moves_ignored:
+ return 'ignored'
+ return ''
+
+ @fields.depends('origin')
+ def on_change_with_product_uom_category(self, name=None):
+ pool = Pool()
+ SaleLine = pool.get('sale.line')
+ category = super(Move, self).on_change_with_product_uom_category(
+ name=name)
+ # Enforce the same unit category as they are used to compute the
+ # remaining quantity to ship and the quantity to invoice.
+ # Use getattr as reference field can have negative id
+ if (isinstance(self.origin, SaleLine)
+ and getattr(self.origin, 'unit', None)):
+ category = self.origin.unit.category.id
+ return category
+
+ def get_cost_price(self, product_cost_price=None):
+ pool = Pool()
+ SaleLine = pool.get('sale.line')
+ Sale = pool.get('sale.sale')
+ # For return sale's move use the cost price of the original sale
+ if (isinstance(self.origin, SaleLine)
+ and self.origin.quantity < 0
+ and self.from_location.type != 'storage'
+ and self.to_location.type == 'storage'
+ and isinstance(self.origin.sale.origin, Sale)):
+ sale = self.origin.sale.origin
+ cost = Decimal(0)
+ qty = Decimal(0)
+ for move in sale.moves:
+ if (move.state == 'done'
+ and move.from_location.type == 'storage'
+ and move.to_location.type == 'customer'
+ and move.product == self.product):
+ move_quantity = Decimal(str(move.internal_quantity))
+ cost_price = move.get_cost_price(
+ product_cost_price=move.cost_price)
+ qty += move_quantity
+ cost += cost_price * move_quantity
+ if qty:
+ product_cost_price = round_price(cost / qty)
+ return super().get_cost_price(product_cost_price=product_cost_price)
+
+ @property
+ def origin_name(self):
+ pool = Pool()
+ SaleLine = pool.get('sale.line')
+ name = super(Move, self).origin_name
+ if isinstance(self.origin, SaleLine):
+ name = self.origin.sale.rec_name
+ return name
+
+ @classmethod
+ @ModelView.button
+ @Workflow.transition('cancelled')
+ @process_sale_move
+ def cancel(cls, moves):
+ super(Move, cls).cancel(moves)
+
+ @classmethod
+ @process_sale_move
+ def delete(cls, moves):
+ super(Move, cls).delete(moves)
diff --git a/modules/sale/stock.xml b/modules/sale/stock.xml
new file mode 100644
index 0000000000..5b2cd70f34
--- /dev/null
+++ b/modules/sale/stock.xml
@@ -0,0 +1,37 @@
+
+
+
+
+
+ stock.move
+ tree
+
+ move_list_shipment
+
+
+
+ Moves
+ stock.move
+
+
+
+
+
+
+
+
+
+
+
+
+
+ form_relate
+ sale.sale,-1
+
+
+
+
diff --git a/modules/sale/tests/__init__.py b/modules/sale/tests/__init__.py
new file mode 100644
index 0000000000..4ecb3d8c26
--- /dev/null
+++ b/modules/sale/tests/__init__.py
@@ -0,0 +1,9 @@
+# This file is part of Tryton. The COPYRIGHT file at the top level of
+# this repository contains the full copyright notices and license terms.
+
+try:
+ from trytond.modules.sale.tests.test_sale import suite
+except ImportError:
+ from .test_sale import suite
+
+__all__ = ['suite']
diff --git a/modules/sale/tests/scenario_sale.rst b/modules/sale/tests/scenario_sale.rst
new file mode 100644
index 0000000000..290add38de
--- /dev/null
+++ b/modules/sale/tests/scenario_sale.rst
@@ -0,0 +1,726 @@
+=============
+Sale Scenario
+=============
+
+Imports::
+
+ >>> import datetime
+ >>> from dateutil.relativedelta import relativedelta
+ >>> from decimal import Decimal
+ >>> from operator import attrgetter
+ >>> from proteus import Model, Wizard, Report
+ >>> from trytond.tests.tools import activate_modules, set_user
+ >>> from trytond.modules.company.tests.tools import create_company, \
+ ... get_company
+ >>> from trytond.modules.account.tests.tools import create_fiscalyear, \
+ ... create_chart, get_accounts, create_tax
+ >>> from trytond.modules.account_invoice.tests.tools import \
+ ... set_fiscalyear_invoice_sequences, create_payment_term
+ >>> today = datetime.date.today()
+
+Activate modules::
+
+ >>> config = activate_modules('sale')
+
+Create company::
+
+ >>> _ = create_company()
+ >>> company = get_company()
+
+Set employee::
+
+ >>> User = Model.get('res.user')
+ >>> Party = Model.get('party.party')
+ >>> Employee = Model.get('company.employee')
+ >>> employee_party = Party(name="Employee")
+ >>> employee_party.save()
+ >>> employee = Employee(party=employee_party)
+ >>> employee.save()
+ >>> user = User(config.user)
+ >>> user.employees.append(employee)
+ >>> user.employee = employee
+ >>> user.save()
+ >>> set_user(user.id)
+
+Create fiscal year::
+
+ >>> fiscalyear = set_fiscalyear_invoice_sequences(
+ ... create_fiscalyear(company))
+ >>> fiscalyear.click('create_period')
+
+Create chart of accounts::
+
+ >>> _ = create_chart(company)
+ >>> accounts = get_accounts(company)
+ >>> revenue = accounts['revenue']
+ >>> expense = accounts['expense']
+ >>> cash = accounts['cash']
+
+ >>> Journal = Model.get('account.journal')
+ >>> PaymentMethod = Model.get('account.invoice.payment.method')
+ >>> cash_journal, = Journal.find([('type', '=', 'cash')])
+ >>> cash_journal.save()
+ >>> payment_method = PaymentMethod()
+ >>> payment_method.name = 'Cash'
+ >>> payment_method.journal = cash_journal
+ >>> payment_method.credit_account = cash
+ >>> payment_method.debit_account = cash
+ >>> payment_method.save()
+
+Create tax::
+
+ >>> tax = create_tax(Decimal('.10'))
+ >>> tax.save()
+
+Create parties::
+
+ >>> Party = Model.get('party.party')
+ >>> supplier = Party(name='Supplier')
+ >>> supplier.save()
+ >>> customer = Party(name='Customer')
+ >>> customer.save()
+
+Create account categories::
+
+ >>> ProductCategory = Model.get('product.category')
+ >>> account_category = ProductCategory(name="Account Category")
+ >>> account_category.accounting = True
+ >>> account_category.account_expense = expense
+ >>> account_category.account_revenue = revenue
+ >>> account_category.save()
+
+ >>> account_category_tax, = account_category.duplicate()
+ >>> account_category_tax.customer_taxes.append(tax)
+ >>> account_category_tax.save()
+
+Create product::
+
+ >>> ProductUom = Model.get('product.uom')
+ >>> unit, = ProductUom.find([('name', '=', 'Unit')])
+ >>> ProductTemplate = Model.get('product.template')
+
+ >>> template = ProductTemplate()
+ >>> template.name = 'product'
+ >>> template.default_uom = unit
+ >>> template.type = 'goods'
+ >>> template.salable = True
+ >>> template.list_price = Decimal('10')
+ >>> template.account_category = account_category_tax
+ >>> template.save()
+ >>> product, = template.products
+
+ >>> template = ProductTemplate()
+ >>> template.name = 'service'
+ >>> template.default_uom = unit
+ >>> template.type = 'service'
+ >>> template.salable = True
+ >>> template.list_price = Decimal('30')
+ >>> template.account_category = account_category
+ >>> template.save()
+ >>> service, = template.products
+
+Create payment term::
+
+ >>> payment_term = create_payment_term()
+ >>> payment_term.save()
+
+Create an Inventory::
+
+ >>> Inventory = Model.get('stock.inventory')
+ >>> Location = Model.get('stock.location')
+ >>> storage, = Location.find([
+ ... ('code', '=', 'STO'),
+ ... ])
+ >>> inventory = Inventory()
+ >>> inventory.location = storage
+ >>> inventory_line = inventory.lines.new(product=product)
+ >>> inventory_line.quantity = 100.0
+ >>> inventory_line.expected_quantity = 0.0
+ >>> inventory.click('confirm')
+ >>> inventory.state
+ 'done'
+
+Sale 5 products::
+
+ >>> Sale = Model.get('sale.sale')
+ >>> SaleLine = Model.get('sale.line')
+ >>> sale = Sale()
+ >>> sale.party = customer
+ >>> sale.payment_term = payment_term
+ >>> sale.invoice_method = 'order'
+ >>> sale_line = SaleLine()
+ >>> sale.lines.append(sale_line)
+ >>> sale_line.product = product
+ >>> sale_line.quantity = 2.0
+ >>> sale_line = SaleLine()
+ >>> sale.lines.append(sale_line)
+ >>> sale_line.type = 'comment'
+ >>> sale_line.description = 'Comment'
+ >>> sale_line = SaleLine()
+ >>> sale.lines.append(sale_line)
+ >>> sale_line.product = product
+ >>> sale_line.quantity = 3.0
+ >>> sale.click('quote')
+ >>> sale.untaxed_amount, sale.tax_amount, sale.total_amount
+ (Decimal('50.00'), Decimal('5.00'), Decimal('55.00'))
+ >>> sale.quoted_by == employee
+ True
+ >>> sale.click('confirm')
+ >>> sale.untaxed_amount, sale.tax_amount, sale.total_amount
+ (Decimal('50.00'), Decimal('5.00'), Decimal('55.00'))
+ >>> sale.confirmed_by == employee
+ True
+ >>> sale.state
+ 'processing'
+ >>> sale.shipment_state
+ 'waiting'
+ >>> sale.invoice_state
+ 'waiting'
+ >>> len(sale.shipments), len(sale.shipment_returns), len(sale.invoices)
+ (1, 0, 1)
+ >>> invoice, = sale.invoices
+ >>> invoice.origins == sale.rec_name
+ True
+ >>> shipment, = sale.shipments
+ >>> shipment.origins == sale.rec_name
+ True
+
+Invoice line must be linked to stock move::
+
+ >>> _, invoice_line1, invoice_line2 = sorted(invoice.lines,
+ ... key=lambda l: l.quantity or 0)
+ >>> stock_move1, stock_move2 = sorted(shipment.outgoing_moves,
+ ... key=lambda m: m.quantity or 0)
+ >>> invoice_line1.stock_moves == [stock_move1]
+ True
+ >>> stock_move1.invoice_lines == [invoice_line1]
+ True
+ >>> invoice_line2.stock_moves == [stock_move2]
+ True
+ >>> stock_move2.invoice_lines == [invoice_line2]
+ True
+
+Check actual quantity::
+
+ >>> all(l.quantity == l.actual_quantity for l in sale.lines)
+ True
+
+Post invoice and check no new invoices::
+
+
+ >>> for invoice in sale.invoices:
+ ... invoice.click('post')
+ >>> sale.reload()
+ >>> len(sale.shipments), len(sale.shipment_returns), len(sale.invoices)
+ (1, 0, 1)
+
+Testing the report::
+
+ >>> sale_report = Report('sale.sale')
+ >>> ext, _, _, name = sale_report.execute([sale], {})
+ >>> ext
+ 'odt'
+ >>> name
+ 'Sale-1'
+
+Sale 5 products with an invoice method 'on shipment'::
+
+ >>> Sale = Model.get('sale.sale')
+ >>> SaleLine = Model.get('sale.line')
+ >>> sale = Sale()
+ >>> sale.party = customer
+ >>> sale.payment_term = payment_term
+ >>> sale.invoice_method = 'shipment'
+ >>> sale_line = SaleLine()
+ >>> sale.lines.append(sale_line)
+ >>> sale_line.product = product
+ >>> sale_line.quantity = 2.0
+ >>> sale_line = SaleLine()
+ >>> sale.lines.append(sale_line)
+ >>> sale_line.type = 'comment'
+ >>> sale_line.description = 'Comment'
+ >>> sale_line = SaleLine()
+ >>> sale.lines.append(sale_line)
+ >>> sale_line.product = product
+ >>> sale_line.quantity = 3.0
+ >>> sale.click('quote')
+ >>> sale.click('confirm')
+ >>> sale.state
+ 'processing'
+ >>> sale.shipment_state
+ 'waiting'
+ >>> sale.invoice_state
+ 'none'
+ >>> sale.reload()
+ >>> len(sale.shipments), len(sale.shipment_returns), len(sale.invoices)
+ (1, 0, 0)
+
+Not yet linked to invoice lines::
+
+ >>> shipment, = sale.shipments
+ >>> stock_move1, stock_move2 = sorted(shipment.outgoing_moves,
+ ... key=lambda m: m.quantity or 0)
+ >>> len(stock_move1.invoice_lines)
+ 0
+ >>> len(stock_move2.invoice_lines)
+ 0
+
+Validate Shipments::
+
+ >>> shipment.click('assign_try')
+ True
+ >>> shipment.click('pick')
+ >>> shipment.click('pack')
+ >>> shipment.click('done')
+
+Open customer invoice::
+
+ >>> sale.reload()
+ >>> sale.invoice_state
+ 'waiting'
+ >>> invoice, = sale.invoices
+ >>> invoice.type
+ 'out'
+ >>> invoice_line1, invoice_line2 = sorted(invoice.lines,
+ ... key=lambda l: l.quantity or 0)
+ >>> for line in invoice.lines:
+ ... line.quantity = 1
+ ... line.save()
+ >>> invoice.click('post')
+
+Invoice lines must be linked to each stock moves::
+
+ >>> invoice_line1.stock_moves == [stock_move1]
+ True
+ >>> invoice_line2.stock_moves == [stock_move2]
+ True
+
+Check second invoices::
+
+ >>> sale.reload()
+ >>> len(sale.invoices)
+ 2
+ >>> sum(l.quantity for i in sale.invoices for l in i.lines)
+ 5.0
+
+Sale 5 products with shipment method 'on invoice'::
+
+ >>> sale = Sale()
+ >>> sale.party = customer
+ >>> sale.payment_term = payment_term
+ >>> sale.shipment_method = 'invoice'
+ >>> sale_line = sale.lines.new()
+ >>> sale_line.product = product
+ >>> sale_line.quantity = 5.0
+ >>> sale.click('quote')
+ >>> sale.click('confirm')
+ >>> sale.state
+ 'processing'
+ >>> sale.shipment_state
+ 'none'
+ >>> sale.invoice_state
+ 'waiting'
+ >>> len(sale.shipments), len(sale.shipment_returns), len(sale.invoices)
+ (0, 0, 1)
+
+Not yet linked to stock moves::
+
+ >>> invoice, = sale.invoices
+ >>> invoice_line, = invoice.lines
+ >>> len(invoice_line.stock_moves)
+ 0
+
+Post and Pay Invoice for 4 products::
+
+ >>> invoice_line, = invoice.lines
+ >>> invoice_line.quantity
+ 5.0
+ >>> invoice_line.quantity = 4.0
+ >>> invoice.click('post')
+ >>> pay = Wizard('account.invoice.pay', [invoice])
+ >>> pay.form.payment_method = payment_method
+ >>> pay.execute('choice')
+ >>> invoice.reload()
+ >>> invoice.state
+ 'paid'
+
+Invoice lines linked to 1 move::
+
+ >>> invoice_line, = invoice.lines
+ >>> len(invoice_line.stock_moves)
+ 1
+
+Stock moves must be linked to invoice line::
+
+ >>> sale.reload()
+ >>> shipment, = sale.shipments
+ >>> shipment.reload()
+ >>> stock_move, = shipment.outgoing_moves
+ >>> stock_move.quantity
+ 4.0
+ >>> stock_move.invoice_lines == [invoice_line]
+ True
+
+Ship 3 products::
+
+ >>> stock_inventory_move, = shipment.inventory_moves
+ >>> stock_inventory_move.quantity
+ 4.0
+ >>> stock_inventory_move.quantity = 3.0
+ >>> shipment.click('assign_try')
+ True
+ >>> shipment.click('pick')
+ >>> shipment.click('pack')
+ >>> shipment.click('done')
+ >>> shipment.state
+ 'done'
+
+New shipments created::
+
+ >>> sale.reload()
+ >>> len(sale.shipments)
+ 2
+
+Invoice lines linked to new moves::
+
+ >>> invoice.reload()
+ >>> invoice_line, = invoice.lines
+ >>> len(invoice_line.stock_moves)
+ 2
+
+Create a Return::
+
+ >>> return_ = Sale()
+ >>> return_.party = customer
+ >>> return_.payment_term = payment_term
+ >>> return_.invoice_method = 'shipment'
+ >>> return_line = SaleLine()
+ >>> return_.lines.append(return_line)
+ >>> return_line.product = product
+ >>> return_line.quantity = -4.
+ >>> return_line = SaleLine()
+ >>> return_.lines.append(return_line)
+ >>> return_line.type = 'comment'
+ >>> return_line.description = 'Comment'
+ >>> return_.click('quote')
+ >>> return_.click('confirm')
+ >>> return_.state
+ 'processing'
+ >>> return_.shipment_state
+ 'waiting'
+ >>> return_.invoice_state
+ 'none'
+ >>> (len(return_.shipments), len(return_.shipment_returns),
+ ... len(return_.invoices))
+ (0, 1, 0)
+
+Receive Return Shipment for 3 products::
+
+ >>> ship_return, = return_.shipment_returns
+ >>> move_return, = ship_return.incoming_moves
+ >>> move_return.product.rec_name
+ 'product'
+ >>> move_return.quantity
+ 4.0
+ >>> move_return.quantity = 3
+ >>> ship_return.click('receive')
+
+Check Return::
+
+ >>> return_.reload()
+ >>> return_.shipment_state
+ 'waiting'
+ >>> return_.invoice_state
+ 'waiting'
+ >>> (len(return_.shipments), len(return_.shipment_returns),
+ ... len(return_.invoices))
+ (0, 2, 1)
+
+Open customer credit note::
+
+ >>> credit_note, = return_.invoices
+ >>> credit_note.type
+ 'out'
+ >>> len(credit_note.lines)
+ 1
+ >>> sum(l.quantity for l in credit_note.lines)
+ -3.0
+ >>> credit_note.click('post')
+
+Receive Remaining Return Shipment::
+
+ >>> return_.reload()
+ >>> _, ship_return = return_.shipment_returns
+ >>> move_return, = ship_return.incoming_moves
+ >>> move_return.product.rec_name
+ 'product'
+ >>> move_return.quantity
+ 1.0
+ >>> ship_return.click('receive')
+
+Check Return::
+
+ >>> return_.reload()
+ >>> return_.shipment_state
+ 'sent'
+ >>> return_.invoice_state
+ 'waiting'
+ >>> (len(return_.shipments), len(return_.shipment_returns),
+ ... len(return_.invoices))
+ (0, 2, 2)
+
+Mixing return and sale::
+
+ >>> mix = Sale()
+ >>> mix.party = customer
+ >>> mix.payment_term = payment_term
+ >>> mix.invoice_method = 'order'
+ >>> mixline = SaleLine()
+ >>> mix.lines.append(mixline)
+ >>> mixline.product = product
+ >>> mixline.quantity = 7.
+ >>> mixline_comment = SaleLine()
+ >>> mix.lines.append(mixline_comment)
+ >>> mixline_comment.type = 'comment'
+ >>> mixline_comment.description = 'Comment'
+ >>> mixline2 = SaleLine()
+ >>> mix.lines.append(mixline2)
+ >>> mixline2.product = product
+ >>> mixline2.quantity = -2.
+ >>> mix.click('quote')
+ >>> mix.click('confirm')
+ >>> mix.state
+ 'processing'
+ >>> mix.shipment_state
+ 'waiting'
+ >>> mix.invoice_state
+ 'waiting'
+ >>> len(mix.shipments), len(mix.shipment_returns), len(mix.invoices)
+ (1, 1, 1)
+
+Checking Shipments::
+
+ >>> mix_return, = mix.shipment_returns
+ >>> mix_shipment, = mix.shipments
+ >>> mix_return.click('receive')
+ >>> move_return, = mix_return.incoming_moves
+ >>> move_return.product.rec_name
+ 'product'
+ >>> move_return.quantity
+ 2.0
+ >>> mix_shipment.click('assign_try')
+ True
+ >>> mix_shipment.click('pick')
+ >>> mix_shipment.click('pack')
+ >>> mix_shipment.click('done')
+ >>> move_shipment, = mix_shipment.outgoing_moves
+ >>> move_shipment.product.rec_name
+ 'product'
+ >>> move_shipment.quantity
+ 7.0
+
+Checking the invoice::
+
+ >>> mix.reload()
+ >>> mix_invoice, = mix.invoices
+ >>> mix_invoice.type
+ 'out'
+ >>> len(mix_invoice.lines)
+ 3
+ >>> sorted(l.quantity for l in mix_invoice.lines if l.quantity)
+ [-2.0, 7.0]
+ >>> mix_invoice.click('post')
+
+Mixing stuff with an invoice method 'on shipment'::
+
+ >>> mix = Sale()
+ >>> mix.party = customer
+ >>> mix.payment_term = payment_term
+ >>> mix.invoice_method = 'shipment'
+ >>> mixline = SaleLine()
+ >>> mix.lines.append(mixline)
+ >>> mixline.product = product
+ >>> mixline.quantity = 6.
+ >>> mixline_comment = SaleLine()
+ >>> mix.lines.append(mixline_comment)
+ >>> mixline_comment.type = 'comment'
+ >>> mixline_comment.description = 'Comment'
+ >>> mixline2 = SaleLine()
+ >>> mix.lines.append(mixline2)
+ >>> mixline2.product = product
+ >>> mixline2.quantity = -3.
+ >>> mix.click('quote')
+ >>> mix.click('confirm')
+ >>> mix.state
+ 'processing'
+ >>> mix.shipment_state
+ 'waiting'
+ >>> mix.invoice_state
+ 'none'
+ >>> len(mix.shipments), len(mix.shipment_returns), len(mix.invoices)
+ (1, 1, 0)
+
+Checking Shipments::
+
+ >>> mix_return, = mix.shipment_returns
+ >>> mix_shipment, = mix.shipments
+ >>> mix_return.click('receive')
+ >>> move_return, = mix_return.incoming_moves
+ >>> move_return.product.rec_name
+ 'product'
+ >>> move_return.quantity
+ 3.0
+ >>> mix_shipment.click('assign_try')
+ True
+ >>> mix_shipment.click('pick')
+ >>> mix_shipment.click('pack')
+ >>> move_shipment, = mix_shipment.outgoing_moves
+ >>> move_shipment.product.rec_name
+ 'product'
+ >>> move_shipment.quantity
+ 6.0
+
+Sale services::
+
+ >>> service_sale = Sale()
+ >>> service_sale.party = customer
+ >>> service_sale.payment_term = payment_term
+ >>> sale_line = service_sale.lines.new()
+ >>> sale_line.product = service
+ >>> sale_line.quantity = 1
+ >>> service_sale.save()
+ >>> service_sale.click('quote')
+ >>> service_sale.click('confirm')
+ >>> service_sale.state
+ 'processing'
+ >>> service_sale.shipment_state
+ 'none'
+ >>> service_sale.invoice_state
+ 'waiting'
+ >>> service_invoice, = service_sale.invoices
+
+Pay the service invoice::
+
+ >>> service_invoice.click('post')
+ >>> pay = Wizard('account.invoice.pay', [service_invoice])
+ >>> pay.form.payment_method = payment_method
+ >>> pay.execute('choice')
+ >>> service_invoice.reload()
+ >>> service_invoice.state
+ 'paid'
+
+Check service sale states::
+
+ >>> service_sale.reload()
+ >>> service_sale.invoice_state
+ 'paid'
+ >>> service_sale.shipment_state
+ 'none'
+ >>> service_sale.state
+ 'done'
+
+Return sales using the wizard::
+
+ >>> sale_to_return = Sale()
+ >>> sale_to_return.party = customer
+ >>> sale_to_return.payment_term = payment_term
+ >>> sale_line = sale_to_return.lines.new()
+ >>> sale_line.product = service
+ >>> sale_line.quantity = 1
+ >>> sale_line = sale_to_return.lines.new()
+ >>> sale_line.type = 'comment'
+ >>> sale_line.description = 'Test comment'
+ >>> sale_to_return.click('quote')
+ >>> sale_to_return.click('confirm')
+ >>> sale_to_return.state
+ 'processing'
+ >>> return_sale = Wizard('sale.return_sale', [sale_to_return])
+ >>> return_sale.execute('return_')
+ >>> returned_sale, = Sale.find([
+ ... ('state', '=', 'draft'),
+ ... ])
+ >>> returned_sale.origin == sale_to_return
+ True
+ >>> sorted([x.quantity or 0 for x in returned_sale.lines])
+ [-1.0, 0]
+
+Create a sale to be invoiced on shipment partialy and check correctly linked
+to invoices::
+
+ >>> sale = Sale()
+ >>> sale.party = customer
+ >>> sale.payment_term = payment_term
+ >>> sale.invoice_method = 'shipment'
+ >>> line = sale.lines.new()
+ >>> line.product = product
+ >>> line.quantity = 10.0
+ >>> sale.click('quote')
+ >>> sale.click('confirm')
+ >>> shipment, = sale.shipments
+ >>> for move in shipment.inventory_moves:
+ ... move.quantity = 5.0
+ >>> shipment.click('assign_try')
+ True
+ >>> shipment.click('pick')
+ >>> shipment.click('pack')
+ >>> shipment.click('done')
+ >>> sale.reload()
+ >>> invoice, = sale.invoices
+ >>> invoice_line, = invoice.lines
+ >>> invoice_line.quantity
+ 5.0
+ >>> stock_move, = invoice_line.stock_moves
+ >>> stock_move.quantity
+ 5.0
+ >>> stock_move.state
+ 'done'
+
+Create a sale to be sent on invoice partially and check correctly linked to
+invoices::
+
+ >>> sale = Sale()
+ >>> sale.party = customer
+ >>> sale.payment_term = payment_term
+ >>> sale.shipment_method = 'invoice'
+ >>> line = sale.lines.new()
+ >>> line.product = product
+ >>> line.quantity = 10.0
+ >>> sale.click('quote')
+ >>> sale.click('confirm')
+ >>> invoice, = sale.invoices
+ >>> invoice_line, = invoice.lines
+ >>> invoice_line.stock_moves == []
+ True
+ >>> invoice_line.quantity = 5.0
+ >>> invoice.click('post')
+ >>> pay = Wizard('account.invoice.pay', [invoice])
+ >>> pay.form.payment_method = payment_method
+ >>> pay.execute('choice')
+ >>> invoice.reload()
+ >>> invoice.state
+ 'paid'
+ >>> invoice_line.reload()
+ >>> stock_move, = invoice_line.stock_moves
+ >>> stock_move.quantity
+ 5.0
+ >>> stock_move.state
+ 'draft'
+
+Deleting a line from a invoice should recreate it::
+
+ >>> sale = Sale()
+ >>> sale.party = customer
+ >>> line = sale.lines.new()
+ >>> line.product = product
+ >>> line.quantity = 10.0
+ >>> sale.click('quote')
+ >>> sale.click('confirm')
+ >>> invoice, = sale.invoices
+ >>> invoice_line, = invoice.lines
+ >>> invoice.lines.remove(invoice_line)
+ >>> invoice.click('post')
+ >>> sale.reload()
+ >>> new_invoice, = sale.invoices
+ >>> new_invoice.number
+ >>> len(new_invoice.lines)
+ 1
diff --git a/modules/sale/tests/scenario_sale_empty.rst b/modules/sale/tests/scenario_sale_empty.rst
new file mode 100644
index 0000000000..35cb5b50ed
--- /dev/null
+++ b/modules/sale/tests/scenario_sale_empty.rst
@@ -0,0 +1,59 @@
+===================
+Sale Empty Scenario
+===================
+
+Imports::
+
+ >>> from proteus import Model
+ >>> from trytond.tests.tools import activate_modules
+ >>> from trytond.modules.company.tests.tools import create_company, \
+ ... get_company
+ >>> from trytond.modules.account.tests.tools import create_fiscalyear, \
+ ... create_chart
+
+Activate modules::
+
+ >>> config = activate_modules('sale')
+
+Create company::
+
+ >>> _ = create_company()
+ >>> company = get_company()
+
+Create chart of accounts::
+
+ >>> _ = create_chart(company)
+
+Create parties::
+
+ >>> Party = Model.get('party.party')
+ >>> customer = Party(name='Customer')
+ >>> customer.save()
+
+Create empty sale::
+
+ >>> Sale = Model.get('sale.sale')
+ >>> sale = Sale()
+ >>> sale.party = customer
+ >>> sale.click('quote')
+ >>> sale.state
+ 'quotation'
+ >>> sale.untaxed_amount
+ Decimal('0')
+ >>> sale.tax_amount
+ Decimal('0')
+ >>> sale.total_amount
+ Decimal('0')
+ >>> sale.click('confirm')
+ >>> sale.state
+ 'done'
+ >>> sale.shipment_state
+ 'none'
+ >>> len(sale.shipments)
+ 0
+ >>> len(sale.shipment_returns)
+ 0
+ >>> sale.invoice_state
+ 'none'
+ >>> len(sale.invoices)
+ 0
diff --git a/modules/sale/tests/scenario_sale_modify_header.rst b/modules/sale/tests/scenario_sale_modify_header.rst
new file mode 100644
index 0000000000..562e3c5d75
--- /dev/null
+++ b/modules/sale/tests/scenario_sale_modify_header.rst
@@ -0,0 +1,98 @@
+===========================
+Sale Modify Header Scenario
+===========================
+
+Imports::
+
+ >>> from proteus import Model, Wizard
+ >>> from decimal import Decimal
+ >>> from trytond.tests.tools import activate_modules
+ >>> from trytond.modules.company.tests.tools import create_company, \
+ ... get_company
+ >>> from trytond.modules.account.tests.tools import create_fiscalyear, \
+ ... create_chart, create_tax, get_accounts
+
+Activate modules::
+
+ >>> config = activate_modules('sale')
+
+Create company::
+
+ >>> _ = create_company()
+ >>> company = get_company()
+
+Create chart of accounts::
+
+ >>> _ = create_chart(company)
+ >>> accounts = get_accounts(company)
+ >>> revenue = accounts['revenue']
+
+Create tax and tax rule::
+
+ >>> tax = create_tax(Decimal('.10'))
+ >>> tax.save()
+ >>> other_tax = create_tax(Decimal('.05'))
+ >>> other_tax.save()
+
+ >>> TaxRule = Model.get('account.tax.rule')
+ >>> foreign = TaxRule(name='Foreign Customers', company=company)
+ >>> foreign_tax = foreign.lines.new()
+ >>> foreign_tax.origin_tax = tax
+ >>> foreign_tax.tax = other_tax
+ >>> foreign.save()
+
+Create account categories::
+
+ >>> ProductCategory = Model.get('product.category')
+ >>> account_category = ProductCategory(name="Account Category")
+ >>> account_category.accounting = True
+ >>> account_category.account_revenue = revenue
+ >>> account_category.customer_taxes.append(tax)
+ >>> account_category.save()
+
+Create product::
+
+ >>> ProductUom = Model.get('product.uom')
+ >>> unit, = ProductUom.find([('name', '=', 'Unit')])
+ >>> ProductTemplate = Model.get('product.template')
+
+ >>> template = ProductTemplate()
+ >>> template.name = 'product'
+ >>> template.default_uom = unit
+ >>> template.type = 'goods'
+ >>> template.salable = True
+ >>> template.list_price = Decimal('10')
+ >>> template.account_category = account_category
+ >>> template.save()
+ >>> product, = template.products
+
+Create parties::
+
+ >>> Party = Model.get('party.party')
+ >>> customer = Party(name='Customer')
+ >>> customer.save()
+ >>> another = Party(name='Another Customer', customer_tax_rule=foreign)
+ >>> another.save()
+
+Create a sale with a line::
+
+ >>> Sale = Model.get('sale.sale')
+ >>> sale = Sale()
+ >>> sale.party = customer
+ >>> sale_line = sale.lines.new()
+ >>> sale_line.product = product
+ >>> sale_line.quantity = 3
+ >>> sale.save()
+ >>> sale.untaxed_amount, sale.tax_amount, sale.total_amount
+ (Decimal('30.00'), Decimal('3.00'), Decimal('33.00'))
+
+Change the party::
+
+ >>> modify_header = Wizard('sale.modify_header', [sale])
+ >>> modify_header.form.party = another
+ >>> modify_header.execute('modify')
+
+ >>> sale.party.name
+ 'Another Customer'
+ >>> sale.untaxed_amount, sale.tax_amount, sale.total_amount
+ (Decimal('30.00'), Decimal('1.50'), Decimal('31.50'))
diff --git a/modules/sale/tests/scenario_sale_reporting.rst b/modules/sale/tests/scenario_sale_reporting.rst
new file mode 100644
index 0000000000..c4cd3d47c8
--- /dev/null
+++ b/modules/sale/tests/scenario_sale_reporting.rst
@@ -0,0 +1,261 @@
+=======================
+Sale Reporting Scenario
+=======================
+
+Imports::
+
+ >>> from dateutil.relativedelta import relativedelta
+ >>> from decimal import Decimal
+ >>> from proteus import Model
+ >>> from trytond.tests.tools import activate_modules
+ >>> from trytond.modules.company.tests.tools import create_company, \
+ ... get_company
+ >>> from trytond.modules.account.tests.tools import create_fiscalyear, \
+ ... create_chart, get_accounts
+ >>> from trytond.modules.account_invoice.tests.tools import \
+ ... set_fiscalyear_invoice_sequences
+
+Activate modules::
+
+ >>> config = activate_modules('sale')
+
+Create company::
+
+ >>> _ = create_company()
+ >>> company = get_company()
+
+Create fiscal year::
+
+ >>> fiscalyear = set_fiscalyear_invoice_sequences(
+ ... create_fiscalyear(company))
+ >>> fiscalyear.click('create_period')
+
+Create chart of accounts::
+
+ >>> _ = create_chart(company)
+ >>> accounts = get_accounts(company)
+ >>> revenue = accounts['revenue']
+ >>> expense = accounts['expense']
+
+Create countries::
+
+ >>> Country = Model.get('country.country')
+ >>> Subdivision = Model.get('country.subdivision')
+ >>> country_us = Country(
+ ... name="United States", code="US", code3="USA", code_numeric="840")
+ >>> country_us.save()
+ >>> california = Subdivision(
+ ... name="California", code="US-CA", type='state', country=country_us)
+ >>> california.save()
+ >>> new_york = Subdivision(
+ ... name="New York", code="US-NY", type='state', country=country_us)
+ >>> new_york.save()
+
+Create parties::
+
+ >>> Party = Model.get('party.party')
+ >>> customer1 = Party(name='Customer1')
+ >>> address, = customer1.addresses
+ >>> address.country = country_us
+ >>> address.subdivision = california
+ >>> customer1.save()
+ >>> customer2 = Party(name='Customer2')
+ >>> address, = customer2.addresses
+ >>> address.country = country_us
+ >>> address.subdivision = new_york
+ >>> customer2.save()
+
+Create account categories::
+
+ >>> Category = Model.get('product.category')
+ >>> account_category = Category(name="Account Category")
+ >>> account_category.accounting = True
+ >>> account_category.account_revenue = revenue
+ >>> account_category.save()
+
+Create products::
+
+ >>> ProductUom = Model.get('product.uom')
+ >>> unit, = ProductUom.find([('name', '=', 'Unit')])
+ >>> ProductTemplate = Model.get('product.template')
+
+ >>> template1 = ProductTemplate()
+ >>> template1.name = "Product1"
+ >>> template1.default_uom = unit
+ >>> template1.type = 'service'
+ >>> template1.salable = True
+ >>> template1.list_price = Decimal('10')
+ >>> template1.account_category = account_category
+ >>> template1.save()
+ >>> product1, = template1.products
+
+ >>> template2, = template1.duplicate(default={'name': "Product2"})
+ >>> product2, = template2.products
+
+ >>> category_root1 = Category(name="Root1")
+ >>> category_root1.save()
+ >>> category_child1 = Category(name="Child1", parent=category_root1)
+ >>> category_child1.save()
+ >>> category_child2 = Category(name="Child2", parent=category_root1)
+ >>> category_child2.save()
+ >>> category_root2 = Category(name="Root2")
+ >>> category_root2.save()
+
+ >>> template1.categories.append(Category(category_child1.id))
+ >>> template1.categories.append(Category(category_root2.id))
+ >>> template1.save()
+ >>> template2.categories.append(Category(category_child2.id))
+ >>> template2.save()
+
+Create sales::
+
+ >>> Sale = Model.get('sale.sale')
+
+ >>> sale1 = Sale()
+ >>> sale1.party = customer1
+ >>> sale1.sale_date = fiscalyear.start_date
+ >>> line = sale1.lines.new()
+ >>> line.product = product1
+ >>> line.quantity = 2
+ >>> line = sale1.lines.new()
+ >>> line.product = product2
+ >>> line.quantity = 1
+ >>> sale1.click('quote')
+ >>> sale1.click('confirm')
+
+ >>> sale2 = Sale()
+ >>> sale2.party = customer2
+ >>> sale2.sale_date = fiscalyear.start_date + relativedelta(months=1)
+ >>> line = sale2.lines.new()
+ >>> line.product = product1
+ >>> line.quantity = 1
+ >>> sale2.click('quote')
+ >>> sale2.click('confirm')
+
+Check sale reporting per customer::
+
+ >>> Customer = Model.get('sale.reporting.customer')
+ >>> CustomerTimeseries = Model.get('sale.reporting.customer.time_series')
+ >>> context = dict(
+ ... from_date=fiscalyear.start_date,
+ ... to_date=fiscalyear.end_date,
+ ... period='month')
+ >>> with config.set_context(context=context):
+ ... reports = Customer.find([])
+ ... time_series = CustomerTimeseries.find([])
+ >>> len(reports)
+ 2
+ >>> with config.set_context(context=context):
+ ... sorted((r.customer.id, r.number, r.revenue) for r in reports) == \
+ ... sorted([(customer1.id, 1, Decimal('30')),
+ ... (customer2.id, 1, Decimal('10'))])
+ True
+ >>> len(time_series)
+ 2
+ >>> with config.set_context(context=context):
+ ... sorted((r.customer.id, r.date, r.number, r.revenue)
+ ... for r in time_series) == sorted(
+ ... [(customer1.id, sale1.sale_date.replace(day=1), 1, Decimal('30')),
+ ... (customer2.id, sale2.sale_date.replace(day=1), 1, Decimal('10'))])
+ True
+
+Check sale reporting per product::
+
+ >>> Product = Model.get('sale.reporting.product')
+ >>> ProductTimeseries = Model.get('sale.reporting.product.time_series')
+ >>> with config.set_context(context=context):
+ ... reports = Product.find([])
+ ... time_series = ProductTimeseries.find([])
+ >>> len(reports)
+ 2
+ >>> with config.set_context(context=context):
+ ... sorted((r.product.id, r.number, r.revenue) for r in reports) == \
+ ... sorted([(product1.id, 2, Decimal('30')),
+ ... (product2.id, 1, Decimal('10'))])
+ True
+ >>> len(time_series)
+ 3
+ >>> with config.set_context(context=context):
+ ... sorted((r.product.id, r.date, r.number, r.revenue)
+ ... for r in time_series) == sorted(
+ ... [(product1.id, sale1.sale_date.replace(day=1), 1, Decimal('20')),
+ ... (product2.id, sale1.sale_date.replace(day=1), 1, Decimal('10')),
+ ... (product1.id, sale2.sale_date.replace(day=1), 1, Decimal('10'))])
+ True
+
+Check sale reporting per categories::
+
+ >>> Category = Model.get('sale.reporting.category')
+ >>> CategoryTimeseries = Model.get('sale.reporting.category.time_series')
+ >>> CategoryTree = Model.get('sale.reporting.category.tree')
+ >>> with config.set_context(context=context):
+ ... reports = Category.find([])
+ ... time_series = CategoryTimeseries.find([])
+ ... tree = CategoryTree.find([])
+ >>> len(reports)
+ 4
+ >>> with config.set_context(context=context):
+ ... sorted((r.category.id, r.number, r.revenue) for r in reports) == \
+ ... sorted([(category_child1.id, 2, Decimal('30')),
+ ... (category_root2.id, 2, Decimal('30')),
+ ... (category_child2.id, 1, Decimal('10')),
+ ... (account_category.id, 2, Decimal('40'))])
+ True
+ >>> len(time_series)
+ 7
+ >>> with config.set_context(context=context):
+ ... sorted((r.category.id, r.date, r.number, r.revenue)
+ ... for r in time_series) == sorted(
+ ... [(category_child1.id, sale1.sale_date.replace(day=1), 1, Decimal('20')),
+ ... (category_root2.id, sale1.sale_date.replace(day=1), 1, Decimal('20')),
+ ... (category_child2.id, sale1.sale_date.replace(day=1), 1, Decimal('10')),
+ ... (category_child1.id, sale2.sale_date.replace(day=1), 1, Decimal('10')),
+ ... (category_root2.id, sale2.sale_date.replace(day=1), 1, Decimal('10')),
+ ... (account_category.id, sale1.sale_date.replace(day=1), 1, Decimal('30')),
+ ... (account_category.id, sale2.sale_date.replace(day=1), 1, Decimal('10'))])
+ True
+ >>> len(tree)
+ 5
+ >>> with config.set_context(context=context):
+ ... sorted((r.name, r.revenue) for r in tree) == sorted([
+ ... ('Root1', Decimal('40')),
+ ... ('Child1', Decimal('30')),
+ ... ('Child2', Decimal('10')),
+ ... ('Root2', Decimal('30')),
+ ... ('Account Category', Decimal('40'))])
+ True
+
+Check sale reporting per regions::
+
+ >>> Region = Model.get('sale.reporting.region')
+ >>> CountryTimeseries = Model.get('sale.reporting.country.time_series')
+ >>> SubdivisionTimeseries = Model.get(
+ ... 'sale.reporting.country.subdivision.time_series')
+ >>> with config.set_context(context=context):
+ ... reports = Region.find([])
+ ... country_time_series = CountryTimeseries.find([])
+ ... subdivision_time_series = SubdivisionTimeseries.find([])
+ >>> len(reports)
+ 3
+ >>> with config.set_context(context=context):
+ ... sorted((r.region, r.number, r.revenue) for r in reports) == \
+ ... sorted([('United States', 2, Decimal('40')),
+ ... ('California', 1, Decimal('30')),
+ ... ('New York', 1, Decimal('10'))])
+ True
+ >>> len(country_time_series)
+ 2
+ >>> with config.set_context(context=context):
+ ... sorted((r.country.id, r.date, r.number, r.revenue)
+ ... for r in country_time_series) == sorted(
+ ... [(country_us.id, sale1.sale_date.replace(day=1), 1, Decimal('30')),
+ ... (country_us.id, sale2.sale_date.replace(day=1), 1, Decimal('10'))])
+ True
+ >>> len(subdivision_time_series)
+ 2
+ >>> with config.set_context(context=context):
+ ... sorted((r.subdivision.id, r.date, r.number, r.revenue)
+ ... for r in subdivision_time_series) == sorted(
+ ... [(california.id, sale1.sale_date.replace(day=1), 1, Decimal('30')),
+ ... (new_york.id, sale2.sale_date.replace(day=1), 1, Decimal('10'))])
+ True
diff --git a/modules/sale/tests/test_sale.py b/modules/sale/tests/test_sale.py
new file mode 100644
index 0000000000..da5ff771fe
--- /dev/null
+++ b/modules/sale/tests/test_sale.py
@@ -0,0 +1,91 @@
+# This file is part of Tryton. The COPYRIGHT file at the top level of
+# this repository contains the full copyright notices and license terms.
+import unittest
+import doctest
+from decimal import Decimal
+
+import trytond.tests.test_tryton
+from trytond.tests.test_tryton import ModuleTestCase, with_transaction
+from trytond.tests.test_tryton import doctest_teardown, doctest_checker
+from trytond.transaction import Transaction
+from trytond.pool import Pool
+
+from trytond.modules.account.tests import create_chart
+from trytond.modules.company.tests import (
+ create_company, set_company, PartyCompanyCheckEraseMixin, CompanyTestMixin)
+
+
+class SaleTestCase(
+ PartyCompanyCheckEraseMixin, CompanyTestMixin, ModuleTestCase):
+ 'Test Sale module'
+ module = 'sale'
+
+ @with_transaction()
+ def test_sale_price(self):
+ "Test sale price"
+ pool = Pool()
+ Account = pool.get('account.account')
+ Template = pool.get('product.template')
+ Product = pool.get('product.product')
+ Uom = pool.get('product.uom')
+
+ company = create_company()
+ with set_company(company):
+ create_chart(company)
+
+ receivable, = Account.search([
+ ('type.receivable', '=', True),
+ ('company', '=', company.id),
+ ])
+ payable, = Account.search([
+ ('type.payable', '=', True),
+ ('company', '=', company.id),
+ ])
+
+ kg, = Uom.search([('name', '=', 'Kilogram')])
+ g, = Uom.search([('name', '=', 'Gram')])
+ pound, = Uom.search([('name', '=', 'Pound')])
+
+ template, = Template.create([{
+ 'name': 'Product',
+ 'default_uom': g.id,
+ 'sale_uom': kg.id,
+ 'list_price': Decimal(5),
+ 'products': [('create', [{}])],
+ }])
+ product, = template.products
+
+ prices = Product.get_sale_price([product], quantity=100)
+ self.assertEqual(prices, {product.id: Decimal(5000)})
+ prices = Product.get_sale_price([product], quantity=1500)
+ self.assertEqual(prices, {product.id: Decimal(5000)})
+
+ with Transaction().set_context(uom=pound.id):
+ prices = Product.get_sale_price([product], quantity=0.5)
+ self.assertEqual(prices, {product.id: Decimal('2267.96185')})
+ prices = Product.get_sale_price([product], quantity=1.5)
+ self.assertEqual(prices, {product.id: Decimal('2267.96185')})
+
+
+def suite():
+ suite = trytond.tests.test_tryton.suite()
+ suite.addTests(unittest.TestLoader().loadTestsFromTestCase(SaleTestCase))
+ suite.addTests(doctest.DocFileSuite('scenario_sale.rst',
+ tearDown=doctest_teardown, encoding='utf-8',
+ optionflags=doctest.REPORT_ONLY_FIRST_FAILURE,
+ checker=doctest_checker))
+ suite.addTests(doctest.DocFileSuite('scenario_sale_empty.rst',
+ tearDown=doctest_teardown, encoding='utf-8',
+ optionflags=doctest.REPORT_ONLY_FIRST_FAILURE,
+ checker=doctest_checker))
+ suite.addTests(doctest.DocFileSuite(
+ 'scenario_sale_modify_header.rst',
+ tearDown=doctest_teardown, encoding='utf-8',
+ optionflags=doctest.REPORT_ONLY_FIRST_FAILURE,
+ checker=doctest_checker))
+ suite.addTests(doctest.DocFileSuite(
+ 'scenario_sale_reporting.rst',
+ tearDown=doctest_teardown, encoding='utf-8',
+ optionflags=doctest.REPORT_ONLY_FIRST_FAILURE,
+ checker=doctest_checker))
+ return suite
diff --git a/modules/sale/tox.ini b/modules/sale/tox.ini
new file mode 100644
index 0000000000..197496c0cb
--- /dev/null
+++ b/modules/sale/tox.ini
@@ -0,0 +1,15 @@
+[tox]
+envlist = {py36,py37,py38,py39}-{sqlite,postgresql},pypy3-{sqlite,postgresql}
+
+[testenv]
+commands = {envpython} setup.py test
+deps =
+ {py36,py37,py38,py39}-postgresql: psycopg2 >= 2.5
+ pypy3-postgresql: psycopg2cffi >= 2.5
+ py36-sqlite: sqlitebck
+setenv =
+ sqlite: TRYTOND_DATABASE_URI={env:SQLITE_URI:sqlite://}
+ postgresql: TRYTOND_DATABASE_URI={env:POSTGRESQL_URI:postgresql://}
+ sqlite: DB_NAME={env:SQLITE_NAME::memory:}
+ postgresql: DB_NAME={env:POSTGRESQL_NAME:test}
+install_command = pip install --pre --find-links https://trydevpi.tryton.org/?local_version={env:CI_JOB_ID:{env:CI_BUILD_NUMBER}.{env:CI_JOB_NUMBER}} {opts} {packages}
diff --git a/modules/sale/tryton.cfg b/modules/sale/tryton.cfg
new file mode 100644
index 0000000000..68b1d2c3f2
--- /dev/null
+++ b/modules/sale/tryton.cfg
@@ -0,0 +1,23 @@
+[tryton]
+version=6.0.10
+depends:
+ account
+ account_invoice
+ account_invoice_stock
+ account_product
+ company
+ country
+ currency
+ ir
+ party
+ product
+ res
+ stock
+xml:
+ sale.xml
+ configuration.xml
+ sale_reporting.xml
+ party.xml
+ stock.xml
+ product.xml
+ message.xml
diff --git a/modules/sale/view/configuration_form.xml b/modules/sale/view/configuration_form.xml
new file mode 100644
index 0000000000..07bea14ff0
--- /dev/null
+++ b/modules/sale/view/configuration_form.xml
@@ -0,0 +1,15 @@
+
+
+
diff --git a/modules/sale/view/handle_invoice_exception_ask_form.xml b/modules/sale/view/handle_invoice_exception_ask_form.xml
new file mode 100644
index 0000000000..4dbd2fde3d
--- /dev/null
+++ b/modules/sale/view/handle_invoice_exception_ask_form.xml
@@ -0,0 +1,10 @@
+
+
+
+
diff --git a/modules/sale/view/handle_shipment_exception_ask_form.xml b/modules/sale/view/handle_shipment_exception_ask_form.xml
new file mode 100644
index 0000000000..4499987412
--- /dev/null
+++ b/modules/sale/view/handle_shipment_exception_ask_form.xml
@@ -0,0 +1,9 @@
+
+
+
diff --git a/modules/sale/view/modify_header_form.xml b/modules/sale/view/modify_header_form.xml
new file mode 100644
index 0000000000..386316a6b4
--- /dev/null
+++ b/modules/sale/view/modify_header_form.xml
@@ -0,0 +1,8 @@
+
+
+
+
+
+
+
diff --git a/modules/sale/view/move_list_shipment.xml b/modules/sale/view/move_list_shipment.xml
new file mode 100644
index 0000000000..baf7bf41ae
--- /dev/null
+++ b/modules/sale/view/move_list_shipment.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/modules/sale/view/party_form.xml b/modules/sale/view/party_form.xml
new file mode 100644
index 0000000000..d2e7b4a3d2
--- /dev/null
+++ b/modules/sale/view/party_form.xml
@@ -0,0 +1,12 @@
+
+
+
+
+
+
+
+
+
+
+
diff --git a/modules/sale/view/product_configuration_form.xml b/modules/sale/view/product_configuration_form.xml
new file mode 100644
index 0000000000..5aeec8ef6f
--- /dev/null
+++ b/modules/sale/view/product_configuration_form.xml
@@ -0,0 +1,9 @@
+
+
+
+
+
+
+
+
diff --git a/modules/sale/view/product_list_sale_line.xml b/modules/sale/view/product_list_sale_line.xml
new file mode 100644
index 0000000000..8d58519b4c
--- /dev/null
+++ b/modules/sale/view/product_list_sale_line.xml
@@ -0,0 +1,12 @@
+
+
+
+
+
+
+
+
+
+
+
diff --git a/modules/sale/view/product_sale_context_form.xml b/modules/sale/view/product_sale_context_form.xml
new file mode 100644
index 0000000000..ad58c01a27
--- /dev/null
+++ b/modules/sale/view/product_sale_context_form.xml
@@ -0,0 +1,19 @@
+
+
+
diff --git a/modules/sale/view/return_sale_start_form.xml b/modules/sale/view/return_sale_start_form.xml
new file mode 100644
index 0000000000..ab40d82526
--- /dev/null
+++ b/modules/sale/view/return_sale_start_form.xml
@@ -0,0 +1,9 @@
+
+
+
diff --git a/modules/sale/view/sale_form.xml b/modules/sale/view/sale_form.xml
new file mode 100644
index 0000000000..a4e1af80c7
--- /dev/null
+++ b/modules/sale/view/sale_form.xml
@@ -0,0 +1,94 @@
+
+
+
diff --git a/modules/sale/view/sale_line_form.xml b/modules/sale/view/sale_line_form.xml
new file mode 100644
index 0000000000..9a9784aa8f
--- /dev/null
+++ b/modules/sale/view/sale_line_form.xml
@@ -0,0 +1,38 @@
+
+
+
diff --git a/modules/sale/view/sale_line_tree.xml b/modules/sale/view/sale_line_tree.xml
new file mode 100644
index 0000000000..876c1a6eab
--- /dev/null
+++ b/modules/sale/view/sale_line_tree.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/modules/sale/view/sale_line_tree_sequence.xml b/modules/sale/view/sale_line_tree_sequence.xml
new file mode 100644
index 0000000000..5b6d135895
--- /dev/null
+++ b/modules/sale/view/sale_line_tree_sequence.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/modules/sale/view/sale_reporting_category_list.xml b/modules/sale/view/sale_reporting_category_list.xml
new file mode 100644
index 0000000000..e26866cd85
--- /dev/null
+++ b/modules/sale/view/sale_reporting_category_list.xml
@@ -0,0 +1,9 @@
+
+
+
+
+
+
+
+
diff --git a/modules/sale/view/sale_reporting_category_time_series_graph_number.xml b/modules/sale/view/sale_reporting_category_time_series_graph_number.xml
new file mode 100644
index 0000000000..93629fd87d
--- /dev/null
+++ b/modules/sale/view/sale_reporting_category_time_series_graph_number.xml
@@ -0,0 +1,11 @@
+
+
+
+
+
+
+
+
+
+
diff --git a/modules/sale/view/sale_reporting_category_time_series_graph_revenue.xml b/modules/sale/view/sale_reporting_category_time_series_graph_revenue.xml
new file mode 100644
index 0000000000..19db21a4f9
--- /dev/null
+++ b/modules/sale/view/sale_reporting_category_time_series_graph_revenue.xml
@@ -0,0 +1,11 @@
+
+
+
+
+
+
+
+
+
+
diff --git a/modules/sale/view/sale_reporting_category_time_series_list.xml b/modules/sale/view/sale_reporting_category_time_series_list.xml
new file mode 100644
index 0000000000..47be3fa189
--- /dev/null
+++ b/modules/sale/view/sale_reporting_category_time_series_list.xml
@@ -0,0 +1,8 @@
+
+
+
+
+
+
+
diff --git a/modules/sale/view/sale_reporting_category_tree.xml b/modules/sale/view/sale_reporting_category_tree.xml
new file mode 100644
index 0000000000..49afe263b1
--- /dev/null
+++ b/modules/sale/view/sale_reporting_category_tree.xml
@@ -0,0 +1,7 @@
+
+
+
+
+
+
diff --git a/modules/sale/view/sale_reporting_context_form.xml b/modules/sale/view/sale_reporting_context_form.xml
new file mode 100644
index 0000000000..c410145021
--- /dev/null
+++ b/modules/sale/view/sale_reporting_context_form.xml
@@ -0,0 +1,17 @@
+
+
+
diff --git a/modules/sale/view/sale_reporting_country_subdivision_time_series_graph_number.xml b/modules/sale/view/sale_reporting_country_subdivision_time_series_graph_number.xml
new file mode 100644
index 0000000000..93629fd87d
--- /dev/null
+++ b/modules/sale/view/sale_reporting_country_subdivision_time_series_graph_number.xml
@@ -0,0 +1,11 @@
+
+
+
+
+
+
+
+
+
+
diff --git a/modules/sale/view/sale_reporting_country_subdivision_time_series_graph_revenue.xml b/modules/sale/view/sale_reporting_country_subdivision_time_series_graph_revenue.xml
new file mode 100644
index 0000000000..19db21a4f9
--- /dev/null
+++ b/modules/sale/view/sale_reporting_country_subdivision_time_series_graph_revenue.xml
@@ -0,0 +1,11 @@
+
+
+
+
+
+
+
+
+
+
diff --git a/modules/sale/view/sale_reporting_country_subdivision_time_series_list.xml b/modules/sale/view/sale_reporting_country_subdivision_time_series_list.xml
new file mode 100644
index 0000000000..47be3fa189
--- /dev/null
+++ b/modules/sale/view/sale_reporting_country_subdivision_time_series_list.xml
@@ -0,0 +1,8 @@
+
+
+
+
+
+
+
diff --git a/modules/sale/view/sale_reporting_country_time_series_graph_number.xml b/modules/sale/view/sale_reporting_country_time_series_graph_number.xml
new file mode 100644
index 0000000000..19db21a4f9
--- /dev/null
+++ b/modules/sale/view/sale_reporting_country_time_series_graph_number.xml
@@ -0,0 +1,11 @@
+
+
+
+
+
+
+
+
+
+
diff --git a/modules/sale/view/sale_reporting_country_time_series_graph_revenue.xml b/modules/sale/view/sale_reporting_country_time_series_graph_revenue.xml
new file mode 100644
index 0000000000..19db21a4f9
--- /dev/null
+++ b/modules/sale/view/sale_reporting_country_time_series_graph_revenue.xml
@@ -0,0 +1,11 @@
+
+
+
+
+
+
+
+
+
+
diff --git a/modules/sale/view/sale_reporting_country_time_series_list.xml b/modules/sale/view/sale_reporting_country_time_series_list.xml
new file mode 100644
index 0000000000..47be3fa189
--- /dev/null
+++ b/modules/sale/view/sale_reporting_country_time_series_list.xml
@@ -0,0 +1,8 @@
+
+
+
+
+
+
+
diff --git a/modules/sale/view/sale_reporting_customer_graph_number.xml b/modules/sale/view/sale_reporting_customer_graph_number.xml
new file mode 100644
index 0000000000..ff9771b7e0
--- /dev/null
+++ b/modules/sale/view/sale_reporting_customer_graph_number.xml
@@ -0,0 +1,11 @@
+
+
+
+
+
+
+
+
+
+
diff --git a/modules/sale/view/sale_reporting_customer_graph_revenue.xml b/modules/sale/view/sale_reporting_customer_graph_revenue.xml
new file mode 100644
index 0000000000..5a7c034cba
--- /dev/null
+++ b/modules/sale/view/sale_reporting_customer_graph_revenue.xml
@@ -0,0 +1,11 @@
+
+
+
+
+
+
+
+
+
+
diff --git a/modules/sale/view/sale_reporting_customer_list.xml b/modules/sale/view/sale_reporting_customer_list.xml
new file mode 100644
index 0000000000..4541148c05
--- /dev/null
+++ b/modules/sale/view/sale_reporting_customer_list.xml
@@ -0,0 +1,9 @@
+
+
+
+
+
+
+
+
diff --git a/modules/sale/view/sale_reporting_customer_time_series_graph_number.xml b/modules/sale/view/sale_reporting_customer_time_series_graph_number.xml
new file mode 100644
index 0000000000..93629fd87d
--- /dev/null
+++ b/modules/sale/view/sale_reporting_customer_time_series_graph_number.xml
@@ -0,0 +1,11 @@
+
+
+
+
+
+
+
+
+
+
diff --git a/modules/sale/view/sale_reporting_customer_time_series_graph_revenue.xml b/modules/sale/view/sale_reporting_customer_time_series_graph_revenue.xml
new file mode 100644
index 0000000000..19db21a4f9
--- /dev/null
+++ b/modules/sale/view/sale_reporting_customer_time_series_graph_revenue.xml
@@ -0,0 +1,11 @@
+
+
+
+
+
+
+
+
+
+
diff --git a/modules/sale/view/sale_reporting_customer_time_series_list.xml b/modules/sale/view/sale_reporting_customer_time_series_list.xml
new file mode 100644
index 0000000000..47be3fa189
--- /dev/null
+++ b/modules/sale/view/sale_reporting_customer_time_series_list.xml
@@ -0,0 +1,8 @@
+
+
+
+
+
+
+
diff --git a/modules/sale/view/sale_reporting_product_graph_number.xml b/modules/sale/view/sale_reporting_product_graph_number.xml
new file mode 100644
index 0000000000..8dfd8a9ebc
--- /dev/null
+++ b/modules/sale/view/sale_reporting_product_graph_number.xml
@@ -0,0 +1,11 @@
+
+
+
+
+
+
+
+
+
+
diff --git a/modules/sale/view/sale_reporting_product_graph_revenue.xml b/modules/sale/view/sale_reporting_product_graph_revenue.xml
new file mode 100644
index 0000000000..fdbbfecdc7
--- /dev/null
+++ b/modules/sale/view/sale_reporting_product_graph_revenue.xml
@@ -0,0 +1,11 @@
+
+
+
+
+
+
+
+
+
+
diff --git a/modules/sale/view/sale_reporting_product_list.xml b/modules/sale/view/sale_reporting_product_list.xml
new file mode 100644
index 0000000000..75626e0725
--- /dev/null
+++ b/modules/sale/view/sale_reporting_product_list.xml
@@ -0,0 +1,9 @@
+
+
+
+
+
+
+
+
diff --git a/modules/sale/view/sale_reporting_product_time_series_graph_number.xml b/modules/sale/view/sale_reporting_product_time_series_graph_number.xml
new file mode 100644
index 0000000000..93629fd87d
--- /dev/null
+++ b/modules/sale/view/sale_reporting_product_time_series_graph_number.xml
@@ -0,0 +1,11 @@
+
+
+
+
+
+
+
+
+
+
diff --git a/modules/sale/view/sale_reporting_product_time_series_graph_revenue.xml b/modules/sale/view/sale_reporting_product_time_series_graph_revenue.xml
new file mode 100644
index 0000000000..19db21a4f9
--- /dev/null
+++ b/modules/sale/view/sale_reporting_product_time_series_graph_revenue.xml
@@ -0,0 +1,11 @@
+
+
+
+
+
+
+
+
+
+
diff --git a/modules/sale/view/sale_reporting_product_time_series_list.xml b/modules/sale/view/sale_reporting_product_time_series_list.xml
new file mode 100644
index 0000000000..47be3fa189
--- /dev/null
+++ b/modules/sale/view/sale_reporting_product_time_series_list.xml
@@ -0,0 +1,8 @@
+
+
+
+
+
+
+
diff --git a/modules/sale/view/sale_reporting_region_tree.xml b/modules/sale/view/sale_reporting_region_tree.xml
new file mode 100644
index 0000000000..4546131fae
--- /dev/null
+++ b/modules/sale/view/sale_reporting_region_tree.xml
@@ -0,0 +1,9 @@
+
+
+
+
+
+
+
+
diff --git a/modules/sale/view/sale_tree.xml b/modules/sale/view/sale_tree.xml
new file mode 100644
index 0000000000..724e150f0c
--- /dev/null
+++ b/modules/sale/view/sale_tree.xml
@@ -0,0 +1,15 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/modules/sale/view/template_form.xml b/modules/sale/view/template_form.xml
new file mode 100644
index 0000000000..dbb109423d
--- /dev/null
+++ b/modules/sale/view/template_form.xml
@@ -0,0 +1,21 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/modules/sale/view/template_tree.xml b/modules/sale/view/template_tree.xml
new file mode 100644
index 0000000000..22e86f92e1
--- /dev/null
+++ b/modules/sale/view/template_tree.xml
@@ -0,0 +1,8 @@
+
+
+
+
+
+
+
diff --git a/modules/sale_advance_payment/.drone.yml b/modules/sale_advance_payment/.drone.yml
new file mode 100644
index 0000000000..2049d30a49
--- /dev/null
+++ b/modules/sale_advance_payment/.drone.yml
@@ -0,0 +1,68 @@
+clone:
+ hg:
+ image: plugins/hg
+ environment:
+ - HG_SHARE_POOL=/root/.cache/hg
+ volumes:
+ - cache:/root/.cache
+
+pipeline:
+ tox:
+ image: ${IMAGE}
+ environment:
+ - CFLAGS=-O0
+ - DB_CACHE=/cache
+ - TOX_TESTENV_PASSENV=CFLAGS DB_CACHE CI_BUILD_NUMBER CI_JOB_NUMBER CI_JOB_ID
+ - POSTGRESQL_URI=postgresql://postgres@postgresql:5432/
+ commands:
+ - echo "[extensions]" >> /root/.hgrc
+ - echo "hgext.share =" >> /root/.hgrc
+ - echo "[share]" >> /root/.hgrc
+ - echo "pool = /root/.cache/hg" >> /root/.hgrc
+ - pip install tox
+ - tox -e "${TOXENV}-${DATABASE}"
+ volumes:
+ - cache:/root/.cache
+ check_dist:
+ image: ${IMAGE}
+ commands:
+ - pip install twine
+ - python setup.py sdist
+ - twine check dist/*
+
+services:
+ postgresql:
+ image: postgres
+ environment:
+ - POSTGRES_HOST_AUTH_METHOD=trust
+ command: "-c fsync=off -c synchronous_commit=off -c full_page_writes=off"
+ when:
+ matrix:
+ DATABASE: postgresql
+
+matrix:
+ include:
+ - IMAGE: python:3.6
+ TOXENV: py36
+ DATABASE: sqlite
+ - IMAGE: python:3.6
+ TOXENV: py36
+ DATABASE: postgresql
+ - IMAGE: python:3.7
+ TOXENV: py37
+ DATABASE: sqlite
+ - IMAGE: python:3.7
+ TOXENV: py37
+ DATABASE: postgresql
+ - IMAGE: python:3.8
+ TOXENV: py38
+ DATABASE: sqlite
+ - IMAGE: python:3.8
+ TOXENV: py38
+ DATABASE: postgresql
+ - IMAGE: python:3.9
+ TOXENV: py39
+ DATABASE: sqlite
+ - IMAGE: python:3.9
+ TOXENV: py39
+ DATABASE: postgresql
diff --git a/modules/sale_advance_payment/.flake8 b/modules/sale_advance_payment/.flake8
new file mode 100644
index 0000000000..fa6b4f66d1
--- /dev/null
+++ b/modules/sale_advance_payment/.flake8
@@ -0,0 +1,2 @@
+[flake8]
+ignore=E123,E124,E126,E128,E741,W503
diff --git a/modules/sale_advance_payment/CHANGELOG b/modules/sale_advance_payment/CHANGELOG
new file mode 100644
index 0000000000..18eea04ce8
--- /dev/null
+++ b/modules/sale_advance_payment/CHANGELOG
@@ -0,0 +1,32 @@
+Version 6.0.1 - 2021-10-15
+* Bug fixes (see mercurial logs for details)
+
+Version 6.0.0 - 2021-05-03
+* Bug fixes (see mercurial logs for details)
+
+Version 5.8.0 - 2020-11-02
+* Bug fixes (see mercurial logs for details)
+* Remove support for Python 3.5
+
+Version 5.6.0 - 2020-05-04
+* Bug fixes (see mercurial logs for details)
+
+Version 5.4.0 - 2019-11-04
+* Bug fixes (see mercurial logs for details)
+
+Version 5.2.0 - 2019-05-06
+* Bug fixes (see mercurial logs for details)
+* Add unearned revenue on account type
+
+Version 5.0.0 - 2018-10-01
+* Bug fixes (see mercurial logs for details)
+* Remove support for Python 2.7
+
+Version 4.8.0 - 2018-04-23
+* Bug fixes (see mercurial logs for details)
+
+Version 4.6.0 - 2017-10-30
+* Bug fixes (see mercurial logs for details)
+
+Version 4.4.0 - 2017-05-01
+* Initial release
diff --git a/modules/sale_advance_payment/COPYRIGHT b/modules/sale_advance_payment/COPYRIGHT
new file mode 100644
index 0000000000..f1aa817a10
--- /dev/null
+++ b/modules/sale_advance_payment/COPYRIGHT
@@ -0,0 +1,16 @@
+Copyright (C) 2015-2017 Nicolas Évrard.
+Copyright (C) 2017-2021 Cédric Krier.
+Copyright (C) 2015-2021 B2CK SPRL.
+
+This program is free software: you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation, either version 3 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program. If not, see .
diff --git a/modules/sale_advance_payment/LICENSE b/modules/sale_advance_payment/LICENSE
new file mode 100644
index 0000000000..94a9ed024d
--- /dev/null
+++ b/modules/sale_advance_payment/LICENSE
@@ -0,0 +1,674 @@
+ GNU GENERAL PUBLIC LICENSE
+ Version 3, 29 June 2007
+
+ Copyright (C) 2007 Free Software Foundation, Inc.
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+ Preamble
+
+ The GNU General Public License is a free, copyleft license for
+software and other kinds of works.
+
+ The licenses for most software and other practical works are designed
+to take away your freedom to share and change the works. By contrast,
+the GNU General Public License is intended to guarantee your freedom to
+share and change all versions of a program--to make sure it remains free
+software for all its users. We, the Free Software Foundation, use the
+GNU General Public License for most of our software; it applies also to
+any other work released this way by its authors. You can apply it to
+your programs, too.
+
+ When we speak of free software, we are referring to freedom, not
+price. Our General Public Licenses are designed to make sure that you
+have the freedom to distribute copies of free software (and charge for
+them if you wish), that you receive source code or can get it if you
+want it, that you can change the software or use pieces of it in new
+free programs, and that you know you can do these things.
+
+ To protect your rights, we need to prevent others from denying you
+these rights or asking you to surrender the rights. Therefore, you have
+certain responsibilities if you distribute copies of the software, or if
+you modify it: responsibilities to respect the freedom of others.
+
+ For example, if you distribute copies of such a program, whether
+gratis or for a fee, you must pass on to the recipients the same
+freedoms that you received. You must make sure that they, too, receive
+or can get the source code. And you must show them these terms so they
+know their rights.
+
+ Developers that use the GNU GPL protect your rights with two steps:
+(1) assert copyright on the software, and (2) offer you this License
+giving you legal permission to copy, distribute and/or modify it.
+
+ For the developers' and authors' protection, the GPL clearly explains
+that there is no warranty for this free software. For both users' and
+authors' sake, the GPL requires that modified versions be marked as
+changed, so that their problems will not be attributed erroneously to
+authors of previous versions.
+
+ Some devices are designed to deny users access to install or run
+modified versions of the software inside them, although the manufacturer
+can do so. This is fundamentally incompatible with the aim of
+protecting users' freedom to change the software. The systematic
+pattern of such abuse occurs in the area of products for individuals to
+use, which is precisely where it is most unacceptable. Therefore, we
+have designed this version of the GPL to prohibit the practice for those
+products. If such problems arise substantially in other domains, we
+stand ready to extend this provision to those domains in future versions
+of the GPL, as needed to protect the freedom of users.
+
+ Finally, every program is threatened constantly by software patents.
+States should not allow patents to restrict development and use of
+software on general-purpose computers, but in those that do, we wish to
+avoid the special danger that patents applied to a free program could
+make it effectively proprietary. To prevent this, the GPL assures that
+patents cannot be used to render the program non-free.
+
+ The precise terms and conditions for copying, distribution and
+modification follow.
+
+ TERMS AND CONDITIONS
+
+ 0. Definitions.
+
+ "This License" refers to version 3 of the GNU General Public License.
+
+ "Copyright" also means copyright-like laws that apply to other kinds of
+works, such as semiconductor masks.
+
+ "The Program" refers to any copyrightable work licensed under this
+License. Each licensee is addressed as "you". "Licensees" and
+"recipients" may be individuals or organizations.
+
+ To "modify" a work means to copy from or adapt all or part of the work
+in a fashion requiring copyright permission, other than the making of an
+exact copy. The resulting work is called a "modified version" of the
+earlier work or a work "based on" the earlier work.
+
+ A "covered work" means either the unmodified Program or a work based
+on the Program.
+
+ To "propagate" a work means to do anything with it that, without
+permission, would make you directly or secondarily liable for
+infringement under applicable copyright law, except executing it on a
+computer or modifying a private copy. Propagation includes copying,
+distribution (with or without modification), making available to the
+public, and in some countries other activities as well.
+
+ To "convey" a work means any kind of propagation that enables other
+parties to make or receive copies. Mere interaction with a user through
+a computer network, with no transfer of a copy, is not conveying.
+
+ An interactive user interface displays "Appropriate Legal Notices"
+to the extent that it includes a convenient and prominently visible
+feature that (1) displays an appropriate copyright notice, and (2)
+tells the user that there is no warranty for the work (except to the
+extent that warranties are provided), that licensees may convey the
+work under this License, and how to view a copy of this License. If
+the interface presents a list of user commands or options, such as a
+menu, a prominent item in the list meets this criterion.
+
+ 1. Source Code.
+
+ The "source code" for a work means the preferred form of the work
+for making modifications to it. "Object code" means any non-source
+form of a work.
+
+ A "Standard Interface" means an interface that either is an official
+standard defined by a recognized standards body, or, in the case of
+interfaces specified for a particular programming language, one that
+is widely used among developers working in that language.
+
+ The "System Libraries" of an executable work include anything, other
+than the work as a whole, that (a) is included in the normal form of
+packaging a Major Component, but which is not part of that Major
+Component, and (b) serves only to enable use of the work with that
+Major Component, or to implement a Standard Interface for which an
+implementation is available to the public in source code form. A
+"Major Component", in this context, means a major essential component
+(kernel, window system, and so on) of the specific operating system
+(if any) on which the executable work runs, or a compiler used to
+produce the work, or an object code interpreter used to run it.
+
+ The "Corresponding Source" for a work in object code form means all
+the source code needed to generate, install, and (for an executable
+work) run the object code and to modify the work, including scripts to
+control those activities. However, it does not include the work's
+System Libraries, or general-purpose tools or generally available free
+programs which are used unmodified in performing those activities but
+which are not part of the work. For example, Corresponding Source
+includes interface definition files associated with source files for
+the work, and the source code for shared libraries and dynamically
+linked subprograms that the work is specifically designed to require,
+such as by intimate data communication or control flow between those
+subprograms and other parts of the work.
+
+ The Corresponding Source need not include anything that users
+can regenerate automatically from other parts of the Corresponding
+Source.
+
+ The Corresponding Source for a work in source code form is that
+same work.
+
+ 2. Basic Permissions.
+
+ All rights granted under this License are granted for the term of
+copyright on the Program, and are irrevocable provided the stated
+conditions are met. This License explicitly affirms your unlimited
+permission to run the unmodified Program. The output from running a
+covered work is covered by this License only if the output, given its
+content, constitutes a covered work. This License acknowledges your
+rights of fair use or other equivalent, as provided by copyright law.
+
+ You may make, run and propagate covered works that you do not
+convey, without conditions so long as your license otherwise remains
+in force. You may convey covered works to others for the sole purpose
+of having them make modifications exclusively for you, or provide you
+with facilities for running those works, provided that you comply with
+the terms of this License in conveying all material for which you do
+not control copyright. Those thus making or running the covered works
+for you must do so exclusively on your behalf, under your direction
+and control, on terms that prohibit them from making any copies of
+your copyrighted material outside their relationship with you.
+
+ Conveying under any other circumstances is permitted solely under
+the conditions stated below. Sublicensing is not allowed; section 10
+makes it unnecessary.
+
+ 3. Protecting Users' Legal Rights From Anti-Circumvention Law.
+
+ No covered work shall be deemed part of an effective technological
+measure under any applicable law fulfilling obligations under article
+11 of the WIPO copyright treaty adopted on 20 December 1996, or
+similar laws prohibiting or restricting circumvention of such
+measures.
+
+ When you convey a covered work, you waive any legal power to forbid
+circumvention of technological measures to the extent such circumvention
+is effected by exercising rights under this License with respect to
+the covered work, and you disclaim any intention to limit operation or
+modification of the work as a means of enforcing, against the work's
+users, your or third parties' legal rights to forbid circumvention of
+technological measures.
+
+ 4. Conveying Verbatim Copies.
+
+ You may convey verbatim copies of the Program's source code as you
+receive it, in any medium, provided that you conspicuously and
+appropriately publish on each copy an appropriate copyright notice;
+keep intact all notices stating that this License and any
+non-permissive terms added in accord with section 7 apply to the code;
+keep intact all notices of the absence of any warranty; and give all
+recipients a copy of this License along with the Program.
+
+ You may charge any price or no price for each copy that you convey,
+and you may offer support or warranty protection for a fee.
+
+ 5. Conveying Modified Source Versions.
+
+ You may convey a work based on the Program, or the modifications to
+produce it from the Program, in the form of source code under the
+terms of section 4, provided that you also meet all of these conditions:
+
+ a) The work must carry prominent notices stating that you modified
+ it, and giving a relevant date.
+
+ b) The work must carry prominent notices stating that it is
+ released under this License and any conditions added under section
+ 7. This requirement modifies the requirement in section 4 to
+ "keep intact all notices".
+
+ c) You must license the entire work, as a whole, under this
+ License to anyone who comes into possession of a copy. This
+ License will therefore apply, along with any applicable section 7
+ additional terms, to the whole of the work, and all its parts,
+ regardless of how they are packaged. This License gives no
+ permission to license the work in any other way, but it does not
+ invalidate such permission if you have separately received it.
+
+ d) If the work has interactive user interfaces, each must display
+ Appropriate Legal Notices; however, if the Program has interactive
+ interfaces that do not display Appropriate Legal Notices, your
+ work need not make them do so.
+
+ A compilation of a covered work with other separate and independent
+works, which are not by their nature extensions of the covered work,
+and which are not combined with it such as to form a larger program,
+in or on a volume of a storage or distribution medium, is called an
+"aggregate" if the compilation and its resulting copyright are not
+used to limit the access or legal rights of the compilation's users
+beyond what the individual works permit. Inclusion of a covered work
+in an aggregate does not cause this License to apply to the other
+parts of the aggregate.
+
+ 6. Conveying Non-Source Forms.
+
+ You may convey a covered work in object code form under the terms
+of sections 4 and 5, provided that you also convey the
+machine-readable Corresponding Source under the terms of this License,
+in one of these ways:
+
+ a) Convey the object code in, or embodied in, a physical product
+ (including a physical distribution medium), accompanied by the
+ Corresponding Source fixed on a durable physical medium
+ customarily used for software interchange.
+
+ b) Convey the object code in, or embodied in, a physical product
+ (including a physical distribution medium), accompanied by a
+ written offer, valid for at least three years and valid for as
+ long as you offer spare parts or customer support for that product
+ model, to give anyone who possesses the object code either (1) a
+ copy of the Corresponding Source for all the software in the
+ product that is covered by this License, on a durable physical
+ medium customarily used for software interchange, for a price no
+ more than your reasonable cost of physically performing this
+ conveying of source, or (2) access to copy the
+ Corresponding Source from a network server at no charge.
+
+ c) Convey individual copies of the object code with a copy of the
+ written offer to provide the Corresponding Source. This
+ alternative is allowed only occasionally and noncommercially, and
+ only if you received the object code with such an offer, in accord
+ with subsection 6b.
+
+ d) Convey the object code by offering access from a designated
+ place (gratis or for a charge), and offer equivalent access to the
+ Corresponding Source in the same way through the same place at no
+ further charge. You need not require recipients to copy the
+ Corresponding Source along with the object code. If the place to
+ copy the object code is a network server, the Corresponding Source
+ may be on a different server (operated by you or a third party)
+ that supports equivalent copying facilities, provided you maintain
+ clear directions next to the object code saying where to find the
+ Corresponding Source. Regardless of what server hosts the
+ Corresponding Source, you remain obligated to ensure that it is
+ available for as long as needed to satisfy these requirements.
+
+ e) Convey the object code using peer-to-peer transmission, provided
+ you inform other peers where the object code and Corresponding
+ Source of the work are being offered to the general public at no
+ charge under subsection 6d.
+
+ A separable portion of the object code, whose source code is excluded
+from the Corresponding Source as a System Library, need not be
+included in conveying the object code work.
+
+ A "User Product" is either (1) a "consumer product", which means any
+tangible personal property which is normally used for personal, family,
+or household purposes, or (2) anything designed or sold for incorporation
+into a dwelling. In determining whether a product is a consumer product,
+doubtful cases shall be resolved in favor of coverage. For a particular
+product received by a particular user, "normally used" refers to a
+typical or common use of that class of product, regardless of the status
+of the particular user or of the way in which the particular user
+actually uses, or expects or is expected to use, the product. A product
+is a consumer product regardless of whether the product has substantial
+commercial, industrial or non-consumer uses, unless such uses represent
+the only significant mode of use of the product.
+
+ "Installation Information" for a User Product means any methods,
+procedures, authorization keys, or other information required to install
+and execute modified versions of a covered work in that User Product from
+a modified version of its Corresponding Source. The information must
+suffice to ensure that the continued functioning of the modified object
+code is in no case prevented or interfered with solely because
+modification has been made.
+
+ If you convey an object code work under this section in, or with, or
+specifically for use in, a User Product, and the conveying occurs as
+part of a transaction in which the right of possession and use of the
+User Product is transferred to the recipient in perpetuity or for a
+fixed term (regardless of how the transaction is characterized), the
+Corresponding Source conveyed under this section must be accompanied
+by the Installation Information. But this requirement does not apply
+if neither you nor any third party retains the ability to install
+modified object code on the User Product (for example, the work has
+been installed in ROM).
+
+ The requirement to provide Installation Information does not include a
+requirement to continue to provide support service, warranty, or updates
+for a work that has been modified or installed by the recipient, or for
+the User Product in which it has been modified or installed. Access to a
+network may be denied when the modification itself materially and
+adversely affects the operation of the network or violates the rules and
+protocols for communication across the network.
+
+ Corresponding Source conveyed, and Installation Information provided,
+in accord with this section must be in a format that is publicly
+documented (and with an implementation available to the public in
+source code form), and must require no special password or key for
+unpacking, reading or copying.
+
+ 7. Additional Terms.
+
+ "Additional permissions" are terms that supplement the terms of this
+License by making exceptions from one or more of its conditions.
+Additional permissions that are applicable to the entire Program shall
+be treated as though they were included in this License, to the extent
+that they are valid under applicable law. If additional permissions
+apply only to part of the Program, that part may be used separately
+under those permissions, but the entire Program remains governed by
+this License without regard to the additional permissions.
+
+ When you convey a copy of a covered work, you may at your option
+remove any additional permissions from that copy, or from any part of
+it. (Additional permissions may be written to require their own
+removal in certain cases when you modify the work.) You may place
+additional permissions on material, added by you to a covered work,
+for which you have or can give appropriate copyright permission.
+
+ Notwithstanding any other provision of this License, for material you
+add to a covered work, you may (if authorized by the copyright holders of
+that material) supplement the terms of this License with terms:
+
+ a) Disclaiming warranty or limiting liability differently from the
+ terms of sections 15 and 16 of this License; or
+
+ b) Requiring preservation of specified reasonable legal notices or
+ author attributions in that material or in the Appropriate Legal
+ Notices displayed by works containing it; or
+
+ c) Prohibiting misrepresentation of the origin of that material, or
+ requiring that modified versions of such material be marked in
+ reasonable ways as different from the original version; or
+
+ d) Limiting the use for publicity purposes of names of licensors or
+ authors of the material; or
+
+ e) Declining to grant rights under trademark law for use of some
+ trade names, trademarks, or service marks; or
+
+ f) Requiring indemnification of licensors and authors of that
+ material by anyone who conveys the material (or modified versions of
+ it) with contractual assumptions of liability to the recipient, for
+ any liability that these contractual assumptions directly impose on
+ those licensors and authors.
+
+ All other non-permissive additional terms are considered "further
+restrictions" within the meaning of section 10. If the Program as you
+received it, or any part of it, contains a notice stating that it is
+governed by this License along with a term that is a further
+restriction, you may remove that term. If a license document contains
+a further restriction but permits relicensing or conveying under this
+License, you may add to a covered work material governed by the terms
+of that license document, provided that the further restriction does
+not survive such relicensing or conveying.
+
+ If you add terms to a covered work in accord with this section, you
+must place, in the relevant source files, a statement of the
+additional terms that apply to those files, or a notice indicating
+where to find the applicable terms.
+
+ Additional terms, permissive or non-permissive, may be stated in the
+form of a separately written license, or stated as exceptions;
+the above requirements apply either way.
+
+ 8. Termination.
+
+ You may not propagate or modify a covered work except as expressly
+provided under this License. Any attempt otherwise to propagate or
+modify it is void, and will automatically terminate your rights under
+this License (including any patent licenses granted under the third
+paragraph of section 11).
+
+ However, if you cease all violation of this License, then your
+license from a particular copyright holder is reinstated (a)
+provisionally, unless and until the copyright holder explicitly and
+finally terminates your license, and (b) permanently, if the copyright
+holder fails to notify you of the violation by some reasonable means
+prior to 60 days after the cessation.
+
+ Moreover, your license from a particular copyright holder is
+reinstated permanently if the copyright holder notifies you of the
+violation by some reasonable means, this is the first time you have
+received notice of violation of this License (for any work) from that
+copyright holder, and you cure the violation prior to 30 days after
+your receipt of the notice.
+
+ Termination of your rights under this section does not terminate the
+licenses of parties who have received copies or rights from you under
+this License. If your rights have been terminated and not permanently
+reinstated, you do not qualify to receive new licenses for the same
+material under section 10.
+
+ 9. Acceptance Not Required for Having Copies.
+
+ You are not required to accept this License in order to receive or
+run a copy of the Program. Ancillary propagation of a covered work
+occurring solely as a consequence of using peer-to-peer transmission
+to receive a copy likewise does not require acceptance. However,
+nothing other than this License grants you permission to propagate or
+modify any covered work. These actions infringe copyright if you do
+not accept this License. Therefore, by modifying or propagating a
+covered work, you indicate your acceptance of this License to do so.
+
+ 10. Automatic Licensing of Downstream Recipients.
+
+ Each time you convey a covered work, the recipient automatically
+receives a license from the original licensors, to run, modify and
+propagate that work, subject to this License. You are not responsible
+for enforcing compliance by third parties with this License.
+
+ An "entity transaction" is a transaction transferring control of an
+organization, or substantially all assets of one, or subdividing an
+organization, or merging organizations. If propagation of a covered
+work results from an entity transaction, each party to that
+transaction who receives a copy of the work also receives whatever
+licenses to the work the party's predecessor in interest had or could
+give under the previous paragraph, plus a right to possession of the
+Corresponding Source of the work from the predecessor in interest, if
+the predecessor has it or can get it with reasonable efforts.
+
+ You may not impose any further restrictions on the exercise of the
+rights granted or affirmed under this License. For example, you may
+not impose a license fee, royalty, or other charge for exercise of
+rights granted under this License, and you may not initiate litigation
+(including a cross-claim or counterclaim in a lawsuit) alleging that
+any patent claim is infringed by making, using, selling, offering for
+sale, or importing the Program or any portion of it.
+
+ 11. Patents.
+
+ A "contributor" is a copyright holder who authorizes use under this
+License of the Program or a work on which the Program is based. The
+work thus licensed is called the contributor's "contributor version".
+
+ A contributor's "essential patent claims" are all patent claims
+owned or controlled by the contributor, whether already acquired or
+hereafter acquired, that would be infringed by some manner, permitted
+by this License, of making, using, or selling its contributor version,
+but do not include claims that would be infringed only as a
+consequence of further modification of the contributor version. For
+purposes of this definition, "control" includes the right to grant
+patent sublicenses in a manner consistent with the requirements of
+this License.
+
+ Each contributor grants you a non-exclusive, worldwide, royalty-free
+patent license under the contributor's essential patent claims, to
+make, use, sell, offer for sale, import and otherwise run, modify and
+propagate the contents of its contributor version.
+
+ In the following three paragraphs, a "patent license" is any express
+agreement or commitment, however denominated, not to enforce a patent
+(such as an express permission to practice a patent or covenant not to
+sue for patent infringement). To "grant" such a patent license to a
+party means to make such an agreement or commitment not to enforce a
+patent against the party.
+
+ If you convey a covered work, knowingly relying on a patent license,
+and the Corresponding Source of the work is not available for anyone
+to copy, free of charge and under the terms of this License, through a
+publicly available network server or other readily accessible means,
+then you must either (1) cause the Corresponding Source to be so
+available, or (2) arrange to deprive yourself of the benefit of the
+patent license for this particular work, or (3) arrange, in a manner
+consistent with the requirements of this License, to extend the patent
+license to downstream recipients. "Knowingly relying" means you have
+actual knowledge that, but for the patent license, your conveying the
+covered work in a country, or your recipient's use of the covered work
+in a country, would infringe one or more identifiable patents in that
+country that you have reason to believe are valid.
+
+ If, pursuant to or in connection with a single transaction or
+arrangement, you convey, or propagate by procuring conveyance of, a
+covered work, and grant a patent license to some of the parties
+receiving the covered work authorizing them to use, propagate, modify
+or convey a specific copy of the covered work, then the patent license
+you grant is automatically extended to all recipients of the covered
+work and works based on it.
+
+ A patent license is "discriminatory" if it does not include within
+the scope of its coverage, prohibits the exercise of, or is
+conditioned on the non-exercise of one or more of the rights that are
+specifically granted under this License. You may not convey a covered
+work if you are a party to an arrangement with a third party that is
+in the business of distributing software, under which you make payment
+to the third party based on the extent of your activity of conveying
+the work, and under which the third party grants, to any of the
+parties who would receive the covered work from you, a discriminatory
+patent license (a) in connection with copies of the covered work
+conveyed by you (or copies made from those copies), or (b) primarily
+for and in connection with specific products or compilations that
+contain the covered work, unless you entered into that arrangement,
+or that patent license was granted, prior to 28 March 2007.
+
+ Nothing in this License shall be construed as excluding or limiting
+any implied license or other defenses to infringement that may
+otherwise be available to you under applicable patent law.
+
+ 12. No Surrender of Others' Freedom.
+
+ If conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License. If you cannot convey a
+covered work so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you may
+not convey it at all. For example, if you agree to terms that obligate you
+to collect a royalty for further conveying from those to whom you convey
+the Program, the only way you could satisfy both those terms and this
+License would be to refrain entirely from conveying the Program.
+
+ 13. Use with the GNU Affero General Public License.
+
+ Notwithstanding any other provision of this License, you have
+permission to link or combine any covered work with a work licensed
+under version 3 of the GNU Affero General Public License into a single
+combined work, and to convey the resulting work. The terms of this
+License will continue to apply to the part which is the covered work,
+but the special requirements of the GNU Affero General Public License,
+section 13, concerning interaction through a network will apply to the
+combination as such.
+
+ 14. Revised Versions of this License.
+
+ The Free Software Foundation may publish revised and/or new versions of
+the GNU General Public License from time to time. Such new versions will
+be similar in spirit to the present version, but may differ in detail to
+address new problems or concerns.
+
+ Each version is given a distinguishing version number. If the
+Program specifies that a certain numbered version of the GNU General
+Public License "or any later version" applies to it, you have the
+option of following the terms and conditions either of that numbered
+version or of any later version published by the Free Software
+Foundation. If the Program does not specify a version number of the
+GNU General Public License, you may choose any version ever published
+by the Free Software Foundation.
+
+ If the Program specifies that a proxy can decide which future
+versions of the GNU General Public License can be used, that proxy's
+public statement of acceptance of a version permanently authorizes you
+to choose that version for the Program.
+
+ Later license versions may give you additional or different
+permissions. However, no additional obligations are imposed on any
+author or copyright holder as a result of your choosing to follow a
+later version.
+
+ 15. Disclaimer of Warranty.
+
+ THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY
+APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT
+HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY
+OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO,
+THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM
+IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF
+ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
+
+ 16. Limitation of Liability.
+
+ IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS
+THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY
+GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE
+USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF
+DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD
+PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS),
+EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF
+SUCH DAMAGES.
+
+ 17. Interpretation of Sections 15 and 16.
+
+ If the disclaimer of warranty and limitation of liability provided
+above cannot be given local legal effect according to their terms,
+reviewing courts shall apply local law that most closely approximates
+an absolute waiver of all civil liability in connection with the
+Program, unless a warranty or assumption of liability accompanies a
+copy of the Program in return for a fee.
+
+ END OF TERMS AND CONDITIONS
+
+ How to Apply These Terms to Your New Programs
+
+ If you develop a new program, and you want it to be of the greatest
+possible use to the public, the best way to achieve this is to make it
+free software which everyone can redistribute and change under these terms.
+
+ To do so, attach the following notices to the program. It is safest
+to attach them to the start of each source file to most effectively
+state the exclusion of warranty; and each file should have at least
+the "copyright" line and a pointer to where the full notice is found.
+
+
+ Copyright (C)
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see .
+
+Also add information on how to contact you by electronic and paper mail.
+
+ If the program does terminal interaction, make it output a short
+notice like this when it starts in an interactive mode:
+
+ Copyright (C)
+ This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
+ This is free software, and you are welcome to redistribute it
+ under certain conditions; type `show c' for details.
+
+The hypothetical commands `show w' and `show c' should show the appropriate
+parts of the General Public License. Of course, your program's commands
+might be different; for a GUI interface, you would use an "about box".
+
+ You should also get your employer (if you work as a programmer) or school,
+if any, to sign a "copyright disclaimer" for the program, if necessary.
+For more information on this, and how to apply and follow the GNU GPL, see
+.
+
+ The GNU General Public License does not permit incorporating your program
+into proprietary programs. If your program is a subroutine library, you
+may consider it more useful to permit linking proprietary applications with
+the library. If this is what you want to do, use the GNU Lesser General
+Public License instead of this License. But first, please read
+.
diff --git a/modules/sale_advance_payment/MANIFEST.in b/modules/sale_advance_payment/MANIFEST.in
new file mode 100644
index 0000000000..e88b2348a3
--- /dev/null
+++ b/modules/sale_advance_payment/MANIFEST.in
@@ -0,0 +1,5 @@
+include CHANGELOG
+include COPYRIGHT
+include LICENSE
+include README.rst
+include doc/*
diff --git a/modules/sale_advance_payment/README.rst b/modules/sale_advance_payment/README.rst
new file mode 120000
index 0000000000..176d9c2695
--- /dev/null
+++ b/modules/sale_advance_payment/README.rst
@@ -0,0 +1 @@
+doc/index.rst
\ No newline at end of file
diff --git a/modules/sale_advance_payment/__init__.py b/modules/sale_advance_payment/__init__.py
new file mode 100644
index 0000000000..34afd60dc7
--- /dev/null
+++ b/modules/sale_advance_payment/__init__.py
@@ -0,0 +1,26 @@
+# This file is part of Tryton. The COPYRIGHT file at the top level of
+# this repository contains the full copyright notices and license terms.
+
+from trytond.pool import Pool
+from . import sale
+from . import account
+from . import stock
+
+
+def register():
+ Pool.register(
+ sale.AdvancePaymentTerm,
+ sale.AdvancePaymentTermLine,
+ sale.AdvancePaymentTermLineAccount,
+ sale.AdvancePaymentCondition,
+ sale.Sale,
+ sale.SaleLine,
+ account.AccountTypeTemplate,
+ account.AccountType,
+ account.Invoice,
+ account.InvoiceLine,
+ stock.ShipmentOut,
+ module='sale_advance_payment', type_='model')
+ Pool.register(
+ sale.HandleInvoiceException,
+ module='sale_advance_payment', type_='wizard')
diff --git a/modules/sale_advance_payment/account.py b/modules/sale_advance_payment/account.py
new file mode 100644
index 0000000000..aa7ff5b49e
--- /dev/null
+++ b/modules/sale_advance_payment/account.py
@@ -0,0 +1,75 @@
+# This file is part of Tryton. The COPYRIGHT file at the top level of
+# this repository contains the full copyright notices and license terms.
+
+from trytond.model import fields
+from trytond.pool import Pool, PoolMeta
+from trytond.pyson import If, Eval, Bool
+
+
+def AccountTypeMixin(template=False):
+
+ class Mixin:
+ __slots__ = ()
+ unearned_revenue = fields.Boolean(
+ "Unearned Revenue",
+ domain=[
+ If(Eval('statement') != 'balance',
+ ('unearned_revenue', '=', False), ()),
+ ],
+ states={
+ 'invisible': ((Eval('statement') != 'balance')
+ | Eval('assets', True)),
+ },
+ depends=['statement', 'assets'])
+ if not template:
+ for fname in dir(Mixin):
+ field = getattr(Mixin, fname)
+ if not isinstance(field, fields.Field):
+ continue
+ field.states['readonly'] = (
+ Bool(Eval('template', -1)) & ~Eval('template_override', False))
+ return Mixin
+
+
+class AccountTypeTemplate(AccountTypeMixin(template=True), metaclass=PoolMeta):
+ __name__ = 'account.account.type.template'
+
+ def _get_type_value(self, type=None):
+ values = super()._get_type_value(type=type)
+ if not type or type.unearned_revenue != self.unearned_revenue:
+ values['unearned_revenue'] = self.unearned_revenue
+ return values
+
+
+class AccountType(AccountTypeMixin(), metaclass=PoolMeta):
+ __name__ = 'account.account.type'
+
+
+class Invoice(metaclass=PoolMeta):
+ __name__ = 'account.invoice'
+
+ def get_sales(self, name):
+ pool = Pool()
+ AdvancePaymentCondition = pool.get('sale.advance_payment.condition')
+
+ sales = set(super(Invoice, self).get_sales(name))
+ for line in self.lines:
+ if isinstance(line.origin, AdvancePaymentCondition):
+ sales.add(line.origin.sale.id)
+ return list(sales)
+
+
+class InvoiceLine(metaclass=PoolMeta):
+ __name__ = 'account.invoice.line'
+
+ @classmethod
+ def _account_domain(cls, type_):
+ domain = super()._account_domain(type_)
+ if type_ == 'out':
+ domain.append(('type.unearned_revenue', '=', True))
+ return domain
+
+ @classmethod
+ def _get_origin(cls):
+ return (super(InvoiceLine, cls)._get_origin()
+ + ['sale.advance_payment.condition'])
diff --git a/modules/sale_advance_payment/account.xml b/modules/sale_advance_payment/account.xml
new file mode 100644
index 0000000000..fce0b91fe3
--- /dev/null
+++ b/modules/sale_advance_payment/account.xml
@@ -0,0 +1,18 @@
+
+
+
+
+
+ account.account.type.template
+
+ account_type_form
+
+
+
+ account.account.type
+
+ account_type_form
+
+
+
diff --git a/modules/sale_advance_payment/doc/index.rst b/modules/sale_advance_payment/doc/index.rst
new file mode 100644
index 0000000000..d1ddc27646
--- /dev/null
+++ b/modules/sale_advance_payment/doc/index.rst
@@ -0,0 +1,47 @@
+Sale Advance Payment Module
+###########################
+
+The sale_advance_payment module adds support for advance payment management on
+the sale.
+
+The module adds a new document: the Advance Payment Term that defines how the
+shipment or the supply processes should be managed. Either process can be
+completely delayed until the advance payments are paid.
+
+Two new fields are added to *Sale*:
+
+- *Advance Payment Term*
+- *Advance Payment Conditions*
+
+The conditions are computed at the quotation of the sale if a payment term is
+set.
+
+When the sale is processed the advance payment invoices are created, final
+invoices will be generated when this advance payment invoices are paid. Those
+invoices will take into the account the amount previously paid by the customer.
+
+.. warning::
+ If an advance payment invoice is cancelled and not recreated when
+ processing the exception. The condition of the cancelled invoice will be
+ concidered as met.
+..
+
+Advance Payment Term
+********************
+
+It defines how advance payment invoices should be created and what they block
+until they are paid.
+
+- Name: The name of the term.
+- Lines:
+
+ - Description: The description used for the invoice line.
+ - Account: The account used for the invoice line. If it has default taxes,
+ the taxes will be applied.
+ - Block Supply: If checked, it prevents the creation of any supply request
+ before the payment of the advance payment invoice.
+ - Block Shipping: If checked, the shipments can not be packed before the
+ payment of the advance payment invoice.
+ - Invoice Delay: The delay to apply on the sale date for the date of the
+ advance payment invoice.
+ - Formula: It computes the amount of the invoice line.
diff --git a/modules/sale_advance_payment/exceptions.py b/modules/sale_advance_payment/exceptions.py
new file mode 100644
index 0000000000..1a1751f5ae
--- /dev/null
+++ b/modules/sale_advance_payment/exceptions.py
@@ -0,0 +1,12 @@
+# This file is part of Tryton. The COPYRIGHT file at the top level of
+# this repository contains the full copyright notices and license terms.
+
+from trytond.model.exceptions import ValidationError, AccessError
+
+
+class FormulaError(ValidationError):
+ pass
+
+
+class ShippingBlocked(AccessError):
+ pass
diff --git a/modules/sale_advance_payment/locale/bg.po b/modules/sale_advance_payment/locale/bg.po
new file mode 100644
index 0000000000..ce53ee15b4
--- /dev/null
+++ b/modules/sale_advance_payment/locale/bg.po
@@ -0,0 +1,192 @@
+#
+msgid ""
+msgstr "Content-Type: text/plain; charset=utf-8\n"
+
+msgctxt "field:account.account.type,unearned_revenue:"
+msgid "Unearned Revenue"
+msgstr ""
+
+msgctxt "field:account.account.type.template,unearned_revenue:"
+msgid "Unearned Revenue"
+msgstr ""
+
+msgctxt "field:sale.advance_payment.condition,account:"
+msgid "Account"
+msgstr ""
+
+msgctxt "field:sale.advance_payment.condition,amount:"
+msgid "Amount"
+msgstr ""
+
+msgctxt "field:sale.advance_payment.condition,block_shipping:"
+msgid "Block Shipping"
+msgstr ""
+
+msgctxt "field:sale.advance_payment.condition,block_supply:"
+msgid "Block Supply"
+msgstr ""
+
+msgctxt "field:sale.advance_payment.condition,completed:"
+msgid "Completed"
+msgstr ""
+
+msgctxt "field:sale.advance_payment.condition,description:"
+msgid "Description"
+msgstr ""
+
+msgctxt "field:sale.advance_payment.condition,invoice_delay:"
+msgid "Invoice Delay"
+msgstr ""
+
+msgctxt "field:sale.advance_payment.condition,invoice_lines:"
+msgid "Invoice Lines"
+msgstr ""
+
+msgctxt "field:sale.advance_payment.condition,sale:"
+msgid "Sale"
+msgstr ""
+
+msgctxt "field:sale.advance_payment.condition,sale_company:"
+msgid "Company"
+msgstr ""
+
+msgctxt "field:sale.advance_payment.condition,sale_state:"
+msgid "Sale State"
+msgstr ""
+
+msgctxt "field:sale.advance_payment_term,lines:"
+msgid "Lines"
+msgstr ""
+
+msgctxt "field:sale.advance_payment_term,name:"
+msgid "Name"
+msgstr ""
+
+msgctxt "field:sale.advance_payment_term.line,account:"
+msgid "Account"
+msgstr ""
+
+msgctxt "field:sale.advance_payment_term.line,accounts:"
+msgid "Accounts"
+msgstr ""
+
+#, fuzzy
+msgctxt "field:sale.advance_payment_term.line,advance_payment_term:"
+msgid "Advance Payment Term"
+msgstr "Advance Payment Terms"
+
+msgctxt "field:sale.advance_payment_term.line,block_shipping:"
+msgid "Block Shipping"
+msgstr ""
+
+msgctxt "field:sale.advance_payment_term.line,block_supply:"
+msgid "Block Supply"
+msgstr ""
+
+msgctxt "field:sale.advance_payment_term.line,description:"
+msgid "Description"
+msgstr ""
+
+msgctxt "field:sale.advance_payment_term.line,formula:"
+msgid "Formula"
+msgstr ""
+
+msgctxt "field:sale.advance_payment_term.line,invoice_delay:"
+msgid "Invoice Delay"
+msgstr ""
+
+msgctxt "field:sale.advance_payment_term.line.account,account:"
+msgid "Account"
+msgstr ""
+
+msgctxt "field:sale.advance_payment_term.line.account,company:"
+msgid "Company"
+msgstr ""
+
+msgctxt "field:sale.advance_payment_term.line.account,line:"
+msgid "Line"
+msgstr ""
+
+msgctxt "field:sale.sale,advance_payment_conditions:"
+msgid "Advance Payment Conditions"
+msgstr ""
+
+msgctxt "field:sale.sale,advance_payment_invoices:"
+msgid "Advance Payment Invoices"
+msgstr ""
+
+#, fuzzy
+msgctxt "field:sale.sale,advance_payment_term:"
+msgid "Advance Payment Term"
+msgstr "Advance Payment Terms"
+
+msgctxt "help:sale.advance_payment_term.line,account:"
+msgid "Used for the line of advance payment invoice."
+msgstr ""
+
+msgctxt "help:sale.advance_payment_term.line,block_shipping:"
+msgid "Check to prevent the packing of the shipment before advance payment."
+msgstr ""
+
+msgctxt "help:sale.advance_payment_term.line,block_supply:"
+msgid "Check to prevent any supply request before advance payment."
+msgstr ""
+
+msgctxt "help:sale.advance_payment_term.line,description:"
+msgid "Used as description for the invoice line."
+msgstr ""
+
+msgctxt "help:sale.advance_payment_term.line,formula:"
+msgid ""
+"A python expression used to compute the advance payment amount that will be evaluated with:\n"
+"- total_amount: The total amount of the sale.\n"
+"- untaxed_amount: The total untaxed amount of the sale."
+msgstr ""
+
+msgctxt "help:sale.advance_payment_term.line,invoice_delay:"
+msgid ""
+"Delta to apply on the sale date for the date of the advance payment invoice."
+msgstr ""
+
+msgctxt "model:ir.action,name:act_advance_invoice_form"
+msgid "Advance Invoices"
+msgstr "Advance Invoices"
+
+msgctxt "model:ir.action,name:act_advance_payment_term_form"
+msgid "Advance Payment Terms"
+msgstr "Advance Payment Terms"
+
+msgctxt "model:ir.message,text:msg_shipping_blocked"
+msgid ""
+"To pack shipments the customer must paid the advance payment for sale "
+"\"%(sale)s\"."
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_term_line_invalid_formula"
+msgid ""
+"Invalid formula \"%(formula)s\" in term line \"%(term_line)s\" with "
+"exception \"%(exception)s\"."
+msgstr ""
+
+msgctxt "model:ir.ui.menu,name:menu_advance_payment_term"
+msgid "Advance Payment Terms"
+msgstr "Advance Payment Terms"
+
+msgctxt "model:sale.advance_payment.condition,name:"
+msgid "Advance Payment Condition"
+msgstr ""
+
+#, fuzzy
+msgctxt "model:sale.advance_payment_term,name:"
+msgid "Advance Payment Term"
+msgstr "Advance Payment Terms"
+
+#, fuzzy
+msgctxt "model:sale.advance_payment_term.line,name:"
+msgid "Advance Payment Term Line"
+msgstr "Advance Payment Terms"
+
+#, fuzzy
+msgctxt "model:sale.advance_payment_term.line.account,name:"
+msgid "Advance Payment Term Line Account"
+msgstr "Advance Payment Terms"
diff --git a/modules/sale_advance_payment/locale/ca.po b/modules/sale_advance_payment/locale/ca.po
new file mode 100644
index 0000000000..61875d26a2
--- /dev/null
+++ b/modules/sale_advance_payment/locale/ca.po
@@ -0,0 +1,200 @@
+#
+msgid ""
+msgstr "Content-Type: text/plain; charset=utf-8\n"
+
+msgctxt "field:account.account.type,unearned_revenue:"
+msgid "Unearned Revenue"
+msgstr "Ingressos no meritats"
+
+msgctxt "field:account.account.type.template,unearned_revenue:"
+msgid "Unearned Revenue"
+msgstr "Ingressos no meritats"
+
+msgctxt "field:sale.advance_payment.condition,account:"
+msgid "Account"
+msgstr "Compte"
+
+msgctxt "field:sale.advance_payment.condition,amount:"
+msgid "Amount"
+msgstr "Import"
+
+msgctxt "field:sale.advance_payment.condition,block_shipping:"
+msgid "Block Shipping"
+msgstr "Bloqueja enviament"
+
+msgctxt "field:sale.advance_payment.condition,block_supply:"
+msgid "Block Supply"
+msgstr "Bloqueja aprovisionament"
+
+msgctxt "field:sale.advance_payment.condition,completed:"
+msgid "Completed"
+msgstr "Completat"
+
+msgctxt "field:sale.advance_payment.condition,description:"
+msgid "Description"
+msgstr "Descripció"
+
+msgctxt "field:sale.advance_payment.condition,invoice_delay:"
+msgid "Invoice Delay"
+msgstr "Retard factura"
+
+msgctxt "field:sale.advance_payment.condition,invoice_lines:"
+msgid "Invoice Lines"
+msgstr "Línies de factura"
+
+msgctxt "field:sale.advance_payment.condition,sale:"
+msgid "Sale"
+msgstr "Venda"
+
+msgctxt "field:sale.advance_payment.condition,sale_company:"
+msgid "Company"
+msgstr "Empresa"
+
+msgctxt "field:sale.advance_payment.condition,sale_state:"
+msgid "Sale State"
+msgstr "Estat de la venda"
+
+msgctxt "field:sale.advance_payment_term,lines:"
+msgid "Lines"
+msgstr "Línies"
+
+msgctxt "field:sale.advance_payment_term,name:"
+msgid "Name"
+msgstr "Nom"
+
+msgctxt "field:sale.advance_payment_term.line,account:"
+msgid "Account"
+msgstr "Compte"
+
+msgctxt "field:sale.advance_payment_term.line,accounts:"
+msgid "Accounts"
+msgstr "Comptes"
+
+msgctxt "field:sale.advance_payment_term.line,advance_payment_term:"
+msgid "Advance Payment Term"
+msgstr "Termini de pagament per avançat"
+
+msgctxt "field:sale.advance_payment_term.line,block_shipping:"
+msgid "Block Shipping"
+msgstr "Bloqueja l'enviament"
+
+msgctxt "field:sale.advance_payment_term.line,block_supply:"
+msgid "Block Supply"
+msgstr "Bloqueja aprovisionament"
+
+msgctxt "field:sale.advance_payment_term.line,description:"
+msgid "Description"
+msgstr "Descripció"
+
+msgctxt "field:sale.advance_payment_term.line,formula:"
+msgid "Formula"
+msgstr "Fórmula"
+
+msgctxt "field:sale.advance_payment_term.line,invoice_delay:"
+msgid "Invoice Delay"
+msgstr "Retard de factura"
+
+msgctxt "field:sale.advance_payment_term.line.account,account:"
+msgid "Account"
+msgstr "Compte"
+
+msgctxt "field:sale.advance_payment_term.line.account,company:"
+msgid "Company"
+msgstr "Empresa"
+
+msgctxt "field:sale.advance_payment_term.line.account,line:"
+msgid "Line"
+msgstr "Línia"
+
+msgctxt "field:sale.sale,advance_payment_conditions:"
+msgid "Advance Payment Conditions"
+msgstr "Condicions de pagament per avançat"
+
+msgctxt "field:sale.sale,advance_payment_invoices:"
+msgid "Advance Payment Invoices"
+msgstr "Factures de pagament per avançat"
+
+msgctxt "field:sale.sale,advance_payment_term:"
+msgid "Advance Payment Term"
+msgstr "Termini de pagament per avançat"
+
+msgctxt "help:sale.advance_payment_term.line,account:"
+msgid "Used for the line of advance payment invoice."
+msgstr "Utilitzat en la línia de la factura de pagament per avançat."
+
+msgctxt "help:sale.advance_payment_term.line,block_shipping:"
+msgid "Check to prevent the packing of the shipment before advance payment."
+msgstr ""
+"Marqueu per evitar que s'empaquetin els albarans abans del pagament per "
+"avançat."
+
+msgctxt "help:sale.advance_payment_term.line,block_supply:"
+msgid "Check to prevent any supply request before advance payment."
+msgstr ""
+"Marqueu per evitar l'aprovisionament d'existències abans del pagament per "
+"avançat."
+
+msgctxt "help:sale.advance_payment_term.line,description:"
+msgid "Used as description for the invoice line."
+msgstr "Utilitzat com a descripció per la línia de factura."
+
+msgctxt "help:sale.advance_payment_term.line,formula:"
+msgid ""
+"A python expression used to compute the advance payment amount that will be evaluated with:\n"
+"- total_amount: The total amount of the sale.\n"
+"- untaxed_amount: The total untaxed amount of the sale."
+msgstr ""
+"Una expressió de python utilizada per calcular l'import de pagament per avançat que s'avaluarà amb: \n"
+"- total_amount: L'import total de la venta.\n"
+"- untaxed_amount: L'import sense impostos de la venda."
+
+msgctxt "help:sale.advance_payment_term.line,invoice_delay:"
+msgid ""
+"Delta to apply on the sale date for the date of the advance payment invoice."
+msgstr ""
+"Retard a aplicar a la data de la venda per obtenir la data de la factura per"
+" avançat."
+
+msgctxt "model:ir.action,name:act_advance_invoice_form"
+msgid "Advance Invoices"
+msgstr "Factures per avançat"
+
+msgctxt "model:ir.action,name:act_advance_payment_term_form"
+msgid "Advance Payment Terms"
+msgstr "Terminis de pagament per avançat"
+
+msgctxt "model:ir.message,text:msg_shipping_blocked"
+msgid ""
+"To pack shipments the customer must paid the advance payment for sale "
+"\"%(sale)s\"."
+msgstr ""
+"Per empaquetar els albarans de client s'ha de pagar per avançant la venda "
+"\"%(sale)s\"."
+
+msgctxt "model:ir.message,text:msg_term_line_invalid_formula"
+msgid ""
+"Invalid formula \"%(formula)s\" in term line \"%(term_line)s\" with "
+"exception \"%(exception)s\"."
+msgstr ""
+"Fórmula \"%(formula)s\" invalida a la línia de termini de pagament "
+"\"%(term_line)s\" amb l'excepció \"%(exception)s\"."
+
+msgctxt "model:ir.ui.menu,name:menu_advance_payment_term"
+msgid "Advance Payment Terms"
+msgstr "Terminis de pagament per avançat"
+
+msgctxt "model:sale.advance_payment.condition,name:"
+msgid "Advance Payment Condition"
+msgstr "Condicions de pagament per avançat"
+
+msgctxt "model:sale.advance_payment_term,name:"
+msgid "Advance Payment Term"
+msgstr "Forma de pagament per avançat"
+
+msgctxt "model:sale.advance_payment_term.line,name:"
+msgid "Advance Payment Term Line"
+msgstr "Línia de forma de pagament per avançat"
+
+msgctxt "model:sale.advance_payment_term.line.account,name:"
+msgid "Advance Payment Term Line Account"
+msgstr "Comptes de la línia de pagament per avançat"
diff --git a/modules/sale_advance_payment/locale/cs.po b/modules/sale_advance_payment/locale/cs.po
new file mode 100644
index 0000000000..ce53ee15b4
--- /dev/null
+++ b/modules/sale_advance_payment/locale/cs.po
@@ -0,0 +1,192 @@
+#
+msgid ""
+msgstr "Content-Type: text/plain; charset=utf-8\n"
+
+msgctxt "field:account.account.type,unearned_revenue:"
+msgid "Unearned Revenue"
+msgstr ""
+
+msgctxt "field:account.account.type.template,unearned_revenue:"
+msgid "Unearned Revenue"
+msgstr ""
+
+msgctxt "field:sale.advance_payment.condition,account:"
+msgid "Account"
+msgstr ""
+
+msgctxt "field:sale.advance_payment.condition,amount:"
+msgid "Amount"
+msgstr ""
+
+msgctxt "field:sale.advance_payment.condition,block_shipping:"
+msgid "Block Shipping"
+msgstr ""
+
+msgctxt "field:sale.advance_payment.condition,block_supply:"
+msgid "Block Supply"
+msgstr ""
+
+msgctxt "field:sale.advance_payment.condition,completed:"
+msgid "Completed"
+msgstr ""
+
+msgctxt "field:sale.advance_payment.condition,description:"
+msgid "Description"
+msgstr ""
+
+msgctxt "field:sale.advance_payment.condition,invoice_delay:"
+msgid "Invoice Delay"
+msgstr ""
+
+msgctxt "field:sale.advance_payment.condition,invoice_lines:"
+msgid "Invoice Lines"
+msgstr ""
+
+msgctxt "field:sale.advance_payment.condition,sale:"
+msgid "Sale"
+msgstr ""
+
+msgctxt "field:sale.advance_payment.condition,sale_company:"
+msgid "Company"
+msgstr ""
+
+msgctxt "field:sale.advance_payment.condition,sale_state:"
+msgid "Sale State"
+msgstr ""
+
+msgctxt "field:sale.advance_payment_term,lines:"
+msgid "Lines"
+msgstr ""
+
+msgctxt "field:sale.advance_payment_term,name:"
+msgid "Name"
+msgstr ""
+
+msgctxt "field:sale.advance_payment_term.line,account:"
+msgid "Account"
+msgstr ""
+
+msgctxt "field:sale.advance_payment_term.line,accounts:"
+msgid "Accounts"
+msgstr ""
+
+#, fuzzy
+msgctxt "field:sale.advance_payment_term.line,advance_payment_term:"
+msgid "Advance Payment Term"
+msgstr "Advance Payment Terms"
+
+msgctxt "field:sale.advance_payment_term.line,block_shipping:"
+msgid "Block Shipping"
+msgstr ""
+
+msgctxt "field:sale.advance_payment_term.line,block_supply:"
+msgid "Block Supply"
+msgstr ""
+
+msgctxt "field:sale.advance_payment_term.line,description:"
+msgid "Description"
+msgstr ""
+
+msgctxt "field:sale.advance_payment_term.line,formula:"
+msgid "Formula"
+msgstr ""
+
+msgctxt "field:sale.advance_payment_term.line,invoice_delay:"
+msgid "Invoice Delay"
+msgstr ""
+
+msgctxt "field:sale.advance_payment_term.line.account,account:"
+msgid "Account"
+msgstr ""
+
+msgctxt "field:sale.advance_payment_term.line.account,company:"
+msgid "Company"
+msgstr ""
+
+msgctxt "field:sale.advance_payment_term.line.account,line:"
+msgid "Line"
+msgstr ""
+
+msgctxt "field:sale.sale,advance_payment_conditions:"
+msgid "Advance Payment Conditions"
+msgstr ""
+
+msgctxt "field:sale.sale,advance_payment_invoices:"
+msgid "Advance Payment Invoices"
+msgstr ""
+
+#, fuzzy
+msgctxt "field:sale.sale,advance_payment_term:"
+msgid "Advance Payment Term"
+msgstr "Advance Payment Terms"
+
+msgctxt "help:sale.advance_payment_term.line,account:"
+msgid "Used for the line of advance payment invoice."
+msgstr ""
+
+msgctxt "help:sale.advance_payment_term.line,block_shipping:"
+msgid "Check to prevent the packing of the shipment before advance payment."
+msgstr ""
+
+msgctxt "help:sale.advance_payment_term.line,block_supply:"
+msgid "Check to prevent any supply request before advance payment."
+msgstr ""
+
+msgctxt "help:sale.advance_payment_term.line,description:"
+msgid "Used as description for the invoice line."
+msgstr ""
+
+msgctxt "help:sale.advance_payment_term.line,formula:"
+msgid ""
+"A python expression used to compute the advance payment amount that will be evaluated with:\n"
+"- total_amount: The total amount of the sale.\n"
+"- untaxed_amount: The total untaxed amount of the sale."
+msgstr ""
+
+msgctxt "help:sale.advance_payment_term.line,invoice_delay:"
+msgid ""
+"Delta to apply on the sale date for the date of the advance payment invoice."
+msgstr ""
+
+msgctxt "model:ir.action,name:act_advance_invoice_form"
+msgid "Advance Invoices"
+msgstr "Advance Invoices"
+
+msgctxt "model:ir.action,name:act_advance_payment_term_form"
+msgid "Advance Payment Terms"
+msgstr "Advance Payment Terms"
+
+msgctxt "model:ir.message,text:msg_shipping_blocked"
+msgid ""
+"To pack shipments the customer must paid the advance payment for sale "
+"\"%(sale)s\"."
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_term_line_invalid_formula"
+msgid ""
+"Invalid formula \"%(formula)s\" in term line \"%(term_line)s\" with "
+"exception \"%(exception)s\"."
+msgstr ""
+
+msgctxt "model:ir.ui.menu,name:menu_advance_payment_term"
+msgid "Advance Payment Terms"
+msgstr "Advance Payment Terms"
+
+msgctxt "model:sale.advance_payment.condition,name:"
+msgid "Advance Payment Condition"
+msgstr ""
+
+#, fuzzy
+msgctxt "model:sale.advance_payment_term,name:"
+msgid "Advance Payment Term"
+msgstr "Advance Payment Terms"
+
+#, fuzzy
+msgctxt "model:sale.advance_payment_term.line,name:"
+msgid "Advance Payment Term Line"
+msgstr "Advance Payment Terms"
+
+#, fuzzy
+msgctxt "model:sale.advance_payment_term.line.account,name:"
+msgid "Advance Payment Term Line Account"
+msgstr "Advance Payment Terms"
diff --git a/modules/sale_advance_payment/locale/de.po b/modules/sale_advance_payment/locale/de.po
new file mode 100644
index 0000000000..95c32b3091
--- /dev/null
+++ b/modules/sale_advance_payment/locale/de.po
@@ -0,0 +1,197 @@
+#
+msgid ""
+msgstr "Content-Type: text/plain; charset=utf-8\n"
+
+msgctxt "field:account.account.type,unearned_revenue:"
+msgid "Unearned Revenue"
+msgstr "Erhaltene Anzahlungen"
+
+msgctxt "field:account.account.type.template,unearned_revenue:"
+msgid "Unearned Revenue"
+msgstr "Erhaltene Anzahlungen"
+
+msgctxt "field:sale.advance_payment.condition,account:"
+msgid "Account"
+msgstr "Konto"
+
+msgctxt "field:sale.advance_payment.condition,amount:"
+msgid "Amount"
+msgstr "Betrag"
+
+msgctxt "field:sale.advance_payment.condition,block_shipping:"
+msgid "Block Shipping"
+msgstr "Versand sperren"
+
+msgctxt "field:sale.advance_payment.condition,block_supply:"
+msgid "Block Supply"
+msgstr "Beschaffung sperren"
+
+msgctxt "field:sale.advance_payment.condition,completed:"
+msgid "Completed"
+msgstr "Abgeschlossen"
+
+msgctxt "field:sale.advance_payment.condition,description:"
+msgid "Description"
+msgstr "Beschreibung"
+
+msgctxt "field:sale.advance_payment.condition,invoice_delay:"
+msgid "Invoice Delay"
+msgstr "Rechnungsfrist"
+
+msgctxt "field:sale.advance_payment.condition,invoice_lines:"
+msgid "Invoice Lines"
+msgstr "Rechnungspositionen"
+
+msgctxt "field:sale.advance_payment.condition,sale:"
+msgid "Sale"
+msgstr "Verkauf"
+
+msgctxt "field:sale.advance_payment.condition,sale_company:"
+msgid "Company"
+msgstr "Unternehmen"
+
+msgctxt "field:sale.advance_payment.condition,sale_state:"
+msgid "Sale State"
+msgstr "Verkaufsstatus"
+
+msgctxt "field:sale.advance_payment_term,lines:"
+msgid "Lines"
+msgstr "Positionen"
+
+msgctxt "field:sale.advance_payment_term,name:"
+msgid "Name"
+msgstr "Name"
+
+msgctxt "field:sale.advance_payment_term.line,account:"
+msgid "Account"
+msgstr "Konto"
+
+msgctxt "field:sale.advance_payment_term.line,accounts:"
+msgid "Accounts"
+msgstr "Konten"
+
+msgctxt "field:sale.advance_payment_term.line,advance_payment_term:"
+msgid "Advance Payment Term"
+msgstr "Zahlungsbedingung Anzahlung"
+
+msgctxt "field:sale.advance_payment_term.line,block_shipping:"
+msgid "Block Shipping"
+msgstr "Versand sperren"
+
+msgctxt "field:sale.advance_payment_term.line,block_supply:"
+msgid "Block Supply"
+msgstr "Beschaffung sperren"
+
+msgctxt "field:sale.advance_payment_term.line,description:"
+msgid "Description"
+msgstr "Beschreibung"
+
+msgctxt "field:sale.advance_payment_term.line,formula:"
+msgid "Formula"
+msgstr "Formel"
+
+msgctxt "field:sale.advance_payment_term.line,invoice_delay:"
+msgid "Invoice Delay"
+msgstr "Rechnungsfrist"
+
+msgctxt "field:sale.advance_payment_term.line.account,account:"
+msgid "Account"
+msgstr "Konto"
+
+msgctxt "field:sale.advance_payment_term.line.account,company:"
+msgid "Company"
+msgstr "Unternehmen"
+
+msgctxt "field:sale.advance_payment_term.line.account,line:"
+msgid "Line"
+msgstr "Position"
+
+msgctxt "field:sale.sale,advance_payment_conditions:"
+msgid "Advance Payment Conditions"
+msgstr "Anzahlungskonditionen"
+
+msgctxt "field:sale.sale,advance_payment_invoices:"
+msgid "Advance Payment Invoices"
+msgstr "Anzahlungsrechnungen"
+
+msgctxt "field:sale.sale,advance_payment_term:"
+msgid "Advance Payment Term"
+msgstr "Zahlungsbedingung der Anzahlung"
+
+msgctxt "help:sale.advance_payment_term.line,account:"
+msgid "Used for the line of advance payment invoice."
+msgstr "Wird für die Position der Anzahlungsrechnung verwendet."
+
+msgctxt "help:sale.advance_payment_term.line,block_shipping:"
+msgid "Check to prevent the packing of the shipment before advance payment."
+msgstr ""
+"Aktivieren, um das Packen der Lieferung vor einer Anzahlung zu verhindern."
+
+msgctxt "help:sale.advance_payment_term.line,block_supply:"
+msgid "Check to prevent any supply request before advance payment."
+msgstr "Aktivieren, um Bestellungen vor Eingang der Anzahlung zu verhindern."
+
+msgctxt "help:sale.advance_payment_term.line,description:"
+msgid "Used as description for the invoice line."
+msgstr "Wird für die Bezeichnung der Rechnungsposition verwendet."
+
+msgctxt "help:sale.advance_payment_term.line,formula:"
+msgid ""
+"A python expression used to compute the advance payment amount that will be evaluated with:\n"
+"- total_amount: The total amount of the sale.\n"
+"- untaxed_amount: The total untaxed amount of the sale."
+msgstr ""
+"Ein Python-Ausdruck um den Anzahlungsbetrag zu berechnen, der ausgewertet wird mit:\n"
+"- total_amount: Den Gesamtbetrag des Verkaufs.\n"
+"- untaxed_amount: Den Gesamtnettobetrag des Verkaufs."
+
+msgctxt "help:sale.advance_payment_term.line,invoice_delay:"
+msgid ""
+"Delta to apply on the sale date for the date of the advance payment invoice."
+msgstr ""
+"Zeitspanne für das Verkaufsdatum zum Bestimmen des Datums der "
+"Anzahlungsrechnung."
+
+msgctxt "model:ir.action,name:act_advance_invoice_form"
+msgid "Advance Invoices"
+msgstr "Anzahlungsrechnungen"
+
+msgctxt "model:ir.action,name:act_advance_payment_term_form"
+msgid "Advance Payment Terms"
+msgstr "Zahlungsbedingungen Anzahlung"
+
+msgctxt "model:ir.message,text:msg_shipping_blocked"
+msgid ""
+"To pack shipments the customer must paid the advance payment for sale "
+"\"%(sale)s\"."
+msgstr ""
+"Damit die Lieferposten gepackt werden können, muss der Kunde die Anzahlung "
+"für Verkauf \"%(sale)s\" geleistet haben."
+
+msgctxt "model:ir.message,text:msg_term_line_invalid_formula"
+msgid ""
+"Invalid formula \"%(formula)s\" in term line \"%(term_line)s\" with "
+"exception \"%(exception)s\"."
+msgstr ""
+"Ungültige Formel \"%(formula)s\" in Anzahlungsbedingungsposition "
+"\"%(term_line)s\" mit Fehlermeldung \"%(exception)s\"."
+
+msgctxt "model:ir.ui.menu,name:menu_advance_payment_term"
+msgid "Advance Payment Terms"
+msgstr "Zahlungsbedingungen Anzahlung"
+
+msgctxt "model:sale.advance_payment.condition,name:"
+msgid "Advance Payment Condition"
+msgstr "Anzahlungskondition"
+
+msgctxt "model:sale.advance_payment_term,name:"
+msgid "Advance Payment Term"
+msgstr "Zahlungsbedingung Anzahlung"
+
+msgctxt "model:sale.advance_payment_term.line,name:"
+msgid "Advance Payment Term Line"
+msgstr "Position Zahlungsbedingung Anzahlung"
+
+msgctxt "model:sale.advance_payment_term.line.account,name:"
+msgid "Advance Payment Term Line Account"
+msgstr "Konto Position Zahlungsbedingung Anzahlung"
diff --git a/modules/sale_advance_payment/locale/es.po b/modules/sale_advance_payment/locale/es.po
new file mode 100644
index 0000000000..46fca80118
--- /dev/null
+++ b/modules/sale_advance_payment/locale/es.po
@@ -0,0 +1,199 @@
+#
+msgid ""
+msgstr "Content-Type: text/plain; charset=utf-8\n"
+
+msgctxt "field:account.account.type,unearned_revenue:"
+msgid "Unearned Revenue"
+msgstr "Ingresos no meritados"
+
+msgctxt "field:account.account.type.template,unearned_revenue:"
+msgid "Unearned Revenue"
+msgstr "Ingresos no meritados"
+
+msgctxt "field:sale.advance_payment.condition,account:"
+msgid "Account"
+msgstr "Cuenta"
+
+msgctxt "field:sale.advance_payment.condition,amount:"
+msgid "Amount"
+msgstr "Cantidad"
+
+msgctxt "field:sale.advance_payment.condition,block_shipping:"
+msgid "Block Shipping"
+msgstr "Bloquear envió"
+
+msgctxt "field:sale.advance_payment.condition,block_supply:"
+msgid "Block Supply"
+msgstr "Bloquear suministro"
+
+msgctxt "field:sale.advance_payment.condition,completed:"
+msgid "Completed"
+msgstr "Completado"
+
+msgctxt "field:sale.advance_payment.condition,description:"
+msgid "Description"
+msgstr "Descripción"
+
+msgctxt "field:sale.advance_payment.condition,invoice_delay:"
+msgid "Invoice Delay"
+msgstr "Retraso de factura"
+
+msgctxt "field:sale.advance_payment.condition,invoice_lines:"
+msgid "Invoice Lines"
+msgstr "Líneas de factura"
+
+msgctxt "field:sale.advance_payment.condition,sale:"
+msgid "Sale"
+msgstr "Venta"
+
+msgctxt "field:sale.advance_payment.condition,sale_company:"
+msgid "Company"
+msgstr "Empresa"
+
+msgctxt "field:sale.advance_payment.condition,sale_state:"
+msgid "Sale State"
+msgstr "Estado de la venta"
+
+msgctxt "field:sale.advance_payment_term,lines:"
+msgid "Lines"
+msgstr "Líneas"
+
+msgctxt "field:sale.advance_payment_term,name:"
+msgid "Name"
+msgstr "Nombre"
+
+msgctxt "field:sale.advance_payment_term.line,account:"
+msgid "Account"
+msgstr "Cuenta"
+
+msgctxt "field:sale.advance_payment_term.line,accounts:"
+msgid "Accounts"
+msgstr "Cuentas"
+
+msgctxt "field:sale.advance_payment_term.line,advance_payment_term:"
+msgid "Advance Payment Term"
+msgstr "Plazo de pago adelantado"
+
+msgctxt "field:sale.advance_payment_term.line,block_shipping:"
+msgid "Block Shipping"
+msgstr "Bloquear el envío"
+
+msgctxt "field:sale.advance_payment_term.line,block_supply:"
+msgid "Block Supply"
+msgstr "Bloquear suministro"
+
+msgctxt "field:sale.advance_payment_term.line,description:"
+msgid "Description"
+msgstr "Descripción"
+
+msgctxt "field:sale.advance_payment_term.line,formula:"
+msgid "Formula"
+msgstr "Fórmula"
+
+msgctxt "field:sale.advance_payment_term.line,invoice_delay:"
+msgid "Invoice Delay"
+msgstr "Retraso de factura"
+
+msgctxt "field:sale.advance_payment_term.line.account,account:"
+msgid "Account"
+msgstr "Cuenta"
+
+msgctxt "field:sale.advance_payment_term.line.account,company:"
+msgid "Company"
+msgstr "Empresa"
+
+msgctxt "field:sale.advance_payment_term.line.account,line:"
+msgid "Line"
+msgstr "Línea"
+
+msgctxt "field:sale.sale,advance_payment_conditions:"
+msgid "Advance Payment Conditions"
+msgstr "Condiciones de pago adelantado"
+
+msgctxt "field:sale.sale,advance_payment_invoices:"
+msgid "Advance Payment Invoices"
+msgstr "Facturas de pago adelantado"
+
+msgctxt "field:sale.sale,advance_payment_term:"
+msgid "Advance Payment Term"
+msgstr "Plazo de pago adelantado"
+
+msgctxt "help:sale.advance_payment_term.line,account:"
+msgid "Used for the line of advance payment invoice."
+msgstr "Utilizado en la línea de factura por avanzado."
+
+msgctxt "help:sale.advance_payment_term.line,block_shipping:"
+msgid "Check to prevent the packing of the shipment before advance payment."
+msgstr ""
+"Marcar para impedir el empaquetado del albarán antes del pago adelantado."
+
+msgctxt "help:sale.advance_payment_term.line,block_supply:"
+msgid "Check to prevent any supply request before advance payment."
+msgstr ""
+"Marcar para impedir cualquier solicitud de suministro anterior al pago "
+"adelantado."
+
+msgctxt "help:sale.advance_payment_term.line,description:"
+msgid "Used as description for the invoice line."
+msgstr "Utilizado como descripción para la línea de factura."
+
+msgctxt "help:sale.advance_payment_term.line,formula:"
+msgid ""
+"A python expression used to compute the advance payment amount that will be evaluated with:\n"
+"- total_amount: The total amount of the sale.\n"
+"- untaxed_amount: The total untaxed amount of the sale."
+msgstr ""
+"Expresión python utilizada para calcular el importe de pago adelantado que será evaluada con:\n"
+"- total_amount: El importe total de la venta.\n"
+"- untaxed_amount: El impote total sin impuestos de la venta."
+
+msgctxt "help:sale.advance_payment_term.line,invoice_delay:"
+msgid ""
+"Delta to apply on the sale date for the date of the advance payment invoice."
+msgstr ""
+"Retraso a aplicar sobre la fecha de venta para obtener la fecha de la "
+"factura de pago por adelantado."
+
+msgctxt "model:ir.action,name:act_advance_invoice_form"
+msgid "Advance Invoices"
+msgstr "Facturas adelantadas"
+
+msgctxt "model:ir.action,name:act_advance_payment_term_form"
+msgid "Advance Payment Terms"
+msgstr "Plazos de pago por adelantado"
+
+msgctxt "model:ir.message,text:msg_shipping_blocked"
+msgid ""
+"To pack shipments the customer must paid the advance payment for sale "
+"\"%(sale)s\"."
+msgstr ""
+"Para empaquetar los albaranes de cliente debe pagar el pago adelantado de la"
+" venta \"%(sale)s\"."
+
+msgctxt "model:ir.message,text:msg_term_line_invalid_formula"
+msgid ""
+"Invalid formula \"%(formula)s\" in term line \"%(term_line)s\" with "
+"exception \"%(exception)s\"."
+msgstr ""
+"Fórmula \"%(formula)s\" inválida en la línea de término \"%(term_line)s\" "
+"con la siguiente excepción \"%(exception)s\"."
+
+msgctxt "model:ir.ui.menu,name:menu_advance_payment_term"
+msgid "Advance Payment Terms"
+msgstr "Plazos de pago por adelantado"
+
+msgctxt "model:sale.advance_payment.condition,name:"
+msgid "Advance Payment Condition"
+msgstr "Condición de pago adelantado"
+
+msgctxt "model:sale.advance_payment_term,name:"
+msgid "Advance Payment Term"
+msgstr "Plazo de pago adelantado"
+
+msgctxt "model:sale.advance_payment_term.line,name:"
+msgid "Advance Payment Term Line"
+msgstr "Línea de plazo de pago adelantado"
+
+msgctxt "model:sale.advance_payment_term.line.account,name:"
+msgid "Advance Payment Term Line Account"
+msgstr "Cuenta de línea de plazo de pago adelantado"
diff --git a/modules/sale_advance_payment/locale/es_419.po b/modules/sale_advance_payment/locale/es_419.po
new file mode 100644
index 0000000000..5842890248
--- /dev/null
+++ b/modules/sale_advance_payment/locale/es_419.po
@@ -0,0 +1,187 @@
+#
+msgid ""
+msgstr "Content-Type: text/plain; charset=utf-8\n"
+
+msgctxt "field:account.account.type,unearned_revenue:"
+msgid "Unearned Revenue"
+msgstr ""
+
+msgctxt "field:account.account.type.template,unearned_revenue:"
+msgid "Unearned Revenue"
+msgstr ""
+
+msgctxt "field:sale.advance_payment.condition,account:"
+msgid "Account"
+msgstr ""
+
+msgctxt "field:sale.advance_payment.condition,amount:"
+msgid "Amount"
+msgstr ""
+
+msgctxt "field:sale.advance_payment.condition,block_shipping:"
+msgid "Block Shipping"
+msgstr ""
+
+msgctxt "field:sale.advance_payment.condition,block_supply:"
+msgid "Block Supply"
+msgstr ""
+
+msgctxt "field:sale.advance_payment.condition,completed:"
+msgid "Completed"
+msgstr ""
+
+msgctxt "field:sale.advance_payment.condition,description:"
+msgid "Description"
+msgstr ""
+
+msgctxt "field:sale.advance_payment.condition,invoice_delay:"
+msgid "Invoice Delay"
+msgstr ""
+
+msgctxt "field:sale.advance_payment.condition,invoice_lines:"
+msgid "Invoice Lines"
+msgstr ""
+
+msgctxt "field:sale.advance_payment.condition,sale:"
+msgid "Sale"
+msgstr ""
+
+msgctxt "field:sale.advance_payment.condition,sale_company:"
+msgid "Company"
+msgstr ""
+
+msgctxt "field:sale.advance_payment.condition,sale_state:"
+msgid "Sale State"
+msgstr ""
+
+msgctxt "field:sale.advance_payment_term,lines:"
+msgid "Lines"
+msgstr ""
+
+msgctxt "field:sale.advance_payment_term,name:"
+msgid "Name"
+msgstr ""
+
+msgctxt "field:sale.advance_payment_term.line,account:"
+msgid "Account"
+msgstr ""
+
+msgctxt "field:sale.advance_payment_term.line,accounts:"
+msgid "Accounts"
+msgstr ""
+
+msgctxt "field:sale.advance_payment_term.line,advance_payment_term:"
+msgid "Advance Payment Term"
+msgstr ""
+
+msgctxt "field:sale.advance_payment_term.line,block_shipping:"
+msgid "Block Shipping"
+msgstr ""
+
+msgctxt "field:sale.advance_payment_term.line,block_supply:"
+msgid "Block Supply"
+msgstr ""
+
+msgctxt "field:sale.advance_payment_term.line,description:"
+msgid "Description"
+msgstr ""
+
+msgctxt "field:sale.advance_payment_term.line,formula:"
+msgid "Formula"
+msgstr ""
+
+msgctxt "field:sale.advance_payment_term.line,invoice_delay:"
+msgid "Invoice Delay"
+msgstr ""
+
+msgctxt "field:sale.advance_payment_term.line.account,account:"
+msgid "Account"
+msgstr ""
+
+msgctxt "field:sale.advance_payment_term.line.account,company:"
+msgid "Company"
+msgstr ""
+
+msgctxt "field:sale.advance_payment_term.line.account,line:"
+msgid "Line"
+msgstr ""
+
+msgctxt "field:sale.sale,advance_payment_conditions:"
+msgid "Advance Payment Conditions"
+msgstr ""
+
+msgctxt "field:sale.sale,advance_payment_invoices:"
+msgid "Advance Payment Invoices"
+msgstr ""
+
+msgctxt "field:sale.sale,advance_payment_term:"
+msgid "Advance Payment Term"
+msgstr ""
+
+msgctxt "help:sale.advance_payment_term.line,account:"
+msgid "Used for the line of advance payment invoice."
+msgstr ""
+
+msgctxt "help:sale.advance_payment_term.line,block_shipping:"
+msgid "Check to prevent the packing of the shipment before advance payment."
+msgstr ""
+
+msgctxt "help:sale.advance_payment_term.line,block_supply:"
+msgid "Check to prevent any supply request before advance payment."
+msgstr ""
+
+msgctxt "help:sale.advance_payment_term.line,description:"
+msgid "Used as description for the invoice line."
+msgstr ""
+
+msgctxt "help:sale.advance_payment_term.line,formula:"
+msgid ""
+"A python expression used to compute the advance payment amount that will be evaluated with:\n"
+"- total_amount: The total amount of the sale.\n"
+"- untaxed_amount: The total untaxed amount of the sale."
+msgstr ""
+
+msgctxt "help:sale.advance_payment_term.line,invoice_delay:"
+msgid ""
+"Delta to apply on the sale date for the date of the advance payment invoice."
+msgstr ""
+
+msgctxt "model:ir.action,name:act_advance_invoice_form"
+msgid "Advance Invoices"
+msgstr ""
+
+msgctxt "model:ir.action,name:act_advance_payment_term_form"
+msgid "Advance Payment Terms"
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_shipping_blocked"
+msgid ""
+"To pack shipments the customer must paid the advance payment for sale "
+"\"%(sale)s\"."
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_term_line_invalid_formula"
+msgid ""
+"Invalid formula \"%(formula)s\" in term line \"%(term_line)s\" with "
+"exception \"%(exception)s\"."
+msgstr ""
+
+msgctxt "model:ir.ui.menu,name:menu_advance_payment_term"
+msgid "Advance Payment Terms"
+msgstr ""
+
+msgctxt "model:sale.advance_payment.condition,name:"
+msgid "Advance Payment Condition"
+msgstr ""
+
+msgctxt "model:sale.advance_payment_term,name:"
+msgid "Advance Payment Term"
+msgstr ""
+
+msgctxt "model:sale.advance_payment_term.line,name:"
+msgid "Advance Payment Term Line"
+msgstr ""
+
+msgctxt "model:sale.advance_payment_term.line.account,name:"
+msgid "Advance Payment Term Line Account"
+msgstr ""
diff --git a/modules/sale_advance_payment/locale/et.po b/modules/sale_advance_payment/locale/et.po
new file mode 100644
index 0000000000..03f79f9eb5
--- /dev/null
+++ b/modules/sale_advance_payment/locale/et.po
@@ -0,0 +1,188 @@
+#
+msgid ""
+msgstr "Content-Type: text/plain; charset=utf-8\n"
+
+msgctxt "field:account.account.type,unearned_revenue:"
+msgid "Unearned Revenue"
+msgstr "Saamata jäänud tulu"
+
+msgctxt "field:account.account.type.template,unearned_revenue:"
+msgid "Unearned Revenue"
+msgstr "Saamata jäänud tulu"
+
+msgctxt "field:sale.advance_payment.condition,account:"
+msgid "Account"
+msgstr "Konto"
+
+msgctxt "field:sale.advance_payment.condition,amount:"
+msgid "Amount"
+msgstr "Summa"
+
+msgctxt "field:sale.advance_payment.condition,block_shipping:"
+msgid "Block Shipping"
+msgstr "Blokeeri lähetus"
+
+msgctxt "field:sale.advance_payment.condition,block_supply:"
+msgid "Block Supply"
+msgstr "Blokeeri tarne"
+
+msgctxt "field:sale.advance_payment.condition,completed:"
+msgid "Completed"
+msgstr "Lõpetatud"
+
+msgctxt "field:sale.advance_payment.condition,description:"
+msgid "Description"
+msgstr "Kirjeldus"
+
+msgctxt "field:sale.advance_payment.condition,invoice_delay:"
+msgid "Invoice Delay"
+msgstr "Arve viivitus"
+
+msgctxt "field:sale.advance_payment.condition,invoice_lines:"
+msgid "Invoice Lines"
+msgstr "Arve read"
+
+msgctxt "field:sale.advance_payment.condition,sale:"
+msgid "Sale"
+msgstr "Müük"
+
+msgctxt "field:sale.advance_payment.condition,sale_company:"
+msgid "Company"
+msgstr "Ettevõte"
+
+msgctxt "field:sale.advance_payment.condition,sale_state:"
+msgid "Sale State"
+msgstr "Müügi olek"
+
+msgctxt "field:sale.advance_payment_term,lines:"
+msgid "Lines"
+msgstr "Read"
+
+msgctxt "field:sale.advance_payment_term,name:"
+msgid "Name"
+msgstr "Nimi"
+
+msgctxt "field:sale.advance_payment_term.line,account:"
+msgid "Account"
+msgstr "Konto"
+
+msgctxt "field:sale.advance_payment_term.line,accounts:"
+msgid "Accounts"
+msgstr "Kontod"
+
+msgctxt "field:sale.advance_payment_term.line,advance_payment_term:"
+msgid "Advance Payment Term"
+msgstr "Ettemaksu tingimus"
+
+msgctxt "field:sale.advance_payment_term.line,block_shipping:"
+msgid "Block Shipping"
+msgstr "Blokeeri lähetus"
+
+msgctxt "field:sale.advance_payment_term.line,block_supply:"
+msgid "Block Supply"
+msgstr "Blokeeri tarne"
+
+msgctxt "field:sale.advance_payment_term.line,description:"
+msgid "Description"
+msgstr "Kirjeldus"
+
+msgctxt "field:sale.advance_payment_term.line,formula:"
+msgid "Formula"
+msgstr "Valem"
+
+msgctxt "field:sale.advance_payment_term.line,invoice_delay:"
+msgid "Invoice Delay"
+msgstr "Arve viivitus"
+
+msgctxt "field:sale.advance_payment_term.line.account,account:"
+msgid "Account"
+msgstr "Konto"
+
+msgctxt "field:sale.advance_payment_term.line.account,company:"
+msgid "Company"
+msgstr "Ettevõte"
+
+msgctxt "field:sale.advance_payment_term.line.account,line:"
+msgid "Line"
+msgstr "Rida"
+
+msgctxt "field:sale.sale,advance_payment_conditions:"
+msgid "Advance Payment Conditions"
+msgstr "Ettemaksu tingimused"
+
+msgctxt "field:sale.sale,advance_payment_invoices:"
+msgid "Advance Payment Invoices"
+msgstr "Ettemaksu arved"
+
+msgctxt "field:sale.sale,advance_payment_term:"
+msgid "Advance Payment Term"
+msgstr "Ettemaksu tingimused"
+
+msgctxt "help:sale.advance_payment_term.line,account:"
+msgid "Used for the line of advance payment invoice."
+msgstr ""
+
+msgctxt "help:sale.advance_payment_term.line,block_shipping:"
+msgid "Check to prevent the packing of the shipment before advance payment."
+msgstr ""
+
+msgctxt "help:sale.advance_payment_term.line,block_supply:"
+msgid "Check to prevent any supply request before advance payment."
+msgstr ""
+
+msgctxt "help:sale.advance_payment_term.line,description:"
+msgid "Used as description for the invoice line."
+msgstr ""
+
+msgctxt "help:sale.advance_payment_term.line,formula:"
+msgid ""
+"A python expression used to compute the advance payment amount that will be evaluated with:\n"
+"- total_amount: The total amount of the sale.\n"
+"- untaxed_amount: The total untaxed amount of the sale."
+msgstr ""
+
+msgctxt "help:sale.advance_payment_term.line,invoice_delay:"
+msgid ""
+"Delta to apply on the sale date for the date of the advance payment invoice."
+msgstr ""
+
+msgctxt "model:ir.action,name:act_advance_invoice_form"
+msgid "Advance Invoices"
+msgstr "Ettemaksu arved"
+
+msgctxt "model:ir.action,name:act_advance_payment_term_form"
+msgid "Advance Payment Terms"
+msgstr "Ettemaksu tingimused"
+
+msgctxt "model:ir.message,text:msg_shipping_blocked"
+msgid ""
+"To pack shipments the customer must paid the advance payment for sale "
+"\"%(sale)s\"."
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_term_line_invalid_formula"
+msgid ""
+"Invalid formula \"%(formula)s\" in term line \"%(term_line)s\" with "
+"exception \"%(exception)s\"."
+msgstr ""
+
+msgctxt "model:ir.ui.menu,name:menu_advance_payment_term"
+msgid "Advance Payment Terms"
+msgstr "Ettemaksu tingimused"
+
+msgctxt "model:sale.advance_payment.condition,name:"
+msgid "Advance Payment Condition"
+msgstr "Ettemaksu tingimus"
+
+msgctxt "model:sale.advance_payment_term,name:"
+msgid "Advance Payment Term"
+msgstr "Ettemaksu tingimus"
+
+#, fuzzy
+msgctxt "model:sale.advance_payment_term.line,name:"
+msgid "Advance Payment Term Line"
+msgstr "Ettemaksu tingimus"
+
+msgctxt "model:sale.advance_payment_term.line.account,name:"
+msgid "Advance Payment Term Line Account"
+msgstr ""
diff --git a/modules/sale_advance_payment/locale/fa.po b/modules/sale_advance_payment/locale/fa.po
new file mode 100644
index 0000000000..ae87dc1bc1
--- /dev/null
+++ b/modules/sale_advance_payment/locale/fa.po
@@ -0,0 +1,197 @@
+#
+msgid ""
+msgstr "Content-Type: text/plain; charset=utf-8\n"
+
+msgctxt "field:account.account.type,unearned_revenue:"
+msgid "Unearned Revenue"
+msgstr ""
+
+msgctxt "field:account.account.type.template,unearned_revenue:"
+msgid "Unearned Revenue"
+msgstr ""
+
+msgctxt "field:sale.advance_payment.condition,account:"
+msgid "Account"
+msgstr "حساب"
+
+msgctxt "field:sale.advance_payment.condition,amount:"
+msgid "Amount"
+msgstr "مقدار"
+
+msgctxt "field:sale.advance_payment.condition,block_shipping:"
+msgid "Block Shipping"
+msgstr "حمل و نقل مسدود"
+
+msgctxt "field:sale.advance_payment.condition,block_supply:"
+msgid "Block Supply"
+msgstr "عرضه مسدود"
+
+msgctxt "field:sale.advance_payment.condition,completed:"
+msgid "Completed"
+msgstr "تکمیل شده"
+
+msgctxt "field:sale.advance_payment.condition,description:"
+msgid "Description"
+msgstr "شرح"
+
+msgctxt "field:sale.advance_payment.condition,invoice_delay:"
+msgid "Invoice Delay"
+msgstr "صورتحساب تأخیر"
+
+msgctxt "field:sale.advance_payment.condition,invoice_lines:"
+msgid "Invoice Lines"
+msgstr "سطرهای صورتحساب"
+
+msgctxt "field:sale.advance_payment.condition,sale:"
+msgid "Sale"
+msgstr "فروش"
+
+msgctxt "field:sale.advance_payment.condition,sale_company:"
+msgid "Company"
+msgstr "شرکت"
+
+msgctxt "field:sale.advance_payment.condition,sale_state:"
+msgid "Sale State"
+msgstr "وضعیت فروش"
+
+msgctxt "field:sale.advance_payment_term,lines:"
+msgid "Lines"
+msgstr "سطرها"
+
+msgctxt "field:sale.advance_payment_term,name:"
+msgid "Name"
+msgstr "نام"
+
+msgctxt "field:sale.advance_payment_term.line,account:"
+msgid "Account"
+msgstr "حساب"
+
+msgctxt "field:sale.advance_payment_term.line,accounts:"
+msgid "Accounts"
+msgstr "حساب ها"
+
+msgctxt "field:sale.advance_payment_term.line,advance_payment_term:"
+msgid "Advance Payment Term"
+msgstr "نحوه پرداخت پیش پرداخت"
+
+msgctxt "field:sale.advance_payment_term.line,block_shipping:"
+msgid "Block Shipping"
+msgstr "حمل و نقل مسدود"
+
+msgctxt "field:sale.advance_payment_term.line,block_supply:"
+msgid "Block Supply"
+msgstr "عرضه مسدود"
+
+msgctxt "field:sale.advance_payment_term.line,description:"
+msgid "Description"
+msgstr "شرح"
+
+msgctxt "field:sale.advance_payment_term.line,formula:"
+msgid "Formula"
+msgstr "فرمول"
+
+msgctxt "field:sale.advance_payment_term.line,invoice_delay:"
+msgid "Invoice Delay"
+msgstr "صورتحساب تأخیر"
+
+msgctxt "field:sale.advance_payment_term.line.account,account:"
+msgid "Account"
+msgstr "حساب"
+
+msgctxt "field:sale.advance_payment_term.line.account,company:"
+msgid "Company"
+msgstr "شرکت"
+
+msgctxt "field:sale.advance_payment_term.line.account,line:"
+msgid "Line"
+msgstr "سطر"
+
+msgctxt "field:sale.sale,advance_payment_conditions:"
+msgid "Advance Payment Conditions"
+msgstr "شرایط پرداخت پیش پرداخت"
+
+msgctxt "field:sale.sale,advance_payment_invoices:"
+msgid "Advance Payment Invoices"
+msgstr "صورتحساب پرداخت پیش پرداخت"
+
+msgctxt "field:sale.sale,advance_payment_term:"
+msgid "Advance Payment Term"
+msgstr "نحوه پرداخت پیش پرداخت"
+
+msgctxt "help:sale.advance_payment_term.line,account:"
+msgid "Used for the line of advance payment invoice."
+msgstr "سطراستفاده شده برای پیش پرداخت در صورتحساب پرداخت."
+
+msgctxt "help:sale.advance_payment_term.line,block_shipping:"
+msgid "Check to prevent the packing of the shipment before advance payment."
+msgstr ""
+"جهت جلوگیری از بسته بندی حمل و نقل قبل از پرداخت پیش پرداخت، کادر را تیک "
+"بزنید."
+
+msgctxt "help:sale.advance_payment_term.line,block_supply:"
+msgid "Check to prevent any supply request before advance payment."
+msgstr ""
+"جهت جلوگیری از درخواست تأمین قبل از پرداخت پیش پرداخت، کادر را تیک بزنید."
+
+msgctxt "help:sale.advance_payment_term.line,description:"
+msgid "Used as description for the invoice line."
+msgstr "استفاده از سطر صورتحساب بعنوان شرح."
+
+msgctxt "help:sale.advance_payment_term.line,formula:"
+msgid ""
+"A python expression used to compute the advance payment amount that will be evaluated with:\n"
+"- total_amount: The total amount of the sale.\n"
+"- untaxed_amount: The total untaxed amount of the sale."
+msgstr ""
+"یک عبارت پایتون برای محاسبه مبلغ پیش پرداخت که ارزیابی می شود با:\n"
+"- مجموع _ مبلغ : کل مبلغ فروش.\n"
+"- مبلغ - بدون احتساب مالیات : کل مبلغ فروش بدون احتساب مالیات."
+
+msgctxt "help:sale.advance_payment_term.line,invoice_delay:"
+msgid ""
+"Delta to apply on the sale date for the date of the advance payment invoice."
+msgstr "برای تاریخ فاکتور پیش پرداخت. دلتا برای تاریخ فروش اعمال شود"
+
+msgctxt "model:ir.action,name:act_advance_invoice_form"
+msgid "Advance Invoices"
+msgstr "فاکتورهای پیش پرداخت"
+
+msgctxt "model:ir.action,name:act_advance_payment_term_form"
+msgid "Advance Payment Terms"
+msgstr "مدت پرداخت پیش پرداخت"
+
+msgctxt "model:ir.message,text:msg_shipping_blocked"
+msgid ""
+"To pack shipments the customer must paid the advance payment for sale "
+"\"%(sale)s\"."
+msgstr ""
+"برای بسته بندی کالاها، مشتری باید پیش پرداخت را برای فروش "
+":\"%(sale)s\"پرداخت کند."
+
+msgctxt "model:ir.message,text:msg_term_line_invalid_formula"
+msgid ""
+"Invalid formula \"%(formula)s\" in term line \"%(term_line)s\" with "
+"exception \"%(exception)s\"."
+msgstr ""
+"فرمول :\"%(formula)s\"در سطر مدت :\"%(term_line)s\"باشرایط "
+":\"%(exception)s\" نا معتبر است."
+
+msgctxt "model:ir.ui.menu,name:menu_advance_payment_term"
+msgid "Advance Payment Terms"
+msgstr "مدت پرداخت پیش پرداخت"
+
+msgctxt "model:sale.advance_payment.condition,name:"
+msgid "Advance Payment Condition"
+msgstr "شرایط پرداخت پیش پرداخت"
+
+msgctxt "model:sale.advance_payment_term,name:"
+msgid "Advance Payment Term"
+msgstr "مدت پرداخت پیش پرداخت"
+
+msgctxt "model:sale.advance_payment_term.line,name:"
+msgid "Advance Payment Term Line"
+msgstr "سطر مدت پرداخت پیش پرداخت"
+
+msgctxt "model:sale.advance_payment_term.line.account,name:"
+msgid "Advance Payment Term Line Account"
+msgstr "حساب سطر مدت پرداخت پیش پرداخت"
diff --git a/modules/sale_advance_payment/locale/fi.po b/modules/sale_advance_payment/locale/fi.po
new file mode 100644
index 0000000000..ce53ee15b4
--- /dev/null
+++ b/modules/sale_advance_payment/locale/fi.po
@@ -0,0 +1,192 @@
+#
+msgid ""
+msgstr "Content-Type: text/plain; charset=utf-8\n"
+
+msgctxt "field:account.account.type,unearned_revenue:"
+msgid "Unearned Revenue"
+msgstr ""
+
+msgctxt "field:account.account.type.template,unearned_revenue:"
+msgid "Unearned Revenue"
+msgstr ""
+
+msgctxt "field:sale.advance_payment.condition,account:"
+msgid "Account"
+msgstr ""
+
+msgctxt "field:sale.advance_payment.condition,amount:"
+msgid "Amount"
+msgstr ""
+
+msgctxt "field:sale.advance_payment.condition,block_shipping:"
+msgid "Block Shipping"
+msgstr ""
+
+msgctxt "field:sale.advance_payment.condition,block_supply:"
+msgid "Block Supply"
+msgstr ""
+
+msgctxt "field:sale.advance_payment.condition,completed:"
+msgid "Completed"
+msgstr ""
+
+msgctxt "field:sale.advance_payment.condition,description:"
+msgid "Description"
+msgstr ""
+
+msgctxt "field:sale.advance_payment.condition,invoice_delay:"
+msgid "Invoice Delay"
+msgstr ""
+
+msgctxt "field:sale.advance_payment.condition,invoice_lines:"
+msgid "Invoice Lines"
+msgstr ""
+
+msgctxt "field:sale.advance_payment.condition,sale:"
+msgid "Sale"
+msgstr ""
+
+msgctxt "field:sale.advance_payment.condition,sale_company:"
+msgid "Company"
+msgstr ""
+
+msgctxt "field:sale.advance_payment.condition,sale_state:"
+msgid "Sale State"
+msgstr ""
+
+msgctxt "field:sale.advance_payment_term,lines:"
+msgid "Lines"
+msgstr ""
+
+msgctxt "field:sale.advance_payment_term,name:"
+msgid "Name"
+msgstr ""
+
+msgctxt "field:sale.advance_payment_term.line,account:"
+msgid "Account"
+msgstr ""
+
+msgctxt "field:sale.advance_payment_term.line,accounts:"
+msgid "Accounts"
+msgstr ""
+
+#, fuzzy
+msgctxt "field:sale.advance_payment_term.line,advance_payment_term:"
+msgid "Advance Payment Term"
+msgstr "Advance Payment Terms"
+
+msgctxt "field:sale.advance_payment_term.line,block_shipping:"
+msgid "Block Shipping"
+msgstr ""
+
+msgctxt "field:sale.advance_payment_term.line,block_supply:"
+msgid "Block Supply"
+msgstr ""
+
+msgctxt "field:sale.advance_payment_term.line,description:"
+msgid "Description"
+msgstr ""
+
+msgctxt "field:sale.advance_payment_term.line,formula:"
+msgid "Formula"
+msgstr ""
+
+msgctxt "field:sale.advance_payment_term.line,invoice_delay:"
+msgid "Invoice Delay"
+msgstr ""
+
+msgctxt "field:sale.advance_payment_term.line.account,account:"
+msgid "Account"
+msgstr ""
+
+msgctxt "field:sale.advance_payment_term.line.account,company:"
+msgid "Company"
+msgstr ""
+
+msgctxt "field:sale.advance_payment_term.line.account,line:"
+msgid "Line"
+msgstr ""
+
+msgctxt "field:sale.sale,advance_payment_conditions:"
+msgid "Advance Payment Conditions"
+msgstr ""
+
+msgctxt "field:sale.sale,advance_payment_invoices:"
+msgid "Advance Payment Invoices"
+msgstr ""
+
+#, fuzzy
+msgctxt "field:sale.sale,advance_payment_term:"
+msgid "Advance Payment Term"
+msgstr "Advance Payment Terms"
+
+msgctxt "help:sale.advance_payment_term.line,account:"
+msgid "Used for the line of advance payment invoice."
+msgstr ""
+
+msgctxt "help:sale.advance_payment_term.line,block_shipping:"
+msgid "Check to prevent the packing of the shipment before advance payment."
+msgstr ""
+
+msgctxt "help:sale.advance_payment_term.line,block_supply:"
+msgid "Check to prevent any supply request before advance payment."
+msgstr ""
+
+msgctxt "help:sale.advance_payment_term.line,description:"
+msgid "Used as description for the invoice line."
+msgstr ""
+
+msgctxt "help:sale.advance_payment_term.line,formula:"
+msgid ""
+"A python expression used to compute the advance payment amount that will be evaluated with:\n"
+"- total_amount: The total amount of the sale.\n"
+"- untaxed_amount: The total untaxed amount of the sale."
+msgstr ""
+
+msgctxt "help:sale.advance_payment_term.line,invoice_delay:"
+msgid ""
+"Delta to apply on the sale date for the date of the advance payment invoice."
+msgstr ""
+
+msgctxt "model:ir.action,name:act_advance_invoice_form"
+msgid "Advance Invoices"
+msgstr "Advance Invoices"
+
+msgctxt "model:ir.action,name:act_advance_payment_term_form"
+msgid "Advance Payment Terms"
+msgstr "Advance Payment Terms"
+
+msgctxt "model:ir.message,text:msg_shipping_blocked"
+msgid ""
+"To pack shipments the customer must paid the advance payment for sale "
+"\"%(sale)s\"."
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_term_line_invalid_formula"
+msgid ""
+"Invalid formula \"%(formula)s\" in term line \"%(term_line)s\" with "
+"exception \"%(exception)s\"."
+msgstr ""
+
+msgctxt "model:ir.ui.menu,name:menu_advance_payment_term"
+msgid "Advance Payment Terms"
+msgstr "Advance Payment Terms"
+
+msgctxt "model:sale.advance_payment.condition,name:"
+msgid "Advance Payment Condition"
+msgstr ""
+
+#, fuzzy
+msgctxt "model:sale.advance_payment_term,name:"
+msgid "Advance Payment Term"
+msgstr "Advance Payment Terms"
+
+#, fuzzy
+msgctxt "model:sale.advance_payment_term.line,name:"
+msgid "Advance Payment Term Line"
+msgstr "Advance Payment Terms"
+
+#, fuzzy
+msgctxt "model:sale.advance_payment_term.line.account,name:"
+msgid "Advance Payment Term Line Account"
+msgstr "Advance Payment Terms"
diff --git a/modules/sale_advance_payment/locale/fr.po b/modules/sale_advance_payment/locale/fr.po
new file mode 100644
index 0000000000..16a4f83607
--- /dev/null
+++ b/modules/sale_advance_payment/locale/fr.po
@@ -0,0 +1,200 @@
+#
+msgid ""
+msgstr "Content-Type: text/plain; charset=utf-8\n"
+
+msgctxt "field:account.account.type,unearned_revenue:"
+msgid "Unearned Revenue"
+msgstr "Revenu non gagné"
+
+msgctxt "field:account.account.type.template,unearned_revenue:"
+msgid "Unearned Revenue"
+msgstr "Revenu non gagné"
+
+msgctxt "field:sale.advance_payment.condition,account:"
+msgid "Account"
+msgstr "Compte"
+
+msgctxt "field:sale.advance_payment.condition,amount:"
+msgid "Amount"
+msgstr "Montant"
+
+msgctxt "field:sale.advance_payment.condition,block_shipping:"
+msgid "Block Shipping"
+msgstr "Bloquer l'envoi"
+
+msgctxt "field:sale.advance_payment.condition,block_supply:"
+msgid "Block Supply"
+msgstr "Bloquer l'approvisionnement"
+
+msgctxt "field:sale.advance_payment.condition,completed:"
+msgid "Completed"
+msgstr "Terminée"
+
+msgctxt "field:sale.advance_payment.condition,description:"
+msgid "Description"
+msgstr "Description"
+
+msgctxt "field:sale.advance_payment.condition,invoice_delay:"
+msgid "Invoice Delay"
+msgstr "Délai de facturation"
+
+msgctxt "field:sale.advance_payment.condition,invoice_lines:"
+msgid "Invoice Lines"
+msgstr "Lignes de facture"
+
+msgctxt "field:sale.advance_payment.condition,sale:"
+msgid "Sale"
+msgstr "Vente"
+
+msgctxt "field:sale.advance_payment.condition,sale_company:"
+msgid "Company"
+msgstr "Société"
+
+msgctxt "field:sale.advance_payment.condition,sale_state:"
+msgid "Sale State"
+msgstr "État de la vente"
+
+msgctxt "field:sale.advance_payment_term,lines:"
+msgid "Lines"
+msgstr "Lignes"
+
+msgctxt "field:sale.advance_payment_term,name:"
+msgid "Name"
+msgstr "Nom"
+
+msgctxt "field:sale.advance_payment_term.line,account:"
+msgid "Account"
+msgstr "Compte"
+
+msgctxt "field:sale.advance_payment_term.line,accounts:"
+msgid "Accounts"
+msgstr "Comptes"
+
+msgctxt "field:sale.advance_payment_term.line,advance_payment_term:"
+msgid "Advance Payment Term"
+msgstr "Conditions d'acompte"
+
+msgctxt "field:sale.advance_payment_term.line,block_shipping:"
+msgid "Block Shipping"
+msgstr "Bloquer l'envoi"
+
+msgctxt "field:sale.advance_payment_term.line,block_supply:"
+msgid "Block Supply"
+msgstr "Bloquer l'approvisionnement"
+
+msgctxt "field:sale.advance_payment_term.line,description:"
+msgid "Description"
+msgstr "Description"
+
+msgctxt "field:sale.advance_payment_term.line,formula:"
+msgid "Formula"
+msgstr "Formule"
+
+msgctxt "field:sale.advance_payment_term.line,invoice_delay:"
+msgid "Invoice Delay"
+msgstr "Délai de facturation"
+
+msgctxt "field:sale.advance_payment_term.line.account,account:"
+msgid "Account"
+msgstr "Compte"
+
+msgctxt "field:sale.advance_payment_term.line.account,company:"
+msgid "Company"
+msgstr "Société"
+
+msgctxt "field:sale.advance_payment_term.line.account,line:"
+msgid "Line"
+msgstr "Ligne"
+
+msgctxt "field:sale.sale,advance_payment_conditions:"
+msgid "Advance Payment Conditions"
+msgstr "Conditions de l'acompte"
+
+msgctxt "field:sale.sale,advance_payment_invoices:"
+msgid "Advance Payment Invoices"
+msgstr "Factures d'acompte"
+
+msgctxt "field:sale.sale,advance_payment_term:"
+msgid "Advance Payment Term"
+msgstr "Conditions d'acompte"
+
+msgctxt "help:sale.advance_payment_term.line,account:"
+msgid "Used for the line of advance payment invoice."
+msgstr "Utilisé sur la ligne de la facture d'acompte."
+
+msgctxt "help:sale.advance_payment_term.line,block_shipping:"
+msgid "Check to prevent the packing of the shipment before advance payment."
+msgstr ""
+"À cocher afin d'empêcher l'emballage de l'expédition avant le paiement de "
+"l'acompte."
+
+msgctxt "help:sale.advance_payment_term.line,block_supply:"
+msgid "Check to prevent any supply request before advance payment."
+msgstr ""
+"À cocher afin d'empêcher le réapprovisionnement avant le paiement de "
+"l'acompte."
+
+msgctxt "help:sale.advance_payment_term.line,description:"
+msgid "Used as description for the invoice line."
+msgstr "Utilisé comme description sur la ligne de la facture d'acompte."
+
+msgctxt "help:sale.advance_payment_term.line,formula:"
+msgid ""
+"A python expression used to compute the advance payment amount that will be evaluated with:\n"
+"- total_amount: The total amount of the sale.\n"
+"- untaxed_amount: The total untaxed amount of the sale."
+msgstr ""
+"Une expression python utilisée pour calculer le montant de l'acompte ; elle sera évaluée avec :\n"
+"- total_amount : Le montant total de la vente.\n"
+"- untaxed_amount : Le montat total hors-taxes de la vente."
+
+msgctxt "help:sale.advance_payment_term.line,invoice_delay:"
+msgid ""
+"Delta to apply on the sale date for the date of the advance payment invoice."
+msgstr ""
+"Le délai à appliquer à la date de vente pour déterminer la date de la "
+"facture d'acompte."
+
+msgctxt "model:ir.action,name:act_advance_invoice_form"
+msgid "Advance Invoices"
+msgstr "Factures d'acompte"
+
+msgctxt "model:ir.action,name:act_advance_payment_term_form"
+msgid "Advance Payment Terms"
+msgstr "Conditions de paiement d'acompte"
+
+msgctxt "model:ir.message,text:msg_shipping_blocked"
+msgid ""
+"To pack shipments the customer must paid the advance payment for sale "
+"\"%(sale)s\"."
+msgstr ""
+"Pour emballer les expéditions, le client doit payer l'acompte pour la vente "
+"« %(sale)s »."
+
+msgctxt "model:ir.message,text:msg_term_line_invalid_formula"
+msgid ""
+"Invalid formula \"%(formula)s\" in term line \"%(term_line)s\" with "
+"exception \"%(exception)s\"."
+msgstr ""
+"Formule invalide « %(formula)s » sur la ligne de condition de paiement "
+"« %(term_line)s » avec l'exception « %(exception)s »."
+
+msgctxt "model:ir.ui.menu,name:menu_advance_payment_term"
+msgid "Advance Payment Terms"
+msgstr "Conditions de paiement d'acompte"
+
+msgctxt "model:sale.advance_payment.condition,name:"
+msgid "Advance Payment Condition"
+msgstr "Condition d'acompte"
+
+msgctxt "model:sale.advance_payment_term,name:"
+msgid "Advance Payment Term"
+msgstr "Conditions d'acompte"
+
+msgctxt "model:sale.advance_payment_term.line,name:"
+msgid "Advance Payment Term Line"
+msgstr "Ligne des conditidons d'acompte"
+
+msgctxt "model:sale.advance_payment_term.line.account,name:"
+msgid "Advance Payment Term Line Account"
+msgstr "Compte de la ligne des conditions d'acompte"
diff --git a/modules/sale_advance_payment/locale/hu.po b/modules/sale_advance_payment/locale/hu.po
new file mode 100644
index 0000000000..ce53ee15b4
--- /dev/null
+++ b/modules/sale_advance_payment/locale/hu.po
@@ -0,0 +1,192 @@
+#
+msgid ""
+msgstr "Content-Type: text/plain; charset=utf-8\n"
+
+msgctxt "field:account.account.type,unearned_revenue:"
+msgid "Unearned Revenue"
+msgstr ""
+
+msgctxt "field:account.account.type.template,unearned_revenue:"
+msgid "Unearned Revenue"
+msgstr ""
+
+msgctxt "field:sale.advance_payment.condition,account:"
+msgid "Account"
+msgstr ""
+
+msgctxt "field:sale.advance_payment.condition,amount:"
+msgid "Amount"
+msgstr ""
+
+msgctxt "field:sale.advance_payment.condition,block_shipping:"
+msgid "Block Shipping"
+msgstr ""
+
+msgctxt "field:sale.advance_payment.condition,block_supply:"
+msgid "Block Supply"
+msgstr ""
+
+msgctxt "field:sale.advance_payment.condition,completed:"
+msgid "Completed"
+msgstr ""
+
+msgctxt "field:sale.advance_payment.condition,description:"
+msgid "Description"
+msgstr ""
+
+msgctxt "field:sale.advance_payment.condition,invoice_delay:"
+msgid "Invoice Delay"
+msgstr ""
+
+msgctxt "field:sale.advance_payment.condition,invoice_lines:"
+msgid "Invoice Lines"
+msgstr ""
+
+msgctxt "field:sale.advance_payment.condition,sale:"
+msgid "Sale"
+msgstr ""
+
+msgctxt "field:sale.advance_payment.condition,sale_company:"
+msgid "Company"
+msgstr ""
+
+msgctxt "field:sale.advance_payment.condition,sale_state:"
+msgid "Sale State"
+msgstr ""
+
+msgctxt "field:sale.advance_payment_term,lines:"
+msgid "Lines"
+msgstr ""
+
+msgctxt "field:sale.advance_payment_term,name:"
+msgid "Name"
+msgstr ""
+
+msgctxt "field:sale.advance_payment_term.line,account:"
+msgid "Account"
+msgstr ""
+
+msgctxt "field:sale.advance_payment_term.line,accounts:"
+msgid "Accounts"
+msgstr ""
+
+#, fuzzy
+msgctxt "field:sale.advance_payment_term.line,advance_payment_term:"
+msgid "Advance Payment Term"
+msgstr "Advance Payment Terms"
+
+msgctxt "field:sale.advance_payment_term.line,block_shipping:"
+msgid "Block Shipping"
+msgstr ""
+
+msgctxt "field:sale.advance_payment_term.line,block_supply:"
+msgid "Block Supply"
+msgstr ""
+
+msgctxt "field:sale.advance_payment_term.line,description:"
+msgid "Description"
+msgstr ""
+
+msgctxt "field:sale.advance_payment_term.line,formula:"
+msgid "Formula"
+msgstr ""
+
+msgctxt "field:sale.advance_payment_term.line,invoice_delay:"
+msgid "Invoice Delay"
+msgstr ""
+
+msgctxt "field:sale.advance_payment_term.line.account,account:"
+msgid "Account"
+msgstr ""
+
+msgctxt "field:sale.advance_payment_term.line.account,company:"
+msgid "Company"
+msgstr ""
+
+msgctxt "field:sale.advance_payment_term.line.account,line:"
+msgid "Line"
+msgstr ""
+
+msgctxt "field:sale.sale,advance_payment_conditions:"
+msgid "Advance Payment Conditions"
+msgstr ""
+
+msgctxt "field:sale.sale,advance_payment_invoices:"
+msgid "Advance Payment Invoices"
+msgstr ""
+
+#, fuzzy
+msgctxt "field:sale.sale,advance_payment_term:"
+msgid "Advance Payment Term"
+msgstr "Advance Payment Terms"
+
+msgctxt "help:sale.advance_payment_term.line,account:"
+msgid "Used for the line of advance payment invoice."
+msgstr ""
+
+msgctxt "help:sale.advance_payment_term.line,block_shipping:"
+msgid "Check to prevent the packing of the shipment before advance payment."
+msgstr ""
+
+msgctxt "help:sale.advance_payment_term.line,block_supply:"
+msgid "Check to prevent any supply request before advance payment."
+msgstr ""
+
+msgctxt "help:sale.advance_payment_term.line,description:"
+msgid "Used as description for the invoice line."
+msgstr ""
+
+msgctxt "help:sale.advance_payment_term.line,formula:"
+msgid ""
+"A python expression used to compute the advance payment amount that will be evaluated with:\n"
+"- total_amount: The total amount of the sale.\n"
+"- untaxed_amount: The total untaxed amount of the sale."
+msgstr ""
+
+msgctxt "help:sale.advance_payment_term.line,invoice_delay:"
+msgid ""
+"Delta to apply on the sale date for the date of the advance payment invoice."
+msgstr ""
+
+msgctxt "model:ir.action,name:act_advance_invoice_form"
+msgid "Advance Invoices"
+msgstr "Advance Invoices"
+
+msgctxt "model:ir.action,name:act_advance_payment_term_form"
+msgid "Advance Payment Terms"
+msgstr "Advance Payment Terms"
+
+msgctxt "model:ir.message,text:msg_shipping_blocked"
+msgid ""
+"To pack shipments the customer must paid the advance payment for sale "
+"\"%(sale)s\"."
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_term_line_invalid_formula"
+msgid ""
+"Invalid formula \"%(formula)s\" in term line \"%(term_line)s\" with "
+"exception \"%(exception)s\"."
+msgstr ""
+
+msgctxt "model:ir.ui.menu,name:menu_advance_payment_term"
+msgid "Advance Payment Terms"
+msgstr "Advance Payment Terms"
+
+msgctxt "model:sale.advance_payment.condition,name:"
+msgid "Advance Payment Condition"
+msgstr ""
+
+#, fuzzy
+msgctxt "model:sale.advance_payment_term,name:"
+msgid "Advance Payment Term"
+msgstr "Advance Payment Terms"
+
+#, fuzzy
+msgctxt "model:sale.advance_payment_term.line,name:"
+msgid "Advance Payment Term Line"
+msgstr "Advance Payment Terms"
+
+#, fuzzy
+msgctxt "model:sale.advance_payment_term.line.account,name:"
+msgid "Advance Payment Term Line Account"
+msgstr "Advance Payment Terms"
diff --git a/modules/sale_advance_payment/locale/id.po b/modules/sale_advance_payment/locale/id.po
new file mode 100644
index 0000000000..1d41334d20
--- /dev/null
+++ b/modules/sale_advance_payment/locale/id.po
@@ -0,0 +1,187 @@
+#
+msgid ""
+msgstr "Content-Type: text/plain; charset=utf-8\n"
+
+msgctxt "field:account.account.type,unearned_revenue:"
+msgid "Unearned Revenue"
+msgstr ""
+
+msgctxt "field:account.account.type.template,unearned_revenue:"
+msgid "Unearned Revenue"
+msgstr ""
+
+msgctxt "field:sale.advance_payment.condition,account:"
+msgid "Account"
+msgstr "Akun"
+
+msgctxt "field:sale.advance_payment.condition,amount:"
+msgid "Amount"
+msgstr "Jumlah"
+
+msgctxt "field:sale.advance_payment.condition,block_shipping:"
+msgid "Block Shipping"
+msgstr ""
+
+msgctxt "field:sale.advance_payment.condition,block_supply:"
+msgid "Block Supply"
+msgstr ""
+
+msgctxt "field:sale.advance_payment.condition,completed:"
+msgid "Completed"
+msgstr ""
+
+msgctxt "field:sale.advance_payment.condition,description:"
+msgid "Description"
+msgstr "Deskripsi"
+
+msgctxt "field:sale.advance_payment.condition,invoice_delay:"
+msgid "Invoice Delay"
+msgstr ""
+
+msgctxt "field:sale.advance_payment.condition,invoice_lines:"
+msgid "Invoice Lines"
+msgstr "Baris Faktur"
+
+msgctxt "field:sale.advance_payment.condition,sale:"
+msgid "Sale"
+msgstr "Penjualan"
+
+msgctxt "field:sale.advance_payment.condition,sale_company:"
+msgid "Company"
+msgstr "Perusahaan"
+
+msgctxt "field:sale.advance_payment.condition,sale_state:"
+msgid "Sale State"
+msgstr ""
+
+msgctxt "field:sale.advance_payment_term,lines:"
+msgid "Lines"
+msgstr "Baris"
+
+msgctxt "field:sale.advance_payment_term,name:"
+msgid "Name"
+msgstr "Nama"
+
+msgctxt "field:sale.advance_payment_term.line,account:"
+msgid "Account"
+msgstr "Akun"
+
+msgctxt "field:sale.advance_payment_term.line,accounts:"
+msgid "Accounts"
+msgstr ""
+
+msgctxt "field:sale.advance_payment_term.line,advance_payment_term:"
+msgid "Advance Payment Term"
+msgstr ""
+
+msgctxt "field:sale.advance_payment_term.line,block_shipping:"
+msgid "Block Shipping"
+msgstr ""
+
+msgctxt "field:sale.advance_payment_term.line,block_supply:"
+msgid "Block Supply"
+msgstr ""
+
+msgctxt "field:sale.advance_payment_term.line,description:"
+msgid "Description"
+msgstr "Deskripsi"
+
+msgctxt "field:sale.advance_payment_term.line,formula:"
+msgid "Formula"
+msgstr ""
+
+msgctxt "field:sale.advance_payment_term.line,invoice_delay:"
+msgid "Invoice Delay"
+msgstr ""
+
+msgctxt "field:sale.advance_payment_term.line.account,account:"
+msgid "Account"
+msgstr "Akun"
+
+msgctxt "field:sale.advance_payment_term.line.account,company:"
+msgid "Company"
+msgstr "Perusahaan"
+
+msgctxt "field:sale.advance_payment_term.line.account,line:"
+msgid "Line"
+msgstr ""
+
+msgctxt "field:sale.sale,advance_payment_conditions:"
+msgid "Advance Payment Conditions"
+msgstr ""
+
+msgctxt "field:sale.sale,advance_payment_invoices:"
+msgid "Advance Payment Invoices"
+msgstr ""
+
+msgctxt "field:sale.sale,advance_payment_term:"
+msgid "Advance Payment Term"
+msgstr ""
+
+msgctxt "help:sale.advance_payment_term.line,account:"
+msgid "Used for the line of advance payment invoice."
+msgstr ""
+
+msgctxt "help:sale.advance_payment_term.line,block_shipping:"
+msgid "Check to prevent the packing of the shipment before advance payment."
+msgstr ""
+
+msgctxt "help:sale.advance_payment_term.line,block_supply:"
+msgid "Check to prevent any supply request before advance payment."
+msgstr ""
+
+msgctxt "help:sale.advance_payment_term.line,description:"
+msgid "Used as description for the invoice line."
+msgstr ""
+
+msgctxt "help:sale.advance_payment_term.line,formula:"
+msgid ""
+"A python expression used to compute the advance payment amount that will be evaluated with:\n"
+"- total_amount: The total amount of the sale.\n"
+"- untaxed_amount: The total untaxed amount of the sale."
+msgstr ""
+
+msgctxt "help:sale.advance_payment_term.line,invoice_delay:"
+msgid ""
+"Delta to apply on the sale date for the date of the advance payment invoice."
+msgstr ""
+
+msgctxt "model:ir.action,name:act_advance_invoice_form"
+msgid "Advance Invoices"
+msgstr ""
+
+msgctxt "model:ir.action,name:act_advance_payment_term_form"
+msgid "Advance Payment Terms"
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_shipping_blocked"
+msgid ""
+"To pack shipments the customer must paid the advance payment for sale "
+"\"%(sale)s\"."
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_term_line_invalid_formula"
+msgid ""
+"Invalid formula \"%(formula)s\" in term line \"%(term_line)s\" with "
+"exception \"%(exception)s\"."
+msgstr ""
+
+msgctxt "model:ir.ui.menu,name:menu_advance_payment_term"
+msgid "Advance Payment Terms"
+msgstr ""
+
+msgctxt "model:sale.advance_payment.condition,name:"
+msgid "Advance Payment Condition"
+msgstr ""
+
+msgctxt "model:sale.advance_payment_term,name:"
+msgid "Advance Payment Term"
+msgstr ""
+
+msgctxt "model:sale.advance_payment_term.line,name:"
+msgid "Advance Payment Term Line"
+msgstr ""
+
+msgctxt "model:sale.advance_payment_term.line.account,name:"
+msgid "Advance Payment Term Line Account"
+msgstr ""
diff --git a/modules/sale_advance_payment/locale/it.po b/modules/sale_advance_payment/locale/it.po
new file mode 100644
index 0000000000..5197e1cacd
--- /dev/null
+++ b/modules/sale_advance_payment/locale/it.po
@@ -0,0 +1,192 @@
+#
+msgid ""
+msgstr "Content-Type: text/plain; charset=utf-8\n"
+
+msgctxt "field:account.account.type,unearned_revenue:"
+msgid "Unearned Revenue"
+msgstr ""
+
+msgctxt "field:account.account.type.template,unearned_revenue:"
+msgid "Unearned Revenue"
+msgstr ""
+
+msgctxt "field:sale.advance_payment.condition,account:"
+msgid "Account"
+msgstr ""
+
+msgctxt "field:sale.advance_payment.condition,amount:"
+msgid "Amount"
+msgstr ""
+
+msgctxt "field:sale.advance_payment.condition,block_shipping:"
+msgid "Block Shipping"
+msgstr ""
+
+msgctxt "field:sale.advance_payment.condition,block_supply:"
+msgid "Block Supply"
+msgstr ""
+
+msgctxt "field:sale.advance_payment.condition,completed:"
+msgid "Completed"
+msgstr ""
+
+msgctxt "field:sale.advance_payment.condition,description:"
+msgid "Description"
+msgstr ""
+
+msgctxt "field:sale.advance_payment.condition,invoice_delay:"
+msgid "Invoice Delay"
+msgstr ""
+
+msgctxt "field:sale.advance_payment.condition,invoice_lines:"
+msgid "Invoice Lines"
+msgstr ""
+
+msgctxt "field:sale.advance_payment.condition,sale:"
+msgid "Sale"
+msgstr ""
+
+msgctxt "field:sale.advance_payment.condition,sale_company:"
+msgid "Company"
+msgstr "Azienda"
+
+msgctxt "field:sale.advance_payment.condition,sale_state:"
+msgid "Sale State"
+msgstr ""
+
+msgctxt "field:sale.advance_payment_term,lines:"
+msgid "Lines"
+msgstr ""
+
+msgctxt "field:sale.advance_payment_term,name:"
+msgid "Name"
+msgstr "Nome"
+
+msgctxt "field:sale.advance_payment_term.line,account:"
+msgid "Account"
+msgstr ""
+
+msgctxt "field:sale.advance_payment_term.line,accounts:"
+msgid "Accounts"
+msgstr ""
+
+#, fuzzy
+msgctxt "field:sale.advance_payment_term.line,advance_payment_term:"
+msgid "Advance Payment Term"
+msgstr "Advance Payment Terms"
+
+msgctxt "field:sale.advance_payment_term.line,block_shipping:"
+msgid "Block Shipping"
+msgstr ""
+
+msgctxt "field:sale.advance_payment_term.line,block_supply:"
+msgid "Block Supply"
+msgstr ""
+
+msgctxt "field:sale.advance_payment_term.line,description:"
+msgid "Description"
+msgstr ""
+
+msgctxt "field:sale.advance_payment_term.line,formula:"
+msgid "Formula"
+msgstr ""
+
+msgctxt "field:sale.advance_payment_term.line,invoice_delay:"
+msgid "Invoice Delay"
+msgstr ""
+
+msgctxt "field:sale.advance_payment_term.line.account,account:"
+msgid "Account"
+msgstr ""
+
+msgctxt "field:sale.advance_payment_term.line.account,company:"
+msgid "Company"
+msgstr "Azienda"
+
+msgctxt "field:sale.advance_payment_term.line.account,line:"
+msgid "Line"
+msgstr "Riga"
+
+msgctxt "field:sale.sale,advance_payment_conditions:"
+msgid "Advance Payment Conditions"
+msgstr ""
+
+msgctxt "field:sale.sale,advance_payment_invoices:"
+msgid "Advance Payment Invoices"
+msgstr ""
+
+#, fuzzy
+msgctxt "field:sale.sale,advance_payment_term:"
+msgid "Advance Payment Term"
+msgstr "Advance Payment Terms"
+
+msgctxt "help:sale.advance_payment_term.line,account:"
+msgid "Used for the line of advance payment invoice."
+msgstr ""
+
+msgctxt "help:sale.advance_payment_term.line,block_shipping:"
+msgid "Check to prevent the packing of the shipment before advance payment."
+msgstr ""
+
+msgctxt "help:sale.advance_payment_term.line,block_supply:"
+msgid "Check to prevent any supply request before advance payment."
+msgstr ""
+
+msgctxt "help:sale.advance_payment_term.line,description:"
+msgid "Used as description for the invoice line."
+msgstr ""
+
+msgctxt "help:sale.advance_payment_term.line,formula:"
+msgid ""
+"A python expression used to compute the advance payment amount that will be evaluated with:\n"
+"- total_amount: The total amount of the sale.\n"
+"- untaxed_amount: The total untaxed amount of the sale."
+msgstr ""
+
+msgctxt "help:sale.advance_payment_term.line,invoice_delay:"
+msgid ""
+"Delta to apply on the sale date for the date of the advance payment invoice."
+msgstr ""
+
+msgctxt "model:ir.action,name:act_advance_invoice_form"
+msgid "Advance Invoices"
+msgstr "Advance Invoices"
+
+msgctxt "model:ir.action,name:act_advance_payment_term_form"
+msgid "Advance Payment Terms"
+msgstr "Advance Payment Terms"
+
+msgctxt "model:ir.message,text:msg_shipping_blocked"
+msgid ""
+"To pack shipments the customer must paid the advance payment for sale "
+"\"%(sale)s\"."
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_term_line_invalid_formula"
+msgid ""
+"Invalid formula \"%(formula)s\" in term line \"%(term_line)s\" with "
+"exception \"%(exception)s\"."
+msgstr ""
+
+msgctxt "model:ir.ui.menu,name:menu_advance_payment_term"
+msgid "Advance Payment Terms"
+msgstr "Advance Payment Terms"
+
+msgctxt "model:sale.advance_payment.condition,name:"
+msgid "Advance Payment Condition"
+msgstr ""
+
+#, fuzzy
+msgctxt "model:sale.advance_payment_term,name:"
+msgid "Advance Payment Term"
+msgstr "Advance Payment Terms"
+
+#, fuzzy
+msgctxt "model:sale.advance_payment_term.line,name:"
+msgid "Advance Payment Term Line"
+msgstr "Advance Payment Terms"
+
+#, fuzzy
+msgctxt "model:sale.advance_payment_term.line.account,name:"
+msgid "Advance Payment Term Line Account"
+msgstr "Advance Payment Terms"
diff --git a/modules/sale_advance_payment/locale/lo.po b/modules/sale_advance_payment/locale/lo.po
new file mode 100644
index 0000000000..ce53ee15b4
--- /dev/null
+++ b/modules/sale_advance_payment/locale/lo.po
@@ -0,0 +1,192 @@
+#
+msgid ""
+msgstr "Content-Type: text/plain; charset=utf-8\n"
+
+msgctxt "field:account.account.type,unearned_revenue:"
+msgid "Unearned Revenue"
+msgstr ""
+
+msgctxt "field:account.account.type.template,unearned_revenue:"
+msgid "Unearned Revenue"
+msgstr ""
+
+msgctxt "field:sale.advance_payment.condition,account:"
+msgid "Account"
+msgstr ""
+
+msgctxt "field:sale.advance_payment.condition,amount:"
+msgid "Amount"
+msgstr ""
+
+msgctxt "field:sale.advance_payment.condition,block_shipping:"
+msgid "Block Shipping"
+msgstr ""
+
+msgctxt "field:sale.advance_payment.condition,block_supply:"
+msgid "Block Supply"
+msgstr ""
+
+msgctxt "field:sale.advance_payment.condition,completed:"
+msgid "Completed"
+msgstr ""
+
+msgctxt "field:sale.advance_payment.condition,description:"
+msgid "Description"
+msgstr ""
+
+msgctxt "field:sale.advance_payment.condition,invoice_delay:"
+msgid "Invoice Delay"
+msgstr ""
+
+msgctxt "field:sale.advance_payment.condition,invoice_lines:"
+msgid "Invoice Lines"
+msgstr ""
+
+msgctxt "field:sale.advance_payment.condition,sale:"
+msgid "Sale"
+msgstr ""
+
+msgctxt "field:sale.advance_payment.condition,sale_company:"
+msgid "Company"
+msgstr ""
+
+msgctxt "field:sale.advance_payment.condition,sale_state:"
+msgid "Sale State"
+msgstr ""
+
+msgctxt "field:sale.advance_payment_term,lines:"
+msgid "Lines"
+msgstr ""
+
+msgctxt "field:sale.advance_payment_term,name:"
+msgid "Name"
+msgstr ""
+
+msgctxt "field:sale.advance_payment_term.line,account:"
+msgid "Account"
+msgstr ""
+
+msgctxt "field:sale.advance_payment_term.line,accounts:"
+msgid "Accounts"
+msgstr ""
+
+#, fuzzy
+msgctxt "field:sale.advance_payment_term.line,advance_payment_term:"
+msgid "Advance Payment Term"
+msgstr "Advance Payment Terms"
+
+msgctxt "field:sale.advance_payment_term.line,block_shipping:"
+msgid "Block Shipping"
+msgstr ""
+
+msgctxt "field:sale.advance_payment_term.line,block_supply:"
+msgid "Block Supply"
+msgstr ""
+
+msgctxt "field:sale.advance_payment_term.line,description:"
+msgid "Description"
+msgstr ""
+
+msgctxt "field:sale.advance_payment_term.line,formula:"
+msgid "Formula"
+msgstr ""
+
+msgctxt "field:sale.advance_payment_term.line,invoice_delay:"
+msgid "Invoice Delay"
+msgstr ""
+
+msgctxt "field:sale.advance_payment_term.line.account,account:"
+msgid "Account"
+msgstr ""
+
+msgctxt "field:sale.advance_payment_term.line.account,company:"
+msgid "Company"
+msgstr ""
+
+msgctxt "field:sale.advance_payment_term.line.account,line:"
+msgid "Line"
+msgstr ""
+
+msgctxt "field:sale.sale,advance_payment_conditions:"
+msgid "Advance Payment Conditions"
+msgstr ""
+
+msgctxt "field:sale.sale,advance_payment_invoices:"
+msgid "Advance Payment Invoices"
+msgstr ""
+
+#, fuzzy
+msgctxt "field:sale.sale,advance_payment_term:"
+msgid "Advance Payment Term"
+msgstr "Advance Payment Terms"
+
+msgctxt "help:sale.advance_payment_term.line,account:"
+msgid "Used for the line of advance payment invoice."
+msgstr ""
+
+msgctxt "help:sale.advance_payment_term.line,block_shipping:"
+msgid "Check to prevent the packing of the shipment before advance payment."
+msgstr ""
+
+msgctxt "help:sale.advance_payment_term.line,block_supply:"
+msgid "Check to prevent any supply request before advance payment."
+msgstr ""
+
+msgctxt "help:sale.advance_payment_term.line,description:"
+msgid "Used as description for the invoice line."
+msgstr ""
+
+msgctxt "help:sale.advance_payment_term.line,formula:"
+msgid ""
+"A python expression used to compute the advance payment amount that will be evaluated with:\n"
+"- total_amount: The total amount of the sale.\n"
+"- untaxed_amount: The total untaxed amount of the sale."
+msgstr ""
+
+msgctxt "help:sale.advance_payment_term.line,invoice_delay:"
+msgid ""
+"Delta to apply on the sale date for the date of the advance payment invoice."
+msgstr ""
+
+msgctxt "model:ir.action,name:act_advance_invoice_form"
+msgid "Advance Invoices"
+msgstr "Advance Invoices"
+
+msgctxt "model:ir.action,name:act_advance_payment_term_form"
+msgid "Advance Payment Terms"
+msgstr "Advance Payment Terms"
+
+msgctxt "model:ir.message,text:msg_shipping_blocked"
+msgid ""
+"To pack shipments the customer must paid the advance payment for sale "
+"\"%(sale)s\"."
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_term_line_invalid_formula"
+msgid ""
+"Invalid formula \"%(formula)s\" in term line \"%(term_line)s\" with "
+"exception \"%(exception)s\"."
+msgstr ""
+
+msgctxt "model:ir.ui.menu,name:menu_advance_payment_term"
+msgid "Advance Payment Terms"
+msgstr "Advance Payment Terms"
+
+msgctxt "model:sale.advance_payment.condition,name:"
+msgid "Advance Payment Condition"
+msgstr ""
+
+#, fuzzy
+msgctxt "model:sale.advance_payment_term,name:"
+msgid "Advance Payment Term"
+msgstr "Advance Payment Terms"
+
+#, fuzzy
+msgctxt "model:sale.advance_payment_term.line,name:"
+msgid "Advance Payment Term Line"
+msgstr "Advance Payment Terms"
+
+#, fuzzy
+msgctxt "model:sale.advance_payment_term.line.account,name:"
+msgid "Advance Payment Term Line Account"
+msgstr "Advance Payment Terms"
diff --git a/modules/sale_advance_payment/locale/lt.po b/modules/sale_advance_payment/locale/lt.po
new file mode 100644
index 0000000000..7c21cd6877
--- /dev/null
+++ b/modules/sale_advance_payment/locale/lt.po
@@ -0,0 +1,192 @@
+#
+msgid ""
+msgstr "Content-Type: text/plain; charset=utf-8\n"
+
+msgctxt "field:account.account.type,unearned_revenue:"
+msgid "Unearned Revenue"
+msgstr ""
+
+msgctxt "field:account.account.type.template,unearned_revenue:"
+msgid "Unearned Revenue"
+msgstr ""
+
+msgctxt "field:sale.advance_payment.condition,account:"
+msgid "Account"
+msgstr ""
+
+msgctxt "field:sale.advance_payment.condition,amount:"
+msgid "Amount"
+msgstr ""
+
+msgctxt "field:sale.advance_payment.condition,block_shipping:"
+msgid "Block Shipping"
+msgstr ""
+
+msgctxt "field:sale.advance_payment.condition,block_supply:"
+msgid "Block Supply"
+msgstr ""
+
+msgctxt "field:sale.advance_payment.condition,completed:"
+msgid "Completed"
+msgstr ""
+
+msgctxt "field:sale.advance_payment.condition,description:"
+msgid "Description"
+msgstr ""
+
+msgctxt "field:sale.advance_payment.condition,invoice_delay:"
+msgid "Invoice Delay"
+msgstr "Sąskaitos faktūros užlaikymas"
+
+msgctxt "field:sale.advance_payment.condition,invoice_lines:"
+msgid "Invoice Lines"
+msgstr "Sąskaitos faktūros eilutės"
+
+msgctxt "field:sale.advance_payment.condition,sale:"
+msgid "Sale"
+msgstr ""
+
+msgctxt "field:sale.advance_payment.condition,sale_company:"
+msgid "Company"
+msgstr "Organizacija"
+
+msgctxt "field:sale.advance_payment.condition,sale_state:"
+msgid "Sale State"
+msgstr ""
+
+msgctxt "field:sale.advance_payment_term,lines:"
+msgid "Lines"
+msgstr ""
+
+msgctxt "field:sale.advance_payment_term,name:"
+msgid "Name"
+msgstr ""
+
+msgctxt "field:sale.advance_payment_term.line,account:"
+msgid "Account"
+msgstr ""
+
+msgctxt "field:sale.advance_payment_term.line,accounts:"
+msgid "Accounts"
+msgstr ""
+
+#, fuzzy
+msgctxt "field:sale.advance_payment_term.line,advance_payment_term:"
+msgid "Advance Payment Term"
+msgstr "Advance Payment Terms"
+
+msgctxt "field:sale.advance_payment_term.line,block_shipping:"
+msgid "Block Shipping"
+msgstr ""
+
+msgctxt "field:sale.advance_payment_term.line,block_supply:"
+msgid "Block Supply"
+msgstr ""
+
+msgctxt "field:sale.advance_payment_term.line,description:"
+msgid "Description"
+msgstr ""
+
+msgctxt "field:sale.advance_payment_term.line,formula:"
+msgid "Formula"
+msgstr ""
+
+msgctxt "field:sale.advance_payment_term.line,invoice_delay:"
+msgid "Invoice Delay"
+msgstr "Sąskaitos faktūros užlaikymas"
+
+msgctxt "field:sale.advance_payment_term.line.account,account:"
+msgid "Account"
+msgstr ""
+
+msgctxt "field:sale.advance_payment_term.line.account,company:"
+msgid "Company"
+msgstr "Organizacija"
+
+msgctxt "field:sale.advance_payment_term.line.account,line:"
+msgid "Line"
+msgstr ""
+
+msgctxt "field:sale.sale,advance_payment_conditions:"
+msgid "Advance Payment Conditions"
+msgstr ""
+
+msgctxt "field:sale.sale,advance_payment_invoices:"
+msgid "Advance Payment Invoices"
+msgstr "Išankstinio mokėjimo sąskaitos faktūros"
+
+#, fuzzy
+msgctxt "field:sale.sale,advance_payment_term:"
+msgid "Advance Payment Term"
+msgstr "Advance Payment Terms"
+
+msgctxt "help:sale.advance_payment_term.line,account:"
+msgid "Used for the line of advance payment invoice."
+msgstr "Naudojama išankstinio mokėjimo sąskaitos faktūros eilutei."
+
+msgctxt "help:sale.advance_payment_term.line,block_shipping:"
+msgid "Check to prevent the packing of the shipment before advance payment."
+msgstr ""
+
+msgctxt "help:sale.advance_payment_term.line,block_supply:"
+msgid "Check to prevent any supply request before advance payment."
+msgstr ""
+
+msgctxt "help:sale.advance_payment_term.line,description:"
+msgid "Used as description for the invoice line."
+msgstr ""
+
+msgctxt "help:sale.advance_payment_term.line,formula:"
+msgid ""
+"A python expression used to compute the advance payment amount that will be evaluated with:\n"
+"- total_amount: The total amount of the sale.\n"
+"- untaxed_amount: The total untaxed amount of the sale."
+msgstr ""
+
+msgctxt "help:sale.advance_payment_term.line,invoice_delay:"
+msgid ""
+"Delta to apply on the sale date for the date of the advance payment invoice."
+msgstr ""
+
+msgctxt "model:ir.action,name:act_advance_invoice_form"
+msgid "Advance Invoices"
+msgstr "Išankstinės sąskaitos faktūros"
+
+msgctxt "model:ir.action,name:act_advance_payment_term_form"
+msgid "Advance Payment Terms"
+msgstr "Advance Payment Terms"
+
+msgctxt "model:ir.message,text:msg_shipping_blocked"
+msgid ""
+"To pack shipments the customer must paid the advance payment for sale "
+"\"%(sale)s\"."
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_term_line_invalid_formula"
+msgid ""
+"Invalid formula \"%(formula)s\" in term line \"%(term_line)s\" with "
+"exception \"%(exception)s\"."
+msgstr ""
+
+msgctxt "model:ir.ui.menu,name:menu_advance_payment_term"
+msgid "Advance Payment Terms"
+msgstr "Advance Payment Terms"
+
+msgctxt "model:sale.advance_payment.condition,name:"
+msgid "Advance Payment Condition"
+msgstr ""
+
+#, fuzzy
+msgctxt "model:sale.advance_payment_term,name:"
+msgid "Advance Payment Term"
+msgstr "Advance Payment Terms"
+
+#, fuzzy
+msgctxt "model:sale.advance_payment_term.line,name:"
+msgid "Advance Payment Term Line"
+msgstr "Advance Payment Terms"
+
+#, fuzzy
+msgctxt "model:sale.advance_payment_term.line.account,name:"
+msgid "Advance Payment Term Line Account"
+msgstr "Advance Payment Terms"
diff --git a/modules/sale_advance_payment/locale/nl.po b/modules/sale_advance_payment/locale/nl.po
new file mode 100644
index 0000000000..778b137081
--- /dev/null
+++ b/modules/sale_advance_payment/locale/nl.po
@@ -0,0 +1,197 @@
+#
+msgid ""
+msgstr "Content-Type: text/plain; charset=utf-8\n"
+
+msgctxt "field:account.account.type,unearned_revenue:"
+msgid "Unearned Revenue"
+msgstr "Ontvangen vooruitbetalingen"
+
+msgctxt "field:account.account.type.template,unearned_revenue:"
+msgid "Unearned Revenue"
+msgstr "Ontvangen vooruitbetalingen"
+
+msgctxt "field:sale.advance_payment.condition,account:"
+msgid "Account"
+msgstr "Rekening"
+
+msgctxt "field:sale.advance_payment.condition,amount:"
+msgid "Amount"
+msgstr "Bedrag"
+
+msgctxt "field:sale.advance_payment.condition,block_shipping:"
+msgid "Block Shipping"
+msgstr "Verzending blokkeren"
+
+msgctxt "field:sale.advance_payment.condition,block_supply:"
+msgid "Block Supply"
+msgstr "Levering blokkeren"
+
+msgctxt "field:sale.advance_payment.condition,completed:"
+msgid "Completed"
+msgstr "Voltooid"
+
+msgctxt "field:sale.advance_payment.condition,description:"
+msgid "Description"
+msgstr "Omschrijving"
+
+msgctxt "field:sale.advance_payment.condition,invoice_delay:"
+msgid "Invoice Delay"
+msgstr "Factuurvertraging"
+
+msgctxt "field:sale.advance_payment.condition,invoice_lines:"
+msgid "Invoice Lines"
+msgstr "Factuurregels"
+
+msgctxt "field:sale.advance_payment.condition,sale:"
+msgid "Sale"
+msgstr "Verkoop"
+
+msgctxt "field:sale.advance_payment.condition,sale_company:"
+msgid "Company"
+msgstr "Bedrijf"
+
+msgctxt "field:sale.advance_payment.condition,sale_state:"
+msgid "Sale State"
+msgstr "Staat van de verkoop"
+
+msgctxt "field:sale.advance_payment_term,lines:"
+msgid "Lines"
+msgstr "Regels"
+
+msgctxt "field:sale.advance_payment_term,name:"
+msgid "Name"
+msgstr "Naam"
+
+msgctxt "field:sale.advance_payment_term.line,account:"
+msgid "Account"
+msgstr "Rekening"
+
+msgctxt "field:sale.advance_payment_term.line,accounts:"
+msgid "Accounts"
+msgstr "Rekeningen"
+
+msgctxt "field:sale.advance_payment_term.line,advance_payment_term:"
+msgid "Advance Payment Term"
+msgstr "Betalingsvoorwaarden vooruitbetaling"
+
+msgctxt "field:sale.advance_payment_term.line,block_shipping:"
+msgid "Block Shipping"
+msgstr "Verzending blokkeren"
+
+msgctxt "field:sale.advance_payment_term.line,block_supply:"
+msgid "Block Supply"
+msgstr "Levering blokkeren"
+
+msgctxt "field:sale.advance_payment_term.line,description:"
+msgid "Description"
+msgstr "Omschrijving"
+
+msgctxt "field:sale.advance_payment_term.line,formula:"
+msgid "Formula"
+msgstr "Formule"
+
+msgctxt "field:sale.advance_payment_term.line,invoice_delay:"
+msgid "Invoice Delay"
+msgstr "Factuurvertraging"
+
+msgctxt "field:sale.advance_payment_term.line.account,account:"
+msgid "Account"
+msgstr "Rekening"
+
+msgctxt "field:sale.advance_payment_term.line.account,company:"
+msgid "Company"
+msgstr "Bedrijf"
+
+msgctxt "field:sale.advance_payment_term.line.account,line:"
+msgid "Line"
+msgstr "Regel"
+
+msgctxt "field:sale.sale,advance_payment_conditions:"
+msgid "Advance Payment Conditions"
+msgstr "Vooruitbetalingsvoorwaarden"
+
+msgctxt "field:sale.sale,advance_payment_invoices:"
+msgid "Advance Payment Invoices"
+msgstr "Vooruitbetalingsfacturen"
+
+msgctxt "field:sale.sale,advance_payment_term:"
+msgid "Advance Payment Term"
+msgstr "Betalingsvoorwaarden vooruitbetaling"
+
+msgctxt "help:sale.advance_payment_term.line,account:"
+msgid "Used for the line of advance payment invoice."
+msgstr "Wordt gebruikt voor de regel van de factuur voor vooruitbetaling."
+
+msgctxt "help:sale.advance_payment_term.line,block_shipping:"
+msgid "Check to prevent the packing of the shipment before advance payment."
+msgstr ""
+"Vink aan om de verpakking van de zending te voorkomen vóór vooruitbetaling."
+
+msgctxt "help:sale.advance_payment_term.line,block_supply:"
+msgid "Check to prevent any supply request before advance payment."
+msgstr "Vink aan om een leveringsverzoek te voorkomen vóór vooruitbetaling."
+
+msgctxt "help:sale.advance_payment_term.line,description:"
+msgid "Used as description for the invoice line."
+msgstr "Gebruikt als omschrijving voor de factuurregel."
+
+msgctxt "help:sale.advance_payment_term.line,formula:"
+msgid ""
+"A python expression used to compute the advance payment amount that will be evaluated with:\n"
+"- total_amount: The total amount of the sale.\n"
+"- untaxed_amount: The total untaxed amount of the sale."
+msgstr ""
+"Een python-uitdrukking die wordt gebruikt om het voorschotbedrag te berekenen dat wordt geëvalueerd met:\n"
+"- total_amoun: het totale bedrag van de verkoop.\n"
+"-untaxed_amount:: het totale onbelaste bedrag van de verkoop."
+
+msgctxt "help:sale.advance_payment_term.line,invoice_delay:"
+msgid ""
+"Delta to apply on the sale date for the date of the advance payment invoice."
+msgstr ""
+"Tijdsperiode voor de verkoopdatum, om de datum van de voorschotfactuur te "
+"bepalen."
+
+msgctxt "model:ir.action,name:act_advance_invoice_form"
+msgid "Advance Invoices"
+msgstr "Voorschotfacturen"
+
+msgctxt "model:ir.action,name:act_advance_payment_term_form"
+msgid "Advance Payment Terms"
+msgstr "betalingsvoorwaarden voorschotfacturen"
+
+msgctxt "model:ir.message,text:msg_shipping_blocked"
+msgid ""
+"To pack shipments the customer must paid the advance payment for sale "
+"\"%(sale)s\"."
+msgstr ""
+"Om zendingen in te pakken, moet de klant het voorschot betalen voor verkoop "
+"\"%(sale)s\"."
+
+msgctxt "model:ir.message,text:msg_term_line_invalid_formula"
+msgid ""
+"Invalid formula \"%(formula)s\" in term line \"%(term_line)s\" with "
+"exception \"%(exception)s\"."
+msgstr ""
+"Ongeldige formule \"%(formula)s\" in vooruitbetalingsconditie "
+"\"%(term_line)s\" met foutmelding \"%(exception)s\"."
+
+msgctxt "model:ir.ui.menu,name:menu_advance_payment_term"
+msgid "Advance Payment Terms"
+msgstr "betalingsvoorwaarden voorschotfacturen"
+
+msgctxt "model:sale.advance_payment.condition,name:"
+msgid "Advance Payment Condition"
+msgstr "Vooruitbetalingsvoorwaarden"
+
+msgctxt "model:sale.advance_payment_term,name:"
+msgid "Advance Payment Term"
+msgstr "Betalingsvoorwaarden vooruitbetaling"
+
+msgctxt "model:sale.advance_payment_term.line,name:"
+msgid "Advance Payment Term Line"
+msgstr "Termijn voor vooruitbetaling"
+
+msgctxt "model:sale.advance_payment_term.line.account,name:"
+msgid "Advance Payment Term Line Account"
+msgstr "rekening voorschotfactuurregels"
diff --git a/modules/sale_advance_payment/locale/pl.po b/modules/sale_advance_payment/locale/pl.po
new file mode 100644
index 0000000000..333689f4dc
--- /dev/null
+++ b/modules/sale_advance_payment/locale/pl.po
@@ -0,0 +1,192 @@
+#
+msgid ""
+msgstr "Content-Type: text/plain; charset=utf-8\n"
+
+msgctxt "field:account.account.type,unearned_revenue:"
+msgid "Unearned Revenue"
+msgstr ""
+
+msgctxt "field:account.account.type.template,unearned_revenue:"
+msgid "Unearned Revenue"
+msgstr ""
+
+msgctxt "field:sale.advance_payment.condition,account:"
+msgid "Account"
+msgstr "Konto"
+
+msgctxt "field:sale.advance_payment.condition,amount:"
+msgid "Amount"
+msgstr ""
+
+msgctxt "field:sale.advance_payment.condition,block_shipping:"
+msgid "Block Shipping"
+msgstr ""
+
+msgctxt "field:sale.advance_payment.condition,block_supply:"
+msgid "Block Supply"
+msgstr ""
+
+msgctxt "field:sale.advance_payment.condition,completed:"
+msgid "Completed"
+msgstr ""
+
+msgctxt "field:sale.advance_payment.condition,description:"
+msgid "Description"
+msgstr "Opis"
+
+msgctxt "field:sale.advance_payment.condition,invoice_delay:"
+msgid "Invoice Delay"
+msgstr ""
+
+msgctxt "field:sale.advance_payment.condition,invoice_lines:"
+msgid "Invoice Lines"
+msgstr "Wiersze faktury"
+
+msgctxt "field:sale.advance_payment.condition,sale:"
+msgid "Sale"
+msgstr "Sprzedaż"
+
+msgctxt "field:sale.advance_payment.condition,sale_company:"
+msgid "Company"
+msgstr "Firma"
+
+msgctxt "field:sale.advance_payment.condition,sale_state:"
+msgid "Sale State"
+msgstr "Stan sprzedaży"
+
+msgctxt "field:sale.advance_payment_term,lines:"
+msgid "Lines"
+msgstr "Wiersze"
+
+msgctxt "field:sale.advance_payment_term,name:"
+msgid "Name"
+msgstr "Nazwa"
+
+msgctxt "field:sale.advance_payment_term.line,account:"
+msgid "Account"
+msgstr "Konto"
+
+msgctxt "field:sale.advance_payment_term.line,accounts:"
+msgid "Accounts"
+msgstr "Konta"
+
+#, fuzzy
+msgctxt "field:sale.advance_payment_term.line,advance_payment_term:"
+msgid "Advance Payment Term"
+msgstr "Advance Payment Terms"
+
+msgctxt "field:sale.advance_payment_term.line,block_shipping:"
+msgid "Block Shipping"
+msgstr ""
+
+msgctxt "field:sale.advance_payment_term.line,block_supply:"
+msgid "Block Supply"
+msgstr ""
+
+msgctxt "field:sale.advance_payment_term.line,description:"
+msgid "Description"
+msgstr "Opis"
+
+msgctxt "field:sale.advance_payment_term.line,formula:"
+msgid "Formula"
+msgstr "Formuła"
+
+msgctxt "field:sale.advance_payment_term.line,invoice_delay:"
+msgid "Invoice Delay"
+msgstr ""
+
+msgctxt "field:sale.advance_payment_term.line.account,account:"
+msgid "Account"
+msgstr "Konto"
+
+msgctxt "field:sale.advance_payment_term.line.account,company:"
+msgid "Company"
+msgstr "Firma"
+
+msgctxt "field:sale.advance_payment_term.line.account,line:"
+msgid "Line"
+msgstr "Wiersz"
+
+msgctxt "field:sale.sale,advance_payment_conditions:"
+msgid "Advance Payment Conditions"
+msgstr ""
+
+msgctxt "field:sale.sale,advance_payment_invoices:"
+msgid "Advance Payment Invoices"
+msgstr ""
+
+#, fuzzy
+msgctxt "field:sale.sale,advance_payment_term:"
+msgid "Advance Payment Term"
+msgstr "Advance Payment Terms"
+
+msgctxt "help:sale.advance_payment_term.line,account:"
+msgid "Used for the line of advance payment invoice."
+msgstr ""
+
+msgctxt "help:sale.advance_payment_term.line,block_shipping:"
+msgid "Check to prevent the packing of the shipment before advance payment."
+msgstr ""
+
+msgctxt "help:sale.advance_payment_term.line,block_supply:"
+msgid "Check to prevent any supply request before advance payment."
+msgstr ""
+
+msgctxt "help:sale.advance_payment_term.line,description:"
+msgid "Used as description for the invoice line."
+msgstr ""
+
+msgctxt "help:sale.advance_payment_term.line,formula:"
+msgid ""
+"A python expression used to compute the advance payment amount that will be evaluated with:\n"
+"- total_amount: The total amount of the sale.\n"
+"- untaxed_amount: The total untaxed amount of the sale."
+msgstr ""
+
+msgctxt "help:sale.advance_payment_term.line,invoice_delay:"
+msgid ""
+"Delta to apply on the sale date for the date of the advance payment invoice."
+msgstr ""
+
+msgctxt "model:ir.action,name:act_advance_invoice_form"
+msgid "Advance Invoices"
+msgstr "Advance Invoices"
+
+msgctxt "model:ir.action,name:act_advance_payment_term_form"
+msgid "Advance Payment Terms"
+msgstr "Advance Payment Terms"
+
+msgctxt "model:ir.message,text:msg_shipping_blocked"
+msgid ""
+"To pack shipments the customer must paid the advance payment for sale "
+"\"%(sale)s\"."
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_term_line_invalid_formula"
+msgid ""
+"Invalid formula \"%(formula)s\" in term line \"%(term_line)s\" with "
+"exception \"%(exception)s\"."
+msgstr ""
+
+msgctxt "model:ir.ui.menu,name:menu_advance_payment_term"
+msgid "Advance Payment Terms"
+msgstr "Advance Payment Terms"
+
+msgctxt "model:sale.advance_payment.condition,name:"
+msgid "Advance Payment Condition"
+msgstr ""
+
+#, fuzzy
+msgctxt "model:sale.advance_payment_term,name:"
+msgid "Advance Payment Term"
+msgstr "Advance Payment Terms"
+
+#, fuzzy
+msgctxt "model:sale.advance_payment_term.line,name:"
+msgid "Advance Payment Term Line"
+msgstr "Advance Payment Terms"
+
+#, fuzzy
+msgctxt "model:sale.advance_payment_term.line.account,name:"
+msgid "Advance Payment Term Line Account"
+msgstr "Advance Payment Terms"
diff --git a/modules/sale_advance_payment/locale/pt.po b/modules/sale_advance_payment/locale/pt.po
new file mode 100644
index 0000000000..fed4049b62
--- /dev/null
+++ b/modules/sale_advance_payment/locale/pt.po
@@ -0,0 +1,199 @@
+#
+msgid ""
+msgstr "Content-Type: text/plain; charset=utf-8\n"
+
+msgctxt "field:account.account.type,unearned_revenue:"
+msgid "Unearned Revenue"
+msgstr ""
+
+msgctxt "field:account.account.type.template,unearned_revenue:"
+msgid "Unearned Revenue"
+msgstr ""
+
+msgctxt "field:sale.advance_payment.condition,account:"
+msgid "Account"
+msgstr "Conta"
+
+msgctxt "field:sale.advance_payment.condition,amount:"
+msgid "Amount"
+msgstr "Montante"
+
+msgctxt "field:sale.advance_payment.condition,block_shipping:"
+msgid "Block Shipping"
+msgstr "Bloquear Remessa"
+
+msgctxt "field:sale.advance_payment.condition,block_supply:"
+msgid "Block Supply"
+msgstr "Bloquear Abastecimento"
+
+msgctxt "field:sale.advance_payment.condition,completed:"
+msgid "Completed"
+msgstr "Concluído"
+
+msgctxt "field:sale.advance_payment.condition,description:"
+msgid "Description"
+msgstr "Descrição"
+
+msgctxt "field:sale.advance_payment.condition,invoice_delay:"
+msgid "Invoice Delay"
+msgstr "Atraso na Fatura"
+
+msgctxt "field:sale.advance_payment.condition,invoice_lines:"
+msgid "Invoice Lines"
+msgstr "Linhas de Faturas"
+
+msgctxt "field:sale.advance_payment.condition,sale:"
+msgid "Sale"
+msgstr "Venda"
+
+msgctxt "field:sale.advance_payment.condition,sale_company:"
+msgid "Company"
+msgstr "Empresa"
+
+msgctxt "field:sale.advance_payment.condition,sale_state:"
+msgid "Sale State"
+msgstr "Estado da Venda"
+
+msgctxt "field:sale.advance_payment_term,lines:"
+msgid "Lines"
+msgstr "Linhas"
+
+msgctxt "field:sale.advance_payment_term,name:"
+msgid "Name"
+msgstr "Nome"
+
+msgctxt "field:sale.advance_payment_term.line,account:"
+msgid "Account"
+msgstr "Conta"
+
+msgctxt "field:sale.advance_payment_term.line,accounts:"
+msgid "Accounts"
+msgstr "Contas"
+
+msgctxt "field:sale.advance_payment_term.line,advance_payment_term:"
+msgid "Advance Payment Term"
+msgstr "Prazo do Pagamento Adiantado"
+
+msgctxt "field:sale.advance_payment_term.line,block_shipping:"
+msgid "Block Shipping"
+msgstr "Bloquear Remessa"
+
+msgctxt "field:sale.advance_payment_term.line,block_supply:"
+msgid "Block Supply"
+msgstr "Bloquear Abastecimento"
+
+msgctxt "field:sale.advance_payment_term.line,description:"
+msgid "Description"
+msgstr "Descrição"
+
+msgctxt "field:sale.advance_payment_term.line,formula:"
+msgid "Formula"
+msgstr "Fórmula"
+
+msgctxt "field:sale.advance_payment_term.line,invoice_delay:"
+msgid "Invoice Delay"
+msgstr "Atraso na Fatura"
+
+msgctxt "field:sale.advance_payment_term.line.account,account:"
+msgid "Account"
+msgstr "Conta"
+
+msgctxt "field:sale.advance_payment_term.line.account,company:"
+msgid "Company"
+msgstr "Empresa"
+
+msgctxt "field:sale.advance_payment_term.line.account,line:"
+msgid "Line"
+msgstr "Linha"
+
+msgctxt "field:sale.sale,advance_payment_conditions:"
+msgid "Advance Payment Conditions"
+msgstr "Condições de Pagamento Adiantado"
+
+msgctxt "field:sale.sale,advance_payment_invoices:"
+msgid "Advance Payment Invoices"
+msgstr "Faturas de Pagamentos Adiantados"
+
+msgctxt "field:sale.sale,advance_payment_term:"
+msgid "Advance Payment Term"
+msgstr "Prazo de Pagamento Avançado"
+
+msgctxt "help:sale.advance_payment_term.line,account:"
+msgid "Used for the line of advance payment invoice."
+msgstr "Usado na linha de pagamento adiantado da fatura."
+
+msgctxt "help:sale.advance_payment_term.line,block_shipping:"
+msgid "Check to prevent the packing of the shipment before advance payment."
+msgstr ""
+"Marque para prevenir o empacotamento da remessa antes do pagamento "
+"adiantado."
+
+msgctxt "help:sale.advance_payment_term.line,block_supply:"
+msgid "Check to prevent any supply request before advance payment."
+msgstr ""
+"Marque para prevenir quaisquer pedidos de abastecimentos antes do pagamento "
+"adiantado."
+
+msgctxt "help:sale.advance_payment_term.line,description:"
+msgid "Used as description for the invoice line."
+msgstr "Usado como descrição na linha da fatura."
+
+msgctxt "help:sale.advance_payment_term.line,formula:"
+msgid ""
+"A python expression used to compute the advance payment amount that will be evaluated with:\n"
+"- total_amount: The total amount of the sale.\n"
+"- untaxed_amount: The total untaxed amount of the sale."
+msgstr ""
+"Uma expressão python usada para calcular o montante do pagamento adiantado.\n"
+"- total_amount: O montante total da venda.\n"
+"- untaxed_amount: O total não tributado do montante da venda."
+
+msgctxt "help:sale.advance_payment_term.line,invoice_delay:"
+msgid ""
+"Delta to apply on the sale date for the date of the advance payment invoice."
+msgstr ""
+"Delta a ser aplicado na data da venda para a data do pagamento adiantado da "
+"fatura."
+
+#, fuzzy
+msgctxt "model:ir.action,name:act_advance_invoice_form"
+msgid "Advance Invoices"
+msgstr "Advance Invoices"
+
+#, fuzzy
+msgctxt "model:ir.action,name:act_advance_payment_term_form"
+msgid "Advance Payment Terms"
+msgstr "Advance Payment Terms"
+
+msgctxt "model:ir.message,text:msg_shipping_blocked"
+msgid ""
+"To pack shipments the customer must paid the advance payment for sale "
+"\"%(sale)s\"."
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_term_line_invalid_formula"
+msgid ""
+"Invalid formula \"%(formula)s\" in term line \"%(term_line)s\" with "
+"exception \"%(exception)s\"."
+msgstr ""
+
+#, fuzzy
+msgctxt "model:ir.ui.menu,name:menu_advance_payment_term"
+msgid "Advance Payment Terms"
+msgstr "Advance Payment Terms"
+
+msgctxt "model:sale.advance_payment.condition,name:"
+msgid "Advance Payment Condition"
+msgstr "Condições de Pagamentos Adiantados"
+
+msgctxt "model:sale.advance_payment_term,name:"
+msgid "Advance Payment Term"
+msgstr "Prazos de Pagamentos Adiantados"
+
+msgctxt "model:sale.advance_payment_term.line,name:"
+msgid "Advance Payment Term Line"
+msgstr "Linha de Prazos de Pagamentos Adiantados"
+
+msgctxt "model:sale.advance_payment_term.line.account,name:"
+msgid "Advance Payment Term Line Account"
+msgstr "Conta da linha de Prazos de Pagamentos Adiantados"
diff --git a/modules/sale_advance_payment/locale/ro.po b/modules/sale_advance_payment/locale/ro.po
new file mode 100644
index 0000000000..2c22ff08ee
--- /dev/null
+++ b/modules/sale_advance_payment/locale/ro.po
@@ -0,0 +1,187 @@
+#
+msgid ""
+msgstr "Content-Type: text/plain; charset=utf-8\n"
+
+msgctxt "field:account.account.type,unearned_revenue:"
+msgid "Unearned Revenue"
+msgstr ""
+
+msgctxt "field:account.account.type.template,unearned_revenue:"
+msgid "Unearned Revenue"
+msgstr ""
+
+msgctxt "field:sale.advance_payment.condition,account:"
+msgid "Account"
+msgstr "Cont"
+
+msgctxt "field:sale.advance_payment.condition,amount:"
+msgid "Amount"
+msgstr "Suma"
+
+msgctxt "field:sale.advance_payment.condition,block_shipping:"
+msgid "Block Shipping"
+msgstr ""
+
+msgctxt "field:sale.advance_payment.condition,block_supply:"
+msgid "Block Supply"
+msgstr ""
+
+msgctxt "field:sale.advance_payment.condition,completed:"
+msgid "Completed"
+msgstr ""
+
+msgctxt "field:sale.advance_payment.condition,description:"
+msgid "Description"
+msgstr "Descriere"
+
+msgctxt "field:sale.advance_payment.condition,invoice_delay:"
+msgid "Invoice Delay"
+msgstr ""
+
+msgctxt "field:sale.advance_payment.condition,invoice_lines:"
+msgid "Invoice Lines"
+msgstr ""
+
+msgctxt "field:sale.advance_payment.condition,sale:"
+msgid "Sale"
+msgstr ""
+
+msgctxt "field:sale.advance_payment.condition,sale_company:"
+msgid "Company"
+msgstr "Companie"
+
+msgctxt "field:sale.advance_payment.condition,sale_state:"
+msgid "Sale State"
+msgstr ""
+
+msgctxt "field:sale.advance_payment_term,lines:"
+msgid "Lines"
+msgstr "Rânduri"
+
+msgctxt "field:sale.advance_payment_term,name:"
+msgid "Name"
+msgstr ""
+
+msgctxt "field:sale.advance_payment_term.line,account:"
+msgid "Account"
+msgstr "Cont"
+
+msgctxt "field:sale.advance_payment_term.line,accounts:"
+msgid "Accounts"
+msgstr "Conturi"
+
+msgctxt "field:sale.advance_payment_term.line,advance_payment_term:"
+msgid "Advance Payment Term"
+msgstr "Termen de plata in avans"
+
+msgctxt "field:sale.advance_payment_term.line,block_shipping:"
+msgid "Block Shipping"
+msgstr ""
+
+msgctxt "field:sale.advance_payment_term.line,block_supply:"
+msgid "Block Supply"
+msgstr ""
+
+msgctxt "field:sale.advance_payment_term.line,description:"
+msgid "Description"
+msgstr "Descriere"
+
+msgctxt "field:sale.advance_payment_term.line,formula:"
+msgid "Formula"
+msgstr ""
+
+msgctxt "field:sale.advance_payment_term.line,invoice_delay:"
+msgid "Invoice Delay"
+msgstr ""
+
+msgctxt "field:sale.advance_payment_term.line.account,account:"
+msgid "Account"
+msgstr "Cont"
+
+msgctxt "field:sale.advance_payment_term.line.account,company:"
+msgid "Company"
+msgstr "Companie"
+
+msgctxt "field:sale.advance_payment_term.line.account,line:"
+msgid "Line"
+msgstr ""
+
+msgctxt "field:sale.sale,advance_payment_conditions:"
+msgid "Advance Payment Conditions"
+msgstr ""
+
+msgctxt "field:sale.sale,advance_payment_invoices:"
+msgid "Advance Payment Invoices"
+msgstr ""
+
+msgctxt "field:sale.sale,advance_payment_term:"
+msgid "Advance Payment Term"
+msgstr ""
+
+msgctxt "help:sale.advance_payment_term.line,account:"
+msgid "Used for the line of advance payment invoice."
+msgstr ""
+
+msgctxt "help:sale.advance_payment_term.line,block_shipping:"
+msgid "Check to prevent the packing of the shipment before advance payment."
+msgstr ""
+
+msgctxt "help:sale.advance_payment_term.line,block_supply:"
+msgid "Check to prevent any supply request before advance payment."
+msgstr ""
+
+msgctxt "help:sale.advance_payment_term.line,description:"
+msgid "Used as description for the invoice line."
+msgstr ""
+
+msgctxt "help:sale.advance_payment_term.line,formula:"
+msgid ""
+"A python expression used to compute the advance payment amount that will be evaluated with:\n"
+"- total_amount: The total amount of the sale.\n"
+"- untaxed_amount: The total untaxed amount of the sale."
+msgstr ""
+
+msgctxt "help:sale.advance_payment_term.line,invoice_delay:"
+msgid ""
+"Delta to apply on the sale date for the date of the advance payment invoice."
+msgstr ""
+
+msgctxt "model:ir.action,name:act_advance_invoice_form"
+msgid "Advance Invoices"
+msgstr ""
+
+msgctxt "model:ir.action,name:act_advance_payment_term_form"
+msgid "Advance Payment Terms"
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_shipping_blocked"
+msgid ""
+"To pack shipments the customer must paid the advance payment for sale "
+"\"%(sale)s\"."
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_term_line_invalid_formula"
+msgid ""
+"Invalid formula \"%(formula)s\" in term line \"%(term_line)s\" with "
+"exception \"%(exception)s\"."
+msgstr ""
+
+msgctxt "model:ir.ui.menu,name:menu_advance_payment_term"
+msgid "Advance Payment Terms"
+msgstr ""
+
+msgctxt "model:sale.advance_payment.condition,name:"
+msgid "Advance Payment Condition"
+msgstr ""
+
+msgctxt "model:sale.advance_payment_term,name:"
+msgid "Advance Payment Term"
+msgstr ""
+
+msgctxt "model:sale.advance_payment_term.line,name:"
+msgid "Advance Payment Term Line"
+msgstr ""
+
+msgctxt "model:sale.advance_payment_term.line.account,name:"
+msgid "Advance Payment Term Line Account"
+msgstr ""
diff --git a/modules/sale_advance_payment/locale/ru.po b/modules/sale_advance_payment/locale/ru.po
new file mode 100644
index 0000000000..ce53ee15b4
--- /dev/null
+++ b/modules/sale_advance_payment/locale/ru.po
@@ -0,0 +1,192 @@
+#
+msgid ""
+msgstr "Content-Type: text/plain; charset=utf-8\n"
+
+msgctxt "field:account.account.type,unearned_revenue:"
+msgid "Unearned Revenue"
+msgstr ""
+
+msgctxt "field:account.account.type.template,unearned_revenue:"
+msgid "Unearned Revenue"
+msgstr ""
+
+msgctxt "field:sale.advance_payment.condition,account:"
+msgid "Account"
+msgstr ""
+
+msgctxt "field:sale.advance_payment.condition,amount:"
+msgid "Amount"
+msgstr ""
+
+msgctxt "field:sale.advance_payment.condition,block_shipping:"
+msgid "Block Shipping"
+msgstr ""
+
+msgctxt "field:sale.advance_payment.condition,block_supply:"
+msgid "Block Supply"
+msgstr ""
+
+msgctxt "field:sale.advance_payment.condition,completed:"
+msgid "Completed"
+msgstr ""
+
+msgctxt "field:sale.advance_payment.condition,description:"
+msgid "Description"
+msgstr ""
+
+msgctxt "field:sale.advance_payment.condition,invoice_delay:"
+msgid "Invoice Delay"
+msgstr ""
+
+msgctxt "field:sale.advance_payment.condition,invoice_lines:"
+msgid "Invoice Lines"
+msgstr ""
+
+msgctxt "field:sale.advance_payment.condition,sale:"
+msgid "Sale"
+msgstr ""
+
+msgctxt "field:sale.advance_payment.condition,sale_company:"
+msgid "Company"
+msgstr ""
+
+msgctxt "field:sale.advance_payment.condition,sale_state:"
+msgid "Sale State"
+msgstr ""
+
+msgctxt "field:sale.advance_payment_term,lines:"
+msgid "Lines"
+msgstr ""
+
+msgctxt "field:sale.advance_payment_term,name:"
+msgid "Name"
+msgstr ""
+
+msgctxt "field:sale.advance_payment_term.line,account:"
+msgid "Account"
+msgstr ""
+
+msgctxt "field:sale.advance_payment_term.line,accounts:"
+msgid "Accounts"
+msgstr ""
+
+#, fuzzy
+msgctxt "field:sale.advance_payment_term.line,advance_payment_term:"
+msgid "Advance Payment Term"
+msgstr "Advance Payment Terms"
+
+msgctxt "field:sale.advance_payment_term.line,block_shipping:"
+msgid "Block Shipping"
+msgstr ""
+
+msgctxt "field:sale.advance_payment_term.line,block_supply:"
+msgid "Block Supply"
+msgstr ""
+
+msgctxt "field:sale.advance_payment_term.line,description:"
+msgid "Description"
+msgstr ""
+
+msgctxt "field:sale.advance_payment_term.line,formula:"
+msgid "Formula"
+msgstr ""
+
+msgctxt "field:sale.advance_payment_term.line,invoice_delay:"
+msgid "Invoice Delay"
+msgstr ""
+
+msgctxt "field:sale.advance_payment_term.line.account,account:"
+msgid "Account"
+msgstr ""
+
+msgctxt "field:sale.advance_payment_term.line.account,company:"
+msgid "Company"
+msgstr ""
+
+msgctxt "field:sale.advance_payment_term.line.account,line:"
+msgid "Line"
+msgstr ""
+
+msgctxt "field:sale.sale,advance_payment_conditions:"
+msgid "Advance Payment Conditions"
+msgstr ""
+
+msgctxt "field:sale.sale,advance_payment_invoices:"
+msgid "Advance Payment Invoices"
+msgstr ""
+
+#, fuzzy
+msgctxt "field:sale.sale,advance_payment_term:"
+msgid "Advance Payment Term"
+msgstr "Advance Payment Terms"
+
+msgctxt "help:sale.advance_payment_term.line,account:"
+msgid "Used for the line of advance payment invoice."
+msgstr ""
+
+msgctxt "help:sale.advance_payment_term.line,block_shipping:"
+msgid "Check to prevent the packing of the shipment before advance payment."
+msgstr ""
+
+msgctxt "help:sale.advance_payment_term.line,block_supply:"
+msgid "Check to prevent any supply request before advance payment."
+msgstr ""
+
+msgctxt "help:sale.advance_payment_term.line,description:"
+msgid "Used as description for the invoice line."
+msgstr ""
+
+msgctxt "help:sale.advance_payment_term.line,formula:"
+msgid ""
+"A python expression used to compute the advance payment amount that will be evaluated with:\n"
+"- total_amount: The total amount of the sale.\n"
+"- untaxed_amount: The total untaxed amount of the sale."
+msgstr ""
+
+msgctxt "help:sale.advance_payment_term.line,invoice_delay:"
+msgid ""
+"Delta to apply on the sale date for the date of the advance payment invoice."
+msgstr ""
+
+msgctxt "model:ir.action,name:act_advance_invoice_form"
+msgid "Advance Invoices"
+msgstr "Advance Invoices"
+
+msgctxt "model:ir.action,name:act_advance_payment_term_form"
+msgid "Advance Payment Terms"
+msgstr "Advance Payment Terms"
+
+msgctxt "model:ir.message,text:msg_shipping_blocked"
+msgid ""
+"To pack shipments the customer must paid the advance payment for sale "
+"\"%(sale)s\"."
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_term_line_invalid_formula"
+msgid ""
+"Invalid formula \"%(formula)s\" in term line \"%(term_line)s\" with "
+"exception \"%(exception)s\"."
+msgstr ""
+
+msgctxt "model:ir.ui.menu,name:menu_advance_payment_term"
+msgid "Advance Payment Terms"
+msgstr "Advance Payment Terms"
+
+msgctxt "model:sale.advance_payment.condition,name:"
+msgid "Advance Payment Condition"
+msgstr ""
+
+#, fuzzy
+msgctxt "model:sale.advance_payment_term,name:"
+msgid "Advance Payment Term"
+msgstr "Advance Payment Terms"
+
+#, fuzzy
+msgctxt "model:sale.advance_payment_term.line,name:"
+msgid "Advance Payment Term Line"
+msgstr "Advance Payment Terms"
+
+#, fuzzy
+msgctxt "model:sale.advance_payment_term.line.account,name:"
+msgid "Advance Payment Term Line Account"
+msgstr "Advance Payment Terms"
diff --git a/modules/sale_advance_payment/locale/sl.po b/modules/sale_advance_payment/locale/sl.po
new file mode 100644
index 0000000000..371ef49749
--- /dev/null
+++ b/modules/sale_advance_payment/locale/sl.po
@@ -0,0 +1,194 @@
+#
+msgid ""
+msgstr "Content-Type: text/plain; charset=utf-8\n"
+
+msgctxt "field:account.account.type,unearned_revenue:"
+msgid "Unearned Revenue"
+msgstr ""
+
+msgctxt "field:account.account.type.template,unearned_revenue:"
+msgid "Unearned Revenue"
+msgstr ""
+
+msgctxt "field:sale.advance_payment.condition,account:"
+msgid "Account"
+msgstr "Konto"
+
+msgctxt "field:sale.advance_payment.condition,amount:"
+msgid "Amount"
+msgstr "Znesek"
+
+msgctxt "field:sale.advance_payment.condition,block_shipping:"
+msgid "Block Shipping"
+msgstr "Blokada odpreme"
+
+msgctxt "field:sale.advance_payment.condition,block_supply:"
+msgid "Block Supply"
+msgstr "Blokada dobave"
+
+msgctxt "field:sale.advance_payment.condition,completed:"
+msgid "Completed"
+msgstr "Zaključeno"
+
+msgctxt "field:sale.advance_payment.condition,description:"
+msgid "Description"
+msgstr "Opis"
+
+msgctxt "field:sale.advance_payment.condition,invoice_delay:"
+msgid "Invoice Delay"
+msgstr "Zamik računa"
+
+msgctxt "field:sale.advance_payment.condition,invoice_lines:"
+msgid "Invoice Lines"
+msgstr "Postavke računa"
+
+msgctxt "field:sale.advance_payment.condition,sale:"
+msgid "Sale"
+msgstr "Prodajni nalog"
+
+msgctxt "field:sale.advance_payment.condition,sale_company:"
+msgid "Company"
+msgstr "Družba"
+
+msgctxt "field:sale.advance_payment.condition,sale_state:"
+msgid "Sale State"
+msgstr "Stanje prodajnega naloga"
+
+msgctxt "field:sale.advance_payment_term,lines:"
+msgid "Lines"
+msgstr "Postavke"
+
+msgctxt "field:sale.advance_payment_term,name:"
+msgid "Name"
+msgstr "Naziv"
+
+msgctxt "field:sale.advance_payment_term.line,account:"
+msgid "Account"
+msgstr "Konto"
+
+msgctxt "field:sale.advance_payment_term.line,accounts:"
+msgid "Accounts"
+msgstr "Konti"
+
+msgctxt "field:sale.advance_payment_term.line,advance_payment_term:"
+msgid "Advance Payment Term"
+msgstr "Avansni pogoj"
+
+msgctxt "field:sale.advance_payment_term.line,block_shipping:"
+msgid "Block Shipping"
+msgstr "Blokada odpreme"
+
+msgctxt "field:sale.advance_payment_term.line,block_supply:"
+msgid "Block Supply"
+msgstr "Blokada dobave"
+
+msgctxt "field:sale.advance_payment_term.line,description:"
+msgid "Description"
+msgstr "Opis"
+
+msgctxt "field:sale.advance_payment_term.line,formula:"
+msgid "Formula"
+msgstr "Formula"
+
+msgctxt "field:sale.advance_payment_term.line,invoice_delay:"
+msgid "Invoice Delay"
+msgstr "Zamik računa"
+
+msgctxt "field:sale.advance_payment_term.line.account,account:"
+msgid "Account"
+msgstr "Konto"
+
+msgctxt "field:sale.advance_payment_term.line.account,company:"
+msgid "Company"
+msgstr "Družba"
+
+msgctxt "field:sale.advance_payment_term.line.account,line:"
+msgid "Line"
+msgstr "Postavka"
+
+msgctxt "field:sale.sale,advance_payment_conditions:"
+msgid "Advance Payment Conditions"
+msgstr "Avansni pogoji"
+
+msgctxt "field:sale.sale,advance_payment_invoices:"
+msgid "Advance Payment Invoices"
+msgstr "Avansni računi"
+
+msgctxt "field:sale.sale,advance_payment_term:"
+msgid "Advance Payment Term"
+msgstr "Avansni pogoj"
+
+msgctxt "help:sale.advance_payment_term.line,account:"
+msgid "Used for the line of advance payment invoice."
+msgstr "Upošteva se na postavkah avansnega računa."
+
+msgctxt "help:sale.advance_payment_term.line,block_shipping:"
+msgid "Check to prevent the packing of the shipment before advance payment."
+msgstr "Označite, če je avans pogoj za pakiranje pošiljke."
+
+msgctxt "help:sale.advance_payment_term.line,block_supply:"
+msgid "Check to prevent any supply request before advance payment."
+msgstr "Označite, če je avans pogoj za katerokoli dobavo."
+
+msgctxt "help:sale.advance_payment_term.line,description:"
+msgid "Used as description for the invoice line."
+msgstr "Upošteva se pri opisu postavke računa."
+
+msgctxt "help:sale.advance_payment_term.line,formula:"
+msgid ""
+"A python expression used to compute the advance payment amount that will be evaluated with:\n"
+"- total_amount: The total amount of the sale.\n"
+"- untaxed_amount: The total untaxed amount of the sale."
+msgstr ""
+"Pythonski izraz za znesek avansa, preračunan z:\n"
+"- total_amount: skupni znesek,\n"
+"- untaxed_amount: skupni neobdavčeni znesek."
+
+msgctxt "help:sale.advance_payment_term.line,invoice_delay:"
+msgid ""
+"Delta to apply on the sale date for the date of the advance payment invoice."
+msgstr ""
+"Upoštevan zamik od datuma prodajnega naloga za datum avansnega računa."
+
+#, fuzzy
+msgctxt "model:ir.action,name:act_advance_invoice_form"
+msgid "Advance Invoices"
+msgstr "Advance Invoices"
+
+#, fuzzy
+msgctxt "model:ir.action,name:act_advance_payment_term_form"
+msgid "Advance Payment Terms"
+msgstr "Advance Payment Terms"
+
+msgctxt "model:ir.message,text:msg_shipping_blocked"
+msgid ""
+"To pack shipments the customer must paid the advance payment for sale "
+"\"%(sale)s\"."
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_term_line_invalid_formula"
+msgid ""
+"Invalid formula \"%(formula)s\" in term line \"%(term_line)s\" with "
+"exception \"%(exception)s\"."
+msgstr ""
+
+#, fuzzy
+msgctxt "model:ir.ui.menu,name:menu_advance_payment_term"
+msgid "Advance Payment Terms"
+msgstr "Advance Payment Terms"
+
+msgctxt "model:sale.advance_payment.condition,name:"
+msgid "Advance Payment Condition"
+msgstr "Avasni pogoj"
+
+msgctxt "model:sale.advance_payment_term,name:"
+msgid "Advance Payment Term"
+msgstr "Avansni pogoj"
+
+msgctxt "model:sale.advance_payment_term.line,name:"
+msgid "Advance Payment Term Line"
+msgstr "Postavka avansnega pogoja"
+
+msgctxt "model:sale.advance_payment_term.line.account,name:"
+msgid "Advance Payment Term Line Account"
+msgstr "Konto postavke avansnega pogoja"
diff --git a/modules/sale_advance_payment/locale/tr.po b/modules/sale_advance_payment/locale/tr.po
new file mode 100644
index 0000000000..ce53ee15b4
--- /dev/null
+++ b/modules/sale_advance_payment/locale/tr.po
@@ -0,0 +1,192 @@
+#
+msgid ""
+msgstr "Content-Type: text/plain; charset=utf-8\n"
+
+msgctxt "field:account.account.type,unearned_revenue:"
+msgid "Unearned Revenue"
+msgstr ""
+
+msgctxt "field:account.account.type.template,unearned_revenue:"
+msgid "Unearned Revenue"
+msgstr ""
+
+msgctxt "field:sale.advance_payment.condition,account:"
+msgid "Account"
+msgstr ""
+
+msgctxt "field:sale.advance_payment.condition,amount:"
+msgid "Amount"
+msgstr ""
+
+msgctxt "field:sale.advance_payment.condition,block_shipping:"
+msgid "Block Shipping"
+msgstr ""
+
+msgctxt "field:sale.advance_payment.condition,block_supply:"
+msgid "Block Supply"
+msgstr ""
+
+msgctxt "field:sale.advance_payment.condition,completed:"
+msgid "Completed"
+msgstr ""
+
+msgctxt "field:sale.advance_payment.condition,description:"
+msgid "Description"
+msgstr ""
+
+msgctxt "field:sale.advance_payment.condition,invoice_delay:"
+msgid "Invoice Delay"
+msgstr ""
+
+msgctxt "field:sale.advance_payment.condition,invoice_lines:"
+msgid "Invoice Lines"
+msgstr ""
+
+msgctxt "field:sale.advance_payment.condition,sale:"
+msgid "Sale"
+msgstr ""
+
+msgctxt "field:sale.advance_payment.condition,sale_company:"
+msgid "Company"
+msgstr ""
+
+msgctxt "field:sale.advance_payment.condition,sale_state:"
+msgid "Sale State"
+msgstr ""
+
+msgctxt "field:sale.advance_payment_term,lines:"
+msgid "Lines"
+msgstr ""
+
+msgctxt "field:sale.advance_payment_term,name:"
+msgid "Name"
+msgstr ""
+
+msgctxt "field:sale.advance_payment_term.line,account:"
+msgid "Account"
+msgstr ""
+
+msgctxt "field:sale.advance_payment_term.line,accounts:"
+msgid "Accounts"
+msgstr ""
+
+#, fuzzy
+msgctxt "field:sale.advance_payment_term.line,advance_payment_term:"
+msgid "Advance Payment Term"
+msgstr "Advance Payment Terms"
+
+msgctxt "field:sale.advance_payment_term.line,block_shipping:"
+msgid "Block Shipping"
+msgstr ""
+
+msgctxt "field:sale.advance_payment_term.line,block_supply:"
+msgid "Block Supply"
+msgstr ""
+
+msgctxt "field:sale.advance_payment_term.line,description:"
+msgid "Description"
+msgstr ""
+
+msgctxt "field:sale.advance_payment_term.line,formula:"
+msgid "Formula"
+msgstr ""
+
+msgctxt "field:sale.advance_payment_term.line,invoice_delay:"
+msgid "Invoice Delay"
+msgstr ""
+
+msgctxt "field:sale.advance_payment_term.line.account,account:"
+msgid "Account"
+msgstr ""
+
+msgctxt "field:sale.advance_payment_term.line.account,company:"
+msgid "Company"
+msgstr ""
+
+msgctxt "field:sale.advance_payment_term.line.account,line:"
+msgid "Line"
+msgstr ""
+
+msgctxt "field:sale.sale,advance_payment_conditions:"
+msgid "Advance Payment Conditions"
+msgstr ""
+
+msgctxt "field:sale.sale,advance_payment_invoices:"
+msgid "Advance Payment Invoices"
+msgstr ""
+
+#, fuzzy
+msgctxt "field:sale.sale,advance_payment_term:"
+msgid "Advance Payment Term"
+msgstr "Advance Payment Terms"
+
+msgctxt "help:sale.advance_payment_term.line,account:"
+msgid "Used for the line of advance payment invoice."
+msgstr ""
+
+msgctxt "help:sale.advance_payment_term.line,block_shipping:"
+msgid "Check to prevent the packing of the shipment before advance payment."
+msgstr ""
+
+msgctxt "help:sale.advance_payment_term.line,block_supply:"
+msgid "Check to prevent any supply request before advance payment."
+msgstr ""
+
+msgctxt "help:sale.advance_payment_term.line,description:"
+msgid "Used as description for the invoice line."
+msgstr ""
+
+msgctxt "help:sale.advance_payment_term.line,formula:"
+msgid ""
+"A python expression used to compute the advance payment amount that will be evaluated with:\n"
+"- total_amount: The total amount of the sale.\n"
+"- untaxed_amount: The total untaxed amount of the sale."
+msgstr ""
+
+msgctxt "help:sale.advance_payment_term.line,invoice_delay:"
+msgid ""
+"Delta to apply on the sale date for the date of the advance payment invoice."
+msgstr ""
+
+msgctxt "model:ir.action,name:act_advance_invoice_form"
+msgid "Advance Invoices"
+msgstr "Advance Invoices"
+
+msgctxt "model:ir.action,name:act_advance_payment_term_form"
+msgid "Advance Payment Terms"
+msgstr "Advance Payment Terms"
+
+msgctxt "model:ir.message,text:msg_shipping_blocked"
+msgid ""
+"To pack shipments the customer must paid the advance payment for sale "
+"\"%(sale)s\"."
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_term_line_invalid_formula"
+msgid ""
+"Invalid formula \"%(formula)s\" in term line \"%(term_line)s\" with "
+"exception \"%(exception)s\"."
+msgstr ""
+
+msgctxt "model:ir.ui.menu,name:menu_advance_payment_term"
+msgid "Advance Payment Terms"
+msgstr "Advance Payment Terms"
+
+msgctxt "model:sale.advance_payment.condition,name:"
+msgid "Advance Payment Condition"
+msgstr ""
+
+#, fuzzy
+msgctxt "model:sale.advance_payment_term,name:"
+msgid "Advance Payment Term"
+msgstr "Advance Payment Terms"
+
+#, fuzzy
+msgctxt "model:sale.advance_payment_term.line,name:"
+msgid "Advance Payment Term Line"
+msgstr "Advance Payment Terms"
+
+#, fuzzy
+msgctxt "model:sale.advance_payment_term.line.account,name:"
+msgid "Advance Payment Term Line Account"
+msgstr "Advance Payment Terms"
diff --git a/modules/sale_advance_payment/locale/zh_CN.po b/modules/sale_advance_payment/locale/zh_CN.po
new file mode 100644
index 0000000000..ce53ee15b4
--- /dev/null
+++ b/modules/sale_advance_payment/locale/zh_CN.po
@@ -0,0 +1,192 @@
+#
+msgid ""
+msgstr "Content-Type: text/plain; charset=utf-8\n"
+
+msgctxt "field:account.account.type,unearned_revenue:"
+msgid "Unearned Revenue"
+msgstr ""
+
+msgctxt "field:account.account.type.template,unearned_revenue:"
+msgid "Unearned Revenue"
+msgstr ""
+
+msgctxt "field:sale.advance_payment.condition,account:"
+msgid "Account"
+msgstr ""
+
+msgctxt "field:sale.advance_payment.condition,amount:"
+msgid "Amount"
+msgstr ""
+
+msgctxt "field:sale.advance_payment.condition,block_shipping:"
+msgid "Block Shipping"
+msgstr ""
+
+msgctxt "field:sale.advance_payment.condition,block_supply:"
+msgid "Block Supply"
+msgstr ""
+
+msgctxt "field:sale.advance_payment.condition,completed:"
+msgid "Completed"
+msgstr ""
+
+msgctxt "field:sale.advance_payment.condition,description:"
+msgid "Description"
+msgstr ""
+
+msgctxt "field:sale.advance_payment.condition,invoice_delay:"
+msgid "Invoice Delay"
+msgstr ""
+
+msgctxt "field:sale.advance_payment.condition,invoice_lines:"
+msgid "Invoice Lines"
+msgstr ""
+
+msgctxt "field:sale.advance_payment.condition,sale:"
+msgid "Sale"
+msgstr ""
+
+msgctxt "field:sale.advance_payment.condition,sale_company:"
+msgid "Company"
+msgstr ""
+
+msgctxt "field:sale.advance_payment.condition,sale_state:"
+msgid "Sale State"
+msgstr ""
+
+msgctxt "field:sale.advance_payment_term,lines:"
+msgid "Lines"
+msgstr ""
+
+msgctxt "field:sale.advance_payment_term,name:"
+msgid "Name"
+msgstr ""
+
+msgctxt "field:sale.advance_payment_term.line,account:"
+msgid "Account"
+msgstr ""
+
+msgctxt "field:sale.advance_payment_term.line,accounts:"
+msgid "Accounts"
+msgstr ""
+
+#, fuzzy
+msgctxt "field:sale.advance_payment_term.line,advance_payment_term:"
+msgid "Advance Payment Term"
+msgstr "Advance Payment Terms"
+
+msgctxt "field:sale.advance_payment_term.line,block_shipping:"
+msgid "Block Shipping"
+msgstr ""
+
+msgctxt "field:sale.advance_payment_term.line,block_supply:"
+msgid "Block Supply"
+msgstr ""
+
+msgctxt "field:sale.advance_payment_term.line,description:"
+msgid "Description"
+msgstr ""
+
+msgctxt "field:sale.advance_payment_term.line,formula:"
+msgid "Formula"
+msgstr ""
+
+msgctxt "field:sale.advance_payment_term.line,invoice_delay:"
+msgid "Invoice Delay"
+msgstr ""
+
+msgctxt "field:sale.advance_payment_term.line.account,account:"
+msgid "Account"
+msgstr ""
+
+msgctxt "field:sale.advance_payment_term.line.account,company:"
+msgid "Company"
+msgstr ""
+
+msgctxt "field:sale.advance_payment_term.line.account,line:"
+msgid "Line"
+msgstr ""
+
+msgctxt "field:sale.sale,advance_payment_conditions:"
+msgid "Advance Payment Conditions"
+msgstr ""
+
+msgctxt "field:sale.sale,advance_payment_invoices:"
+msgid "Advance Payment Invoices"
+msgstr ""
+
+#, fuzzy
+msgctxt "field:sale.sale,advance_payment_term:"
+msgid "Advance Payment Term"
+msgstr "Advance Payment Terms"
+
+msgctxt "help:sale.advance_payment_term.line,account:"
+msgid "Used for the line of advance payment invoice."
+msgstr ""
+
+msgctxt "help:sale.advance_payment_term.line,block_shipping:"
+msgid "Check to prevent the packing of the shipment before advance payment."
+msgstr ""
+
+msgctxt "help:sale.advance_payment_term.line,block_supply:"
+msgid "Check to prevent any supply request before advance payment."
+msgstr ""
+
+msgctxt "help:sale.advance_payment_term.line,description:"
+msgid "Used as description for the invoice line."
+msgstr ""
+
+msgctxt "help:sale.advance_payment_term.line,formula:"
+msgid ""
+"A python expression used to compute the advance payment amount that will be evaluated with:\n"
+"- total_amount: The total amount of the sale.\n"
+"- untaxed_amount: The total untaxed amount of the sale."
+msgstr ""
+
+msgctxt "help:sale.advance_payment_term.line,invoice_delay:"
+msgid ""
+"Delta to apply on the sale date for the date of the advance payment invoice."
+msgstr ""
+
+msgctxt "model:ir.action,name:act_advance_invoice_form"
+msgid "Advance Invoices"
+msgstr "Advance Invoices"
+
+msgctxt "model:ir.action,name:act_advance_payment_term_form"
+msgid "Advance Payment Terms"
+msgstr "Advance Payment Terms"
+
+msgctxt "model:ir.message,text:msg_shipping_blocked"
+msgid ""
+"To pack shipments the customer must paid the advance payment for sale "
+"\"%(sale)s\"."
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_term_line_invalid_formula"
+msgid ""
+"Invalid formula \"%(formula)s\" in term line \"%(term_line)s\" with "
+"exception \"%(exception)s\"."
+msgstr ""
+
+msgctxt "model:ir.ui.menu,name:menu_advance_payment_term"
+msgid "Advance Payment Terms"
+msgstr "Advance Payment Terms"
+
+msgctxt "model:sale.advance_payment.condition,name:"
+msgid "Advance Payment Condition"
+msgstr ""
+
+#, fuzzy
+msgctxt "model:sale.advance_payment_term,name:"
+msgid "Advance Payment Term"
+msgstr "Advance Payment Terms"
+
+#, fuzzy
+msgctxt "model:sale.advance_payment_term.line,name:"
+msgid "Advance Payment Term Line"
+msgstr "Advance Payment Terms"
+
+#, fuzzy
+msgctxt "model:sale.advance_payment_term.line.account,name:"
+msgid "Advance Payment Term Line Account"
+msgstr "Advance Payment Terms"
diff --git a/modules/sale_advance_payment/message.xml b/modules/sale_advance_payment/message.xml
new file mode 100644
index 0000000000..94cda52563
--- /dev/null
+++ b/modules/sale_advance_payment/message.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+ Invalid formula "%(formula)s" in term line "%(term_line)s" with exception "%(exception)s".
+
+
+ To pack shipments the customer must paid the advance payment for sale "%(sale)s".
+
+
+
diff --git a/modules/sale_advance_payment/minimal_chart.xml b/modules/sale_advance_payment/minimal_chart.xml
new file mode 100644
index 0000000000..af96040b3f
--- /dev/null
+++ b/modules/sale_advance_payment/minimal_chart.xml
@@ -0,0 +1,38 @@
+
+
+
+
+
+ Unearned Revenue
+ Неотработен доход
+ Ingressos no consumits
+ Nicht verdiente Einnahmen
+ Ingresos no ganados
+ Produits constatés d'avance
+ Onverdiende inkomsten
+ Receita não recebida
+ Нетрудовые доходы
+ Nezasluženi prihodki
+
+ balance
+
+
+
+
+
+ Advance Payment
+ Авансово плащане
+ Pagament avançat
+ Vorauszahlung
+ Pago por adelantado
+ Acompte
+ Vooruitbetaling
+ Pagamento adiantado
+ Предоплата
+ Plačilo vnaprej
+
+
+
+
+
diff --git a/modules/sale_advance_payment/minimal_chart_bg.xml b/modules/sale_advance_payment/minimal_chart_bg.xml
new file mode 100644
index 0000000000..9b2908f057
--- /dev/null
+++ b/modules/sale_advance_payment/minimal_chart_bg.xml
@@ -0,0 +1,38 @@
+
+
+
+
+
+
+ Неотработен доход
+
+
+
+
+
+
+
+
+
+ balance
+
+
+
+
+
+
+ Авансово плащане
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/modules/sale_advance_payment/minimal_chart_ca.xml b/modules/sale_advance_payment/minimal_chart_ca.xml
new file mode 100644
index 0000000000..e878493edf
--- /dev/null
+++ b/modules/sale_advance_payment/minimal_chart_ca.xml
@@ -0,0 +1,38 @@
+
+
+
+
+
+
+
+ Ingressos no consumits
+
+
+
+
+
+
+
+
+ balance
+
+
+
+
+
+
+
+ Pagament avançat
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/modules/sale_advance_payment/minimal_chart_de.xml b/modules/sale_advance_payment/minimal_chart_de.xml
new file mode 100644
index 0000000000..d9ac56c9e2
--- /dev/null
+++ b/modules/sale_advance_payment/minimal_chart_de.xml
@@ -0,0 +1,38 @@
+
+
+
+
+
+
+
+
+ Nicht verdiente Einnahmen
+
+
+
+
+
+
+
+ balance
+
+
+
+
+
+
+
+
+ Vorauszahlung
+
+
+
+
+
+
+
+
+
+
+
diff --git a/modules/sale_advance_payment/minimal_chart_en.xml b/modules/sale_advance_payment/minimal_chart_en.xml
new file mode 100644
index 0000000000..682c4512bf
--- /dev/null
+++ b/modules/sale_advance_payment/minimal_chart_en.xml
@@ -0,0 +1,38 @@
+
+
+
+
+
+ Unearned Revenue
+
+
+
+
+
+
+
+
+
+
+ balance
+
+
+
+
+
+ Advance Payment
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/modules/sale_advance_payment/minimal_chart_es.xml b/modules/sale_advance_payment/minimal_chart_es.xml
new file mode 100644
index 0000000000..21cd81973d
--- /dev/null
+++ b/modules/sale_advance_payment/minimal_chart_es.xml
@@ -0,0 +1,38 @@
+
+
+
+
+
+
+
+
+
+ Ingresos no ganados
+
+
+
+
+
+
+ balance
+
+
+
+
+
+
+
+
+
+ Pago por adelantado
+
+
+
+
+
+
+
+
+
+
diff --git a/modules/sale_advance_payment/minimal_chart_fr.xml b/modules/sale_advance_payment/minimal_chart_fr.xml
new file mode 100644
index 0000000000..844e775da9
--- /dev/null
+++ b/modules/sale_advance_payment/minimal_chart_fr.xml
@@ -0,0 +1,38 @@
+
+
+
+
+
+
+
+
+
+
+ Produits constatés d'avance
+
+
+
+
+
+ balance
+
+
+
+
+
+
+
+
+
+
+ Acompte
+
+
+
+
+
+
+
+
+
diff --git a/modules/sale_advance_payment/minimal_chart_nl.xml b/modules/sale_advance_payment/minimal_chart_nl.xml
new file mode 100644
index 0000000000..536658f6d2
--- /dev/null
+++ b/modules/sale_advance_payment/minimal_chart_nl.xml
@@ -0,0 +1,38 @@
+
+
+
+
+
+
+
+
+
+
+
+ Onverdiende inkomsten
+
+
+
+
+ balance
+
+
+
+
+
+
+
+
+
+
+
+ Vooruitbetaling
+
+
+
+
+
+
+
+
diff --git a/modules/sale_advance_payment/minimal_chart_pt.xml b/modules/sale_advance_payment/minimal_chart_pt.xml
new file mode 100644
index 0000000000..92c6ff7f68
--- /dev/null
+++ b/modules/sale_advance_payment/minimal_chart_pt.xml
@@ -0,0 +1,38 @@
+
+
+
+
+
+
+
+
+
+
+
+
+ Receita não recebida
+
+
+
+ balance
+
+
+
+
+
+
+
+
+
+
+
+
+ Pagamento adiantado
+
+
+
+
+
+
+
diff --git a/modules/sale_advance_payment/minimal_chart_ru.xml b/modules/sale_advance_payment/minimal_chart_ru.xml
new file mode 100644
index 0000000000..de79c15807
--- /dev/null
+++ b/modules/sale_advance_payment/minimal_chart_ru.xml
@@ -0,0 +1,38 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Нетрудовые доходы
+
+
+ balance
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Предоплата
+
+
+
+
+
+
diff --git a/modules/sale_advance_payment/minimal_chart_sl.xml b/modules/sale_advance_payment/minimal_chart_sl.xml
new file mode 100644
index 0000000000..7aba54481c
--- /dev/null
+++ b/modules/sale_advance_payment/minimal_chart_sl.xml
@@ -0,0 +1,38 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Nezasluženi prihodki
+
+ balance
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Plačilo vnaprej
+
+
+
+
+
diff --git a/modules/sale_advance_payment/sale.py b/modules/sale_advance_payment/sale.py
new file mode 100644
index 0000000000..fde36c83ff
--- /dev/null
+++ b/modules/sale_advance_payment/sale.py
@@ -0,0 +1,486 @@
+# This file is part of Tryton. The COPYRIGHT file at the top level of
+# this repository contains the full copyright notices and license terms.
+from decimal import Decimal
+from simpleeval import simple_eval
+from itertools import chain
+
+from trytond.i18n import gettext
+from trytond.pool import Pool, PoolMeta
+from trytond.model import (
+ ModelSQL, ModelView, Workflow, DeactivableMixin, fields)
+from trytond.pyson import Eval, Bool
+from trytond.tools import decistmt
+from trytond.transaction import Transaction
+from trytond.modules.company.model import (
+ CompanyMultiValueMixin, CompanyValueMixin)
+
+from .exceptions import FormulaError
+
+
+class AdvancePaymentTerm(
+ DeactivableMixin, ModelSQL, ModelView):
+ "Advance Payment Term"
+ __name__ = 'sale.advance_payment_term'
+
+ name = fields.Char("Name", required=True, translate=True)
+ lines = fields.One2Many(
+ 'sale.advance_payment_term.line', 'advance_payment_term', "Lines")
+
+ def get_advance_payment_context(self, sale):
+ return {
+ 'total_amount': sale.total_amount,
+ 'untaxed_amount': sale.untaxed_amount,
+ }
+
+ def get_conditions(self, sale):
+ conditions = []
+ term_context = self.get_advance_payment_context(sale)
+ for line in self.lines:
+ condition = line.get_condition(sale.currency, **term_context)
+ if condition.amount > 0:
+ conditions.append(condition)
+ return conditions
+
+
+class AdvancePaymentTermLine(ModelView, ModelSQL, CompanyMultiValueMixin):
+ "Advance Payment Term Line"
+ __name__ = 'sale.advance_payment_term.line'
+ _rec_name = 'description'
+
+ advance_payment_term = fields.Many2One(
+ 'sale.advance_payment_term', "Advance Payment Term",
+ required=True, ondelete='CASCADE', select=True)
+ description = fields.Char(
+ "Description", required=True, translate=True,
+ help="Used as description for the invoice line.")
+ account = fields.MultiValue(
+ fields.Many2One('account.account', "Account", required=True,
+ domain=[
+ ('type.unearned_revenue', '=', True),
+ ],
+ help="Used for the line of advance payment invoice."))
+ accounts = fields.One2Many(
+ 'sale.advance_payment_term.line.account', 'line', "Accounts")
+ block_supply = fields.Boolean(
+ "Block Supply",
+ help="Check to prevent any supply request before advance payment.")
+ block_shipping = fields.Boolean(
+ "Block Shipping",
+ help="Check to prevent the packing of the shipment "
+ "before advance payment.")
+ invoice_delay = fields.TimeDelta(
+ "Invoice Delay",
+ help="Delta to apply on the sale date for the date of "
+ "the advance payment invoice.")
+ formula = fields.Char('Formula', required=True,
+ help="A python expression used to compute the advance payment amount "
+ "that will be evaluated with:\n"
+ "- total_amount: The total amount of the sale.\n"
+ "- untaxed_amount: The total untaxed amount of the sale.")
+
+ @classmethod
+ def __setup__(cls):
+ super().__setup__()
+ cls.__access__.add('advance_payment_term')
+
+ @fields.depends('formula', 'description')
+ def pre_validate(self, **names):
+ super(AdvancePaymentTermLine, self).pre_validate()
+ names['total_amount'] = names['untaxed_amount'] = 0
+ try:
+ if not isinstance(self.compute_amount(**names), Decimal):
+ raise Exception('The formula does not return a Decimal')
+ except Exception as exception:
+ raise FormulaError(
+ gettext('sale_advance_payment.msg_term_line_invalid_formula',
+ formula=self.formula,
+ term_line=self.description or '',
+ exception=exception)) from exception
+
+ def get_compute_amount_context(self, **names):
+ return {
+ 'names': names,
+ 'functions': {
+ 'Decimal': Decimal,
+ },
+ }
+
+ def compute_amount(self, **names):
+ context = self.get_compute_amount_context(**names)
+ return simple_eval(decistmt(self.formula), **context)
+
+ def get_condition(self, currency, **context):
+ pool = Pool()
+ AdvancePaymentCondition = pool.get('sale.advance_payment.condition')
+
+ return AdvancePaymentCondition(
+ block_supply=self.block_supply,
+ block_shipping=self.block_shipping,
+ amount=currency.round(self.compute_amount(**context)),
+ account=self.account,
+ invoice_delay=self.invoice_delay,
+ description=self.description)
+
+
+class AdvancePaymentTermLineAccount(ModelSQL, CompanyValueMixin):
+ "Advance Payment Term Line Account"
+ __name__ = 'sale.advance_payment_term.line.account'
+
+ line = fields.Many2One(
+ 'sale.advance_payment_term.line', 'Line', required=True, select=True,
+ ondelete='CASCADE')
+ account = fields.Many2One(
+ 'account.account', "Account", required=True,
+ domain=[
+ ('type.unearned_revenue', '=', True),
+ ('company', '=', Eval('company', -1)),
+ ],
+ depends=['company'])
+
+
+class AdvancePaymentCondition(ModelSQL, ModelView):
+ "Advance Payment Condition"
+ __name__ = 'sale.advance_payment.condition'
+ _rec_name = 'description'
+
+ _states = {
+ 'readonly': Eval('sale_state') != 'draft',
+ }
+ _depends = ['sale_state']
+
+ sale = fields.Many2One('sale.sale', 'Sale', required=True,
+ ondelete='CASCADE', select=True,
+ states={
+ 'readonly': ((Eval('sale_state') != 'draft')
+ & Bool(Eval('sale'))),
+ },
+ depends=['sale_state'])
+ description = fields.Char(
+ "Description", required=True, states=_states, depends=_depends)
+ amount = fields.Numeric(
+ "Amount",
+ digits=(16, Eval('_parent_sale', {}).get('currency_digits', 2)),
+ states=_states, depends=_depends)
+ account = fields.Many2One(
+ 'account.account', "Account", required=True,
+ domain=[
+ ('type.unearned_revenue', '=', True),
+ ('company', '=', Eval('sale_company')),
+ ],
+ states=_states,
+ depends=_depends + ['sale_company'])
+ block_supply = fields.Boolean(
+ "Block Supply", states=_states, depends=_depends)
+ block_shipping = fields.Boolean(
+ "Block Shipping", states=_states, depends=_depends)
+ invoice_delay = fields.TimeDelta(
+ "Invoice Delay", states=_states, depends=_depends)
+
+ invoice_lines = fields.One2Many(
+ 'account.invoice.line', 'origin', "Invoice Lines", readonly=True)
+ completed = fields.Function(fields.Boolean("Completed"), 'get_completed')
+
+ sale_state = fields.Function(fields.Selection(
+ 'get_sale_states', "Sale State"), 'on_change_with_sale_state')
+ sale_company = fields.Function(fields.Many2One(
+ 'company.company', "Company"), 'on_change_with_sale_company')
+
+ del _states
+ del _depends
+
+ @classmethod
+ def __setup__(cls):
+ super(AdvancePaymentCondition, cls).__setup__()
+ cls._order.insert(0, ('amount', 'ASC'))
+
+ @classmethod
+ def get_sale_states(cls):
+ pool = Pool()
+ Sale = pool.get('sale.sale')
+ return Sale.fields_get(['state'])['state']['selection']
+
+ @fields.depends('sale', '_parent_sale.state')
+ def on_change_with_sale_state(self, name=None):
+ if self.sale:
+ return self.sale.state
+
+ @fields.depends('sale', '_parent_sale.company')
+ def on_change_with_sale_company(self, name=None):
+ if self.sale and self.sale.company:
+ return self.sale.company.id
+
+ @classmethod
+ def copy(cls, conditions, default=None):
+ if default is None:
+ default = {}
+ else:
+ default = default.copy()
+ default.setdefault('invoice_lines', [])
+ return super(AdvancePaymentCondition, cls).copy(conditions, default)
+
+ def create_invoice(self):
+ invoice = self.sale._get_invoice_sale()
+ invoice.invoice_date = self.sale.sale_date
+ if self.invoice_delay:
+ invoice.invoice_date += self.invoice_delay
+ invoice.payment_term = None
+
+ invoice_lines = self.get_invoice_advance_payment_lines(invoice)
+ if not invoice_lines:
+ return None
+ invoice.lines = invoice_lines
+ invoice.save()
+
+ invoice.update_taxes()
+ return invoice
+
+ def get_invoice_advance_payment_lines(self, invoice):
+ pool = Pool()
+ InvoiceLine = pool.get('account.invoice.line')
+
+ advance_amount = self._get_advance_amount()
+ advance_amount += self._get_ignored_amount()
+ if advance_amount >= self.amount:
+ return []
+
+ invoice_line = InvoiceLine()
+ invoice_line.invoice = invoice
+ invoice_line.type = 'line'
+ invoice_line.quantity = 1
+ invoice_line.account = self.account
+ invoice_line.unit_price = self.amount - advance_amount
+ invoice_line.description = self.description
+ invoice_line.origin = self
+ invoice_line.company = self.sale.company
+ invoice_line.currency = self.sale.currency
+ # Set taxes
+ invoice_line.on_change_account()
+ return [invoice_line]
+
+ def _get_advance_amount(self):
+ return sum(l.amount for l in self.invoice_lines
+ if l.invoice.state != 'cancelled')
+
+ def _get_ignored_amount(self):
+ skips = {l for i in self.sale.invoices_recreated for l in i.lines}
+ return sum(l.amount for l in self.invoice_lines
+ if l.invoice.state == 'cancelled' and l not in skips)
+
+ def get_completed(self, name):
+ advance_amount = 0
+ lines_ignored = set(l for i in self.sale.invoices_ignored
+ for l in i.lines)
+ for l in self.invoice_lines:
+ if l.invoice.state == 'paid' or l in lines_ignored:
+ advance_amount += l.amount
+ return advance_amount >= self.amount
+
+
+class Sale(metaclass=PoolMeta):
+ __name__ = 'sale.sale'
+
+ advance_payment_term = fields.Many2One('sale.advance_payment_term',
+ 'Advance Payment Term',
+ ondelete='RESTRICT', states={
+ 'readonly': Eval('state') != 'draft',
+ },
+ depends=['state'])
+ advance_payment_conditions = fields.One2Many(
+ 'sale.advance_payment.condition', 'sale',
+ 'Advance Payment Conditions',
+ states={
+ 'readonly': Eval('state') != 'draft',
+ },
+ depends=['state'])
+ advance_payment_invoices = fields.Function(fields.Many2Many(
+ 'account.invoice', None, None, "Advance Payment Invoices"),
+ 'get_advance_payment_invoices',
+ searcher='search_advance_payment_invoices')
+
+ @classmethod
+ @ModelView.button
+ @Workflow.transition('quotation')
+ def quote(cls, sales):
+ pool = Pool()
+ AdvancePaymentCondition = pool.get('sale.advance_payment.condition')
+
+ super(Sale, cls).quote(sales)
+
+ AdvancePaymentCondition.delete(
+ list(chain(*(s.advance_payment_conditions for s in sales))))
+
+ for sale in sales:
+ sale.set_advance_payment_term()
+ cls.save(sales)
+
+ @classmethod
+ def copy(cls, sales, default=None):
+ if default is None:
+ default = {}
+ else:
+ default = default.copy()
+ default.setdefault('advance_payment_conditions', None)
+ return super(Sale, cls).copy(sales, default=default)
+
+ def set_advance_payment_term(self):
+ pool = Pool()
+ AdvancePaymentTerm = pool.get('sale.advance_payment_term')
+ if self.advance_payment_term:
+ if self.party and self.party.lang:
+ with Transaction().set_context(language=self.party.lang.code):
+ advance_payment_term = AdvancePaymentTerm(
+ self.advance_payment_term.id)
+ else:
+ advance_payment_term = self.advance_payment_term
+ self.advance_payment_conditions = \
+ advance_payment_term.get_conditions(self)
+
+ def get_advance_payment_invoices(self, name):
+ invoices = set()
+ for condition in self.advance_payment_conditions:
+ for invoice_line in condition.invoice_lines:
+ if invoice_line.invoice:
+ invoices.add(invoice_line.invoice.id)
+ return list(invoices)
+
+ @classmethod
+ def search_advance_payment_invoices(cls, name, clause):
+ return [('advance_payment_conditions.invoice_lines.invoice'
+ + clause[0].lstrip(name),)
+ + tuple(clause[1:])]
+
+ def get_invoice_state(self):
+ state = super(Sale, self).get_invoice_state()
+ skip_ids = set(x.id for x in self.invoices_ignored)
+ skip_ids.update(x.id for x in self.invoices_recreated)
+ invoices = [i
+ for i in self.advance_payment_invoices if i.id not in skip_ids]
+ if invoices:
+ if any(i.state == 'cancelled' for i in invoices):
+ return 'exception'
+ elif all(i.state == 'paid' for i in invoices):
+ return state
+ else:
+ return 'waiting'
+ return state
+
+ def get_recall_lines(self, invoice):
+ pool = Pool()
+ InvoiceLine = pool.get('account.invoice.line')
+
+ recall_lines = []
+ advance_lines = InvoiceLine.search([
+ ('origin', 'in', [str(c)
+ for c in self.advance_payment_conditions]),
+ ('invoice.state', '=', 'paid'),
+ ])
+ for advance_line in advance_lines:
+ line = InvoiceLine(
+ invoice=invoice,
+ company=invoice.company,
+ type=advance_line.type,
+ quantity=advance_line.quantity,
+ account=advance_line.account,
+ unit_price=-advance_line.amount,
+ description=advance_line.description,
+ origin=advance_line,
+ taxes=advance_line.taxes,
+ )
+ recall_lines.append(line)
+
+ return recall_lines
+
+ def create_invoice(self):
+ pool = Pool()
+ InvoiceLine = pool.get('account.invoice.line')
+
+ invoice = super(Sale, self).create_invoice()
+
+ if self.advance_payment_eligible():
+ if not self.advance_payment_completed:
+ for condition in self.advance_payment_conditions:
+ condition.create_invoice()
+ elif invoice is not None:
+ recall_lines = self.get_recall_lines(invoice)
+ if recall_lines:
+ for line in recall_lines:
+ line.invoice = invoice
+ InvoiceLine.save(recall_lines)
+ invoice.update_taxes()
+
+ return invoice
+
+ def advance_payment_eligible(self, shipment_type=None):
+ """
+ Returns True when the shipment_type is eligible to further processing
+ of the sale's advance payment.
+ """
+ return bool((shipment_type == 'out' or shipment_type is None)
+ and self.advance_payment_conditions)
+
+ @property
+ def advance_payment_completed(self):
+ """
+ Returns True when the advance payment process is completed
+ """
+ return (bool(self.advance_payment_conditions)
+ and all(c.completed for c in self.advance_payment_conditions))
+
+ @property
+ def supply_blocked(self):
+ for condition in self.advance_payment_conditions:
+ if not condition.block_supply:
+ continue
+ if not condition.completed:
+ return True
+ return False
+
+ @property
+ def shipping_blocked(self):
+ for condition in self.advance_payment_conditions:
+ if not condition.block_shipping:
+ continue
+ if not condition.completed:
+ return True
+ return False
+
+
+class SaleLine(metaclass=PoolMeta):
+ __name__ = 'sale.line'
+
+ def get_move(self, shipment_type):
+ move = super(SaleLine, self).get_move(shipment_type)
+ if (self.sale.advance_payment_eligible(shipment_type)
+ and self.sale.supply_blocked):
+ return None
+ return move
+
+ def get_purchase_request(self):
+ request = super(SaleLine, self).get_purchase_request()
+ if (self.sale.advance_payment_eligible()
+ and self.sale.supply_blocked):
+ return None
+ return request
+
+ def get_invoice_line(self):
+ lines = super(SaleLine, self).get_invoice_line()
+ if (self.sale.advance_payment_eligible()
+ and not self.sale.advance_payment_completed):
+ return []
+ return lines
+
+
+class HandleInvoiceException(metaclass=PoolMeta):
+ __name__ = 'sale.handle.invoice.exception'
+
+ def default_ask(self, fields):
+ default = super(HandleInvoiceException, self).default_ask(fields)
+ invoices = default['domain_invoices']
+
+ sale = self.record
+ skips = set(sale.invoices_ignored)
+ skips.update(sale.invoices_recreated)
+ for invoice in sale.advance_payment_invoices:
+ if invoice.state == 'cancelled' and invoice not in skips:
+ invoices.append(invoice.id)
+ return default
diff --git a/modules/sale_advance_payment/sale.xml b/modules/sale_advance_payment/sale.xml
new file mode 100644
index 0000000000..edc4ed4d92
--- /dev/null
+++ b/modules/sale_advance_payment/sale.xml
@@ -0,0 +1,123 @@
+
+
+
+
+
+ sale.sale
+
+ sale_form
+
+
+
+ Advance Invoices
+ account.invoice
+
+
+
+ form_relate
+ sale.sale,-1
+
+
+
+
+ sale.advance_payment.condition
+ form
+ advance_payment_condition_form
+
+
+ sale.advance_payment.condition
+ tree
+ advance_payment_condition_list
+
+
+
+ sale.advance_payment_term
+ form
+ advance_payment_term_form
+
+
+ sale.advance_payment_term
+ tree
+ advance_payment_term_list
+
+
+
+ Advance Payment Terms
+ sale.advance_payment_term
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ sale.advance_payment_term.line
+ form
+ advance_payment_term_line_form
+
+
+ sale.advance_payment_term.line
+ tree
+ advance_payment_term_line_list
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/modules/sale_advance_payment/setup.py b/modules/sale_advance_payment/setup.py
new file mode 100755
index 0000000000..eceecbbc1b
--- /dev/null
+++ b/modules/sale_advance_payment/setup.py
@@ -0,0 +1,153 @@
+#!/usr/bin/env python3
+# This file is part of Tryton. The COPYRIGHT file at the top level of
+# this repository contains the full copyright notices and license terms.
+
+import io
+import os
+import re
+from configparser import ConfigParser
+from setuptools import setup, find_packages
+
+
+def read(fname):
+ return io.open(
+ os.path.join(os.path.dirname(__file__), fname),
+ 'r', encoding='utf-8').read()
+
+
+def get_require_version(name):
+ if minor_version % 2:
+ require = '%s >= %s.%s.dev0, < %s.%s'
+ else:
+ require = '%s >= %s.%s, < %s.%s'
+ require %= (name, major_version, minor_version,
+ major_version, minor_version + 1)
+ return require
+
+
+config = ConfigParser()
+config.read_file(open(os.path.join(os.path.dirname(__file__), 'tryton.cfg')))
+info = dict(config.items('tryton'))
+for key in ('depends', 'extras_depend', 'xml'):
+ if key in info:
+ info[key] = info[key].strip().splitlines()
+version = info.get('version', '0.0.1')
+major_version, minor_version, _ = version.split('.', 2)
+major_version = int(major_version)
+minor_version = int(minor_version)
+name = 'trytond_sale_advance_payment'
+
+download_url = 'http://downloads.tryton.org/%s.%s/' % (
+ major_version, minor_version)
+if minor_version % 2:
+ version = '%s.%s.dev0' % (major_version, minor_version)
+ download_url = (
+ 'hg+http://hg.tryton.org/modules/%s#egg=%s-%s' % (
+ name[8:], name, version))
+local_version = []
+if os.environ.get('CI_JOB_ID'):
+ local_version.append(os.environ['CI_JOB_ID'])
+else:
+ for build in ['CI_BUILD_NUMBER', 'CI_JOB_NUMBER']:
+ if os.environ.get(build):
+ local_version.append(os.environ[build])
+ else:
+ local_version = []
+ break
+if local_version:
+ version += '+' + '.'.join(local_version)
+
+requires = ['simpleeval']
+for dep in info.get('depends', []):
+ if not re.match(r'(ir|res)(\W|$)', dep):
+ requires.append(get_require_version('trytond_%s' % dep))
+requires.append(get_require_version('trytond'))
+
+tests_require = [get_require_version('proteus')]
+for dep in ['sale_supply']:
+ tests_require.append(get_require_version('trytond_%s' % dep))
+dependency_links = []
+if minor_version % 2:
+ dependency_links.append(
+ 'https://trydevpi.tryton.org/?local_version='
+ + '.'.join(local_version))
+
+setup(name=name,
+ version=version,
+ description='Tryton module for sale advance payment',
+ long_description=read('README.rst'),
+ author='Tryton',
+ author_email='bugs@tryton.org',
+ url='http://www.tryton.org/',
+ download_url=download_url,
+ project_urls={
+ "Bug Tracker": 'https://bugs.tryton.org/',
+ "Documentation": 'https://docs.tryton.org/',
+ "Forum": 'https://www.tryton.org/forum',
+ "Source Code": 'https://hg.tryton.org/modules/sale_advance_payment',
+ },
+ keywords='tryton sale advance payment',
+ package_dir={'trytond.modules.sale_advance_payment': '.'},
+ packages=(
+ ['trytond.modules.sale_advance_payment']
+ + ['trytond.modules.sale_advance_payment.%s' % p
+ for p in find_packages()]
+ ),
+ package_data={
+ 'trytond.modules.sale_advance_payment': (info.get('xml', [])
+ + ['tryton.cfg', 'view/*.xml', 'locale/*.po', '*.fodt',
+ 'icons/*.svg', 'tests/*.rst']),
+ },
+ classifiers=[
+ 'Development Status :: 5 - Production/Stable',
+ 'Environment :: Plugins',
+ 'Framework :: Tryton',
+ 'Intended Audience :: Developers',
+ 'Intended Audience :: Financial and Insurance Industry',
+ 'Intended Audience :: Legal Industry',
+ 'License :: OSI Approved :: '
+ 'GNU General Public License v3 or later (GPLv3+)',
+ 'Natural Language :: Bulgarian',
+ 'Natural Language :: Catalan',
+ 'Natural Language :: Chinese (Simplified)',
+ 'Natural Language :: Czech',
+ 'Natural Language :: Dutch',
+ 'Natural Language :: English',
+ 'Natural Language :: Finnish',
+ 'Natural Language :: French',
+ 'Natural Language :: German',
+ 'Natural Language :: Hungarian',
+ 'Natural Language :: Indonesian',
+ 'Natural Language :: Italian',
+ 'Natural Language :: Persian',
+ 'Natural Language :: Polish',
+ 'Natural Language :: Portuguese (Brazilian)',
+ 'Natural Language :: Romanian',
+ 'Natural Language :: Russian',
+ 'Natural Language :: Slovenian',
+ 'Natural Language :: Spanish',
+ 'Natural Language :: Turkish',
+ 'Operating System :: OS Independent',
+ 'Programming Language :: Python :: 3',
+ 'Programming Language :: Python :: 3.6',
+ 'Programming Language :: Python :: 3.7',
+ 'Programming Language :: Python :: 3.8',
+ 'Programming Language :: Python :: 3.9',
+ 'Programming Language :: Python :: Implementation :: CPython',
+ 'Programming Language :: Python :: Implementation :: PyPy',
+ 'Topic :: Office/Business',
+ 'Topic :: Office/Business :: Financial :: Accounting',
+ ],
+ license='GPL-3',
+ python_requires='>=3.6',
+ install_requires=requires,
+ dependency_links=dependency_links,
+ zip_safe=False,
+ entry_points="""
+ [trytond.modules]
+ sale_advance_payment = trytond.modules.sale_advance_payment
+ """,
+ test_suite='tests',
+ test_loader='trytond.test_loader:Loader',
+ tests_require=tests_require,
+ )
diff --git a/modules/sale_advance_payment/stock.py b/modules/sale_advance_payment/stock.py
new file mode 100644
index 0000000000..b2d9d71465
--- /dev/null
+++ b/modules/sale_advance_payment/stock.py
@@ -0,0 +1,30 @@
+# This file is part of Tryton. The COPYRIGHT file at the top level of
+# this repository contains the full copyright notices and license terms.
+
+from trytond.i18n import gettext
+from trytond.model import ModelView, Workflow
+from trytond.pool import Pool, PoolMeta
+
+from .exceptions import ShippingBlocked
+
+
+class ShipmentOut(metaclass=PoolMeta):
+ __name__ = 'stock.shipment.out'
+
+ @classmethod
+ @ModelView.button
+ @Workflow.transition('packed')
+ def pack(cls, shipments):
+ pool = Pool()
+ Sale = pool.get('sale.sale')
+ SaleLine = pool.get('sale.line')
+
+ sales = {move.origin.sale
+ for shipment in shipments for move in shipment.moves
+ if isinstance(move.origin, SaleLine)}
+ for sale in Sale.browse([s.id for s in sales]):
+ if sale.shipping_blocked:
+ raise ShippingBlocked(
+ gettext('sale_advance_payment.msg_shipping_blocked',
+ sale=sale.rec_name))
+ super(ShipmentOut, cls).pack(shipments)
diff --git a/modules/sale_advance_payment/tests/__init__.py b/modules/sale_advance_payment/tests/__init__.py
new file mode 100644
index 0000000000..8a44009b34
--- /dev/null
+++ b/modules/sale_advance_payment/tests/__init__.py
@@ -0,0 +1,9 @@
+# This file is part of Tryton. The COPYRIGHT file at the top level of
+# this repository contains the full copyright notices and license terms.
+
+try:
+ from trytond.modules.sale_advance_payment.tests.test_sale_advance_payment import suite # noqa: E501
+except ImportError:
+ from .test_sale_advance_payment import suite
+
+__all__ = ['suite']
diff --git a/modules/sale_advance_payment/tests/scenario_advance_payment.rst b/modules/sale_advance_payment/tests/scenario_advance_payment.rst
new file mode 100644
index 0000000000..d8a072142a
--- /dev/null
+++ b/modules/sale_advance_payment/tests/scenario_advance_payment.rst
@@ -0,0 +1,406 @@
+==============================
+Sale Advance Payment Scenario
+==============================
+
+Imports::
+
+ >>> import datetime
+ >>> from decimal import Decimal
+ >>> from dateutil.relativedelta import relativedelta
+ >>> from proteus import Model, Wizard
+ >>> from trytond.tests.tools import activate_modules
+ >>> from trytond.modules.company.tests.tools import create_company, \
+ ... get_company
+ >>> from trytond.modules.account.tests.tools import create_fiscalyear, \
+ ... create_chart, get_accounts
+ >>> from trytond.modules.account_invoice.tests.tools import \
+ ... set_fiscalyear_invoice_sequences, create_payment_term
+ >>> from trytond.modules.sale_advance_payment.tests.tools import \
+ ... create_advance_payment_term, add_advance_payment_accounts
+ >>> today = datetime.date.today()
+
+Activate sale_advance_payment::
+
+ >>> config = activate_modules(['sale_advance_payment', 'sale_supply'])
+
+Create company::
+
+ >>> _ = create_company()
+ >>> company = get_company()
+
+Create fiscal years::
+
+ >>> fiscalyear = set_fiscalyear_invoice_sequences(
+ ... create_fiscalyear(company, today=today))
+ >>> fiscalyear.click('create_period')
+ >>> next_fiscalyear = set_fiscalyear_invoice_sequences(
+ ... create_fiscalyear(company, today=today + relativedelta(years=1)))
+ >>> next_fiscalyear.click('create_period')
+
+Create chart of accounts::
+
+ >>> _ = create_chart(company)
+ >>> accounts = add_advance_payment_accounts(get_accounts(company))
+ >>> revenue = accounts['revenue']
+ >>> payable = accounts['payable']
+ >>> cash = accounts['cash']
+ >>> advance_payment_account = accounts['advance_payment']
+
+ >>> Journal = Model.get('account.journal')
+ >>> PaymentMethod = Model.get('account.invoice.payment.method')
+ >>> cash_journal, = Journal.find([('type', '=', 'cash')])
+ >>> cash_journal.save()
+ >>> payment_method = PaymentMethod()
+ >>> payment_method.name = 'Cash'
+ >>> payment_method.journal = cash_journal
+ >>> payment_method.credit_account = cash
+ >>> payment_method.debit_account = cash
+ >>> payment_method.save()
+
+Create customer::
+
+ >>> Party = Model.get('party.party')
+ >>> customer = Party(name='Customer')
+ >>> customer.save()
+
+Create account category::
+
+ >>> ProductCategory = Model.get('product.category')
+ >>> account_category = ProductCategory(name="Account Category")
+ >>> account_category.accounting = True
+ >>> account_category.account_revenue = revenue
+ >>> account_category.save()
+
+Create product::
+
+ >>> ProductUom = Model.get('product.uom')
+ >>> ProductTemplate = Model.get('product.template')
+ >>> unit, = ProductUom.find([('name', '=', 'Unit')])
+
+ >>> template = ProductTemplate()
+ >>> template.name = 'Product'
+ >>> template.default_uom = unit
+ >>> template.type = 'goods'
+ >>> template.salable = True
+ >>> template.list_price = Decimal('20')
+ >>> template.account_category = account_category
+ >>> template.save()
+ >>> product, = template.products
+
+Create payment term::
+
+ >>> payment_term = create_payment_term()
+ >>> payment_term.save()
+
+Create an inventory::
+
+ >>> Inventory = Model.get('stock.inventory')
+ >>> InventoryLine = Model.get('stock.inventory.line')
+ >>> Location = Model.get('stock.location')
+ >>> storage, = Location.find([
+ ... ('code', '=', 'STO'),
+ ... ])
+ >>> inventory = Inventory()
+ >>> inventory.location = storage
+ >>> inventory_line = inventory.lines.new()
+ >>> inventory_line.product = product
+ >>> inventory_line.quantity = 100.0
+ >>> inventory_line.expected_quantity = 0.0
+ >>> inventory.click('confirm')
+ >>> inventory.state
+ 'done'
+
+Create advance payment term preventing the creation of shipment::
+
+ >>> advance_payment_term = create_advance_payment_term(
+ ... 'Advance Payment', '0.1 * total_amount', advance_payment_account,
+ ... block_supply=True)
+ >>> advance_payment_term.save()
+
+Create a normal sale::
+
+ >>> Sale = Model.get('sale.sale')
+ >>> sale = Sale()
+ >>> sale.party = customer
+ >>> sale.payment_term = payment_term
+ >>> line = sale.lines.new()
+ >>> line.product = product
+ >>> line.quantity = 1
+ >>> sale.save()
+ >>> sale.click('quote')
+ >>> sale.click('confirm')
+ >>> sale.click('process')
+ >>> sale.state
+ 'processing'
+
+As usual an invoice and a shipment has been created::
+
+ >>> invoice, = sale.invoices
+ >>> invoice_line, = invoice.lines
+ >>> invoice_line.account == revenue
+ True
+ >>> invoice.total_amount
+ Decimal('20.00')
+ >>> len(sale.shipments)
+ 1
+
+Create a sale with advance payment::
+
+ >>> sale = Sale()
+ >>> sale.party = customer
+ >>> sale.payment_term = payment_term
+ >>> line = sale.lines.new()
+ >>> line.product = product
+ >>> line.quantity = 5
+ >>> sale.advance_payment_term = advance_payment_term
+ >>> sale.click('quote')
+ >>> condition, = sale.advance_payment_conditions
+ >>> condition.amount
+ Decimal('10.00')
+ >>> sale.click('confirm')
+ >>> sale.click('process')
+ >>> sale.state
+ 'processing'
+
+The advance payment invoice has been created::
+
+ >>> invoice, = sale.advance_payment_invoices
+ >>> invoice_line, = invoice.lines
+ >>> invoice_line.account == advance_payment_account
+ True
+ >>> invoice.total_amount
+ Decimal('10.00')
+
+ >>> invoice.click('post')
+ >>> sale.reload()
+ >>> len(sale.invoices)
+ 0
+ >>> len(sale.shipments)
+ 0
+
+Let's pay the advance payment invoice::
+
+ >>> pay = Wizard('account.invoice.pay', [invoice])
+ >>> pay.form.payment_method = payment_method
+ >>> pay.execute('choice')
+
+ >>> sale.reload()
+ >>> sale.state
+ 'processing'
+ >>> len(sale.invoices)
+ 1
+ >>> len(sale.shipments)
+ 1
+
+ >>> invoice, = sale.invoices
+ >>> invoice.total_amount
+ Decimal('90.00')
+ >>> len(invoice.lines)
+ 2
+ >>> il1, il2 = sorted([il for il in invoice.lines],
+ ... key=lambda il: 1 if il.product else 0)
+ >>> il1.account == advance_payment_account
+ True
+ >>> il1.unit_price
+ Decimal('-10.00')
+ >>> il2.product == product
+ True
+ >>> il2.unit_price
+ Decimal('20.0000')
+ >>> il2.quantity
+ 5.0
+
+Create another advance payment term preventing the packing stage::
+
+ >>> advance_payment_term_no_pack = create_advance_payment_term(
+ ... 'Advance Payment (blocked packing)',
+ ... '0.1 * total_amount', advance_payment_account, block_shipping=True)
+ >>> advance_payment_term_no_pack.save()
+
+Create a sale with advance payment::
+
+ >>> sale = Sale()
+ >>> sale.party = customer
+ >>> sale.payment_term = payment_term
+ >>> line = sale.lines.new()
+ >>> line.product = product
+ >>> line.quantity = 6
+ >>> sale.advance_payment_term = advance_payment_term_no_pack
+ >>> sale.click('quote')
+ >>> condition, = sale.advance_payment_conditions
+ >>> condition.amount
+ Decimal('12.00')
+ >>> sale.click('confirm')
+ >>> sale.click('process')
+ >>> sale.state
+ 'processing'
+
+The shipment has been created::
+
+ >>> shipment, = sale.shipments
+
+Let's try to pack it::
+
+ >>> shipment.click('wait')
+ >>> shipment.click('assign_try')
+ True
+ >>> shipment.click('pick')
+ >>> shipment.click('pack') # doctest: +IGNORE_EXCEPTION_DETAIL
+ Traceback (most recent call last):
+ ...
+ ShippingBlocked: ...
+
+Let's pay the advance payment invoice::
+
+ >>> invoice, = sale.advance_payment_invoices
+ >>> invoice.click('post')
+ >>> pay = Wizard('account.invoice.pay', [invoice])
+ >>> pay.form.payment_method = payment_method
+ >>> pay.execute('choice')
+ >>> sale.reload()
+ >>> sale.state
+ 'processing'
+
+Packing the shipment is now allowed::
+
+ >>> shipment.click('pack')
+ >>> shipment.reload()
+ >>> shipment.state
+ 'packed'
+
+In case the product is to be supplied on sale
+---------------------------------------------
+
+Create the product::
+
+ >>> sos_template = ProductTemplate()
+ >>> sos_template.name = 'Supply On Sale product'
+ >>> sos_template.default_uom = unit
+ >>> sos_template.type = 'goods'
+ >>> sos_template.purchasable = True
+ >>> sos_template.salable = True
+ >>> sos_template.list_price = Decimal('10')
+ >>> sos_template.account_category = account_category
+ >>> sos_template.supply_on_sale = True
+ >>> sos_template.save()
+ >>> sos_product, = sos_template.products
+
+Sell 10 of those products::
+
+ >>> Sale = Model.get('sale.sale')
+ >>> sale = Sale()
+ >>> sale.party = customer
+ >>> sale.payment_term = payment_term
+ >>> sale_line = sale.lines.new()
+ >>> sale_line.product = sos_product
+ >>> sale_line.quantity = 10
+ >>> sale.advance_payment_term = advance_payment_term
+ >>> sale.click('quote')
+ >>> sale.click('confirm')
+ >>> sale.click('process')
+ >>> sale.state
+ 'processing'
+
+There is no purchase request created yet::
+
+ >>> PurchaseRequest = Model.get('purchase.request')
+ >>> PurchaseRequest.find()
+ []
+
+The advance payment invoice has been created, now pay it::
+
+ >>> invoice, = sale.advance_payment_invoices
+ >>> invoice.click('post')
+ >>> pay = Wizard('account.invoice.pay', [invoice])
+ >>> pay.form.payment_method = payment_method
+ >>> pay.execute('choice')
+ >>> sale.reload()
+ >>> sale.state
+ 'processing'
+
+There is now a purchase request of the desired quantity::
+
+ >>> purchase_request, = PurchaseRequest.find()
+ >>> purchase_request.quantity
+ 10.0
+
+Testing advance payment conditions exception handling
+-----------------------------------------------------
+
+Create a sale with this term::
+
+ >>> sale = Sale()
+ >>> sale.party = customer
+ >>> sale.payment_term = payment_term
+ >>> line = sale.lines.new()
+ >>> line.product = product
+ >>> line.quantity = 5
+ >>> sale.advance_payment_term = advance_payment_term
+ >>> sale.click('quote')
+ >>> condition1, = sale.advance_payment_conditions
+ >>> condition1.amount
+ Decimal('10.00')
+ >>> sale.click('confirm')
+ >>> sale.click('process')
+ >>> sale.state
+ 'processing'
+
+Let's cancel the advance invoice::
+
+ >>> inv, = sale.advance_payment_invoices
+ >>> inv.click('cancel')
+ >>> sale.reload()
+ >>> sale.invoice_state
+ 'exception'
+
+Handle the exception on the sale level, not recreating the invoice will create
+the final invoice with the remaining total::
+
+ >>> handle_exception = Wizard('sale.handle.invoice.exception', [sale])
+ >>> _ = handle_exception.form.recreate_invoices.pop()
+ >>> handle_exception.execute('handle')
+
+ >>> sale.reload()
+ >>> len(sale.advance_payment_invoices)
+ 1
+ >>> last_invoice, = sale.invoices
+ >>> last_invoice.total_amount
+ Decimal('100.00')
+
+Let's now use the same scenario but recreating the invoice instead of ignoring
+it::
+
+ >>> sale = Sale()
+ >>> sale.party = customer
+ >>> sale.payment_term = payment_term
+ >>> line = sale.lines.new()
+ >>> line.product = product
+ >>> line.quantity = 5
+ >>> sale.advance_payment_term = advance_payment_term
+ >>> sale.save()
+ >>> sale.click('quote')
+ >>> sale.click('confirm')
+ >>> sale.click('process')
+ >>> sale.state
+ 'processing'
+ >>> inv, = sale.advance_payment_invoices
+ >>> inv.click('cancel')
+ >>> sale.reload()
+ >>> sale.invoice_state
+ 'exception'
+
+ >>> handle_exception = Wizard('sale.handle.invoice.exception', [sale])
+ >>> handle_exception.execute('handle')
+ >>> sale.reload()
+ >>> _, inv_recreated = sale.advance_payment_invoices
+ >>> inv_recreated.total_amount
+ Decimal('10.00')
+
+ >>> inv_recreated.click('post')
+ >>> pay = Wizard('account.invoice.pay', [inv_recreated])
+ >>> pay.form.payment_method = payment_method
+ >>> pay.execute('choice')
+ >>> sale.reload()
+ >>> last_invoice, = sale.invoices
+ >>> last_invoice.total_amount
+ Decimal('90.00')
diff --git a/modules/sale_advance_payment/tests/test_sale_advance_payment.py b/modules/sale_advance_payment/tests/test_sale_advance_payment.py
new file mode 100644
index 0000000000..c1e4f44c1d
--- /dev/null
+++ b/modules/sale_advance_payment/tests/test_sale_advance_payment.py
@@ -0,0 +1,23 @@
+# This file is part of Tryton. The COPYRIGHT file at the top level of
+# this repository contains the full copyright notices and license terms.
+import unittest
+import doctest
+from trytond.tests.test_tryton import suite as test_suite
+from trytond.tests.test_tryton import ModuleTestCase
+from trytond.tests.test_tryton import doctest_teardown, doctest_checker
+
+
+class SaleAdvancePaymentTestCase(ModuleTestCase):
+ 'Test Sale Advance Payment module'
+ module = 'sale_advance_payment'
+
+
+def suite():
+ suite = test_suite()
+ suite.addTests(unittest.TestLoader().loadTestsFromTestCase(
+ SaleAdvancePaymentTestCase))
+ suite.addTests(doctest.DocFileSuite('scenario_advance_payment.rst',
+ tearDown=doctest_teardown, encoding='utf-8',
+ checker=doctest_checker,
+ optionflags=doctest.REPORT_ONLY_FIRST_FAILURE))
+ return suite
diff --git a/modules/sale_advance_payment/tests/tools.py b/modules/sale_advance_payment/tests/tools.py
new file mode 100644
index 0000000000..d19e74970a
--- /dev/null
+++ b/modules/sale_advance_payment/tests/tools.py
@@ -0,0 +1,39 @@
+# This file is part of Tryton. The COPYRIGHT file at the top level of
+# this repository contains the full copyright notices and license terms.
+from datetime import timedelta
+
+from proteus import Model
+
+from trytond.modules.company.tests.tools import get_company
+
+
+def create_advance_payment_term(
+ name, formula, account, block_supply=False, block_shipping=False,
+ delay=7, config=None):
+ "Create an advance payment term"
+ AdvancePaymentTerm = Model.get(
+ 'sale.advance_payment_term', config=config)
+
+ advance_payment_term = AdvancePaymentTerm(name=name)
+ line = advance_payment_term.lines.new()
+ line.description = name
+ line.account = account
+ line.block_supply = block_supply
+ line.block_shipping = block_shipping
+ line.formula = formula
+ line.invoice_delay = timedelta(days=delay)
+ return advance_payment_term
+
+
+def add_advance_payment_accounts(accounts, company=None, config=None):
+ "Add advance payment to accounts"
+ Account = Model.get('account.account', config=config)
+
+ if not company:
+ company = get_company()
+
+ accounts['advance_payment'], = Account.find([
+ ('type.unearned_revenue', '=', True),
+ ('company', '=', company.id),
+ ], limit=1)
+ return accounts
diff --git a/modules/sale_advance_payment/tox.ini b/modules/sale_advance_payment/tox.ini
new file mode 100644
index 0000000000..197496c0cb
--- /dev/null
+++ b/modules/sale_advance_payment/tox.ini
@@ -0,0 +1,15 @@
+[tox]
+envlist = {py36,py37,py38,py39}-{sqlite,postgresql},pypy3-{sqlite,postgresql}
+
+[testenv]
+commands = {envpython} setup.py test
+deps =
+ {py36,py37,py38,py39}-postgresql: psycopg2 >= 2.5
+ pypy3-postgresql: psycopg2cffi >= 2.5
+ py36-sqlite: sqlitebck
+setenv =
+ sqlite: TRYTOND_DATABASE_URI={env:SQLITE_URI:sqlite://}
+ postgresql: TRYTOND_DATABASE_URI={env:POSTGRESQL_URI:postgresql://}
+ sqlite: DB_NAME={env:SQLITE_NAME::memory:}
+ postgresql: DB_NAME={env:POSTGRESQL_NAME:test}
+install_command = pip install --pre --find-links https://trydevpi.tryton.org/?local_version={env:CI_JOB_ID:{env:CI_BUILD_NUMBER}.{env:CI_JOB_NUMBER}} {opts} {packages}
diff --git a/modules/sale_advance_payment/tryton.cfg b/modules/sale_advance_payment/tryton.cfg
new file mode 100644
index 0000000000..7100740ac1
--- /dev/null
+++ b/modules/sale_advance_payment/tryton.cfg
@@ -0,0 +1,24 @@
+[tryton]
+version=6.0.2
+depends:
+ account
+ account_invoice
+ ir
+ res
+ sale
+extras_depend:
+ sale_supply
+xml:
+ sale.xml
+ account.xml
+ minimal_chart_bg.xml
+ minimal_chart_ca.xml
+ minimal_chart_de.xml
+ minimal_chart_en.xml
+ minimal_chart_es.xml
+ minimal_chart_fr.xml
+ minimal_chart_nl.xml
+ minimal_chart_pt.xml
+ minimal_chart_ru.xml
+ minimal_chart_sl.xml
+ message.xml
diff --git a/modules/sale_advance_payment/view/account_type_form.xml b/modules/sale_advance_payment/view/account_type_form.xml
new file mode 100644
index 0000000000..b7fc4a6461
--- /dev/null
+++ b/modules/sale_advance_payment/view/account_type_form.xml
@@ -0,0 +1,9 @@
+
+
+
+
+
+
+
+
diff --git a/modules/sale_advance_payment/view/advance_payment_condition_form.xml b/modules/sale_advance_payment/view/advance_payment_condition_form.xml
new file mode 100644
index 0000000000..921fd42c33
--- /dev/null
+++ b/modules/sale_advance_payment/view/advance_payment_condition_form.xml
@@ -0,0 +1,21 @@
+
+
+
diff --git a/modules/sale_advance_payment/view/advance_payment_condition_list.xml b/modules/sale_advance_payment/view/advance_payment_condition_list.xml
new file mode 100644
index 0000000000..1e65967a17
--- /dev/null
+++ b/modules/sale_advance_payment/view/advance_payment_condition_list.xml
@@ -0,0 +1,12 @@
+
+
+
+
+
+
+
+
+
+
+
diff --git a/modules/sale_advance_payment/view/advance_payment_term_form.xml b/modules/sale_advance_payment/view/advance_payment_term_form.xml
new file mode 100644
index 0000000000..11f260d384
--- /dev/null
+++ b/modules/sale_advance_payment/view/advance_payment_term_form.xml
@@ -0,0 +1,10 @@
+
+
+
diff --git a/modules/sale_advance_payment/view/advance_payment_term_line_form.xml b/modules/sale_advance_payment/view/advance_payment_term_line_form.xml
new file mode 100644
index 0000000000..dfb55c36b8
--- /dev/null
+++ b/modules/sale_advance_payment/view/advance_payment_term_line_form.xml
@@ -0,0 +1,21 @@
+
+
+
diff --git a/modules/sale_advance_payment/view/advance_payment_term_line_list.xml b/modules/sale_advance_payment/view/advance_payment_term_line_list.xml
new file mode 100644
index 0000000000..96b9866165
--- /dev/null
+++ b/modules/sale_advance_payment/view/advance_payment_term_line_list.xml
@@ -0,0 +1,12 @@
+
+
+
+
+
+
+
+
+
+
+
diff --git a/modules/sale_advance_payment/view/advance_payment_term_list.xml b/modules/sale_advance_payment/view/advance_payment_term_list.xml
new file mode 100644
index 0000000000..b4d89538b1
--- /dev/null
+++ b/modules/sale_advance_payment/view/advance_payment_term_list.xml
@@ -0,0 +1,6 @@
+
+
+
+
+
diff --git a/modules/sale_advance_payment/view/sale_form.xml b/modules/sale_advance_payment/view/sale_form.xml
new file mode 100644
index 0000000000..06e5349b64
--- /dev/null
+++ b/modules/sale_advance_payment/view/sale_form.xml
@@ -0,0 +1,15 @@
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/modules/sale_amendment/.drone.yml b/modules/sale_amendment/.drone.yml
new file mode 100644
index 0000000000..2049d30a49
--- /dev/null
+++ b/modules/sale_amendment/.drone.yml
@@ -0,0 +1,68 @@
+clone:
+ hg:
+ image: plugins/hg
+ environment:
+ - HG_SHARE_POOL=/root/.cache/hg
+ volumes:
+ - cache:/root/.cache
+
+pipeline:
+ tox:
+ image: ${IMAGE}
+ environment:
+ - CFLAGS=-O0
+ - DB_CACHE=/cache
+ - TOX_TESTENV_PASSENV=CFLAGS DB_CACHE CI_BUILD_NUMBER CI_JOB_NUMBER CI_JOB_ID
+ - POSTGRESQL_URI=postgresql://postgres@postgresql:5432/
+ commands:
+ - echo "[extensions]" >> /root/.hgrc
+ - echo "hgext.share =" >> /root/.hgrc
+ - echo "[share]" >> /root/.hgrc
+ - echo "pool = /root/.cache/hg" >> /root/.hgrc
+ - pip install tox
+ - tox -e "${TOXENV}-${DATABASE}"
+ volumes:
+ - cache:/root/.cache
+ check_dist:
+ image: ${IMAGE}
+ commands:
+ - pip install twine
+ - python setup.py sdist
+ - twine check dist/*
+
+services:
+ postgresql:
+ image: postgres
+ environment:
+ - POSTGRES_HOST_AUTH_METHOD=trust
+ command: "-c fsync=off -c synchronous_commit=off -c full_page_writes=off"
+ when:
+ matrix:
+ DATABASE: postgresql
+
+matrix:
+ include:
+ - IMAGE: python:3.6
+ TOXENV: py36
+ DATABASE: sqlite
+ - IMAGE: python:3.6
+ TOXENV: py36
+ DATABASE: postgresql
+ - IMAGE: python:3.7
+ TOXENV: py37
+ DATABASE: sqlite
+ - IMAGE: python:3.7
+ TOXENV: py37
+ DATABASE: postgresql
+ - IMAGE: python:3.8
+ TOXENV: py38
+ DATABASE: sqlite
+ - IMAGE: python:3.8
+ TOXENV: py38
+ DATABASE: postgresql
+ - IMAGE: python:3.9
+ TOXENV: py39
+ DATABASE: sqlite
+ - IMAGE: python:3.9
+ TOXENV: py39
+ DATABASE: postgresql
diff --git a/modules/sale_amendment/.flake8 b/modules/sale_amendment/.flake8
new file mode 100644
index 0000000000..fa6b4f66d1
--- /dev/null
+++ b/modules/sale_amendment/.flake8
@@ -0,0 +1,2 @@
+[flake8]
+ignore=E123,E124,E126,E128,E741,W503
diff --git a/modules/sale_amendment/CHANGELOG b/modules/sale_amendment/CHANGELOG
new file mode 100644
index 0000000000..233940d345
--- /dev/null
+++ b/modules/sale_amendment/CHANGELOG
@@ -0,0 +1,16 @@
+Version 6.0.1 - 2022-04-15
+* Bug fixes (see mercurial logs for details)
+
+Version 6.0.0 - 2021-05-03
+* Bug fixes (see mercurial logs for details)
+* Support amend line without product
+
+Version 5.8.0 - 2020-11-02
+* Bug fixes (see mercurial logs for details)
+* Remove support for Python 3.5
+
+Version 5.6.0 - 2020-05-04
+* Bug fixes (see mercurial logs for details)
+
+Version 5.4.0 - 2019-11-04
+* Initial release
diff --git a/modules/sale_amendment/COPYRIGHT b/modules/sale_amendment/COPYRIGHT
new file mode 100644
index 0000000000..7cb98d9830
--- /dev/null
+++ b/modules/sale_amendment/COPYRIGHT
@@ -0,0 +1,15 @@
+Copyright (C) 2019-2022 B2CK
+Copyright (C) 2019-2022 Cédric Krier
+
+This program is free software: you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation, either version 3 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program. If not, see .
diff --git a/modules/sale_amendment/LICENSE b/modules/sale_amendment/LICENSE
new file mode 100644
index 0000000000..94a9ed024d
--- /dev/null
+++ b/modules/sale_amendment/LICENSE
@@ -0,0 +1,674 @@
+ GNU GENERAL PUBLIC LICENSE
+ Version 3, 29 June 2007
+
+ Copyright (C) 2007 Free Software Foundation, Inc.
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+ Preamble
+
+ The GNU General Public License is a free, copyleft license for
+software and other kinds of works.
+
+ The licenses for most software and other practical works are designed
+to take away your freedom to share and change the works. By contrast,
+the GNU General Public License is intended to guarantee your freedom to
+share and change all versions of a program--to make sure it remains free
+software for all its users. We, the Free Software Foundation, use the
+GNU General Public License for most of our software; it applies also to
+any other work released this way by its authors. You can apply it to
+your programs, too.
+
+ When we speak of free software, we are referring to freedom, not
+price. Our General Public Licenses are designed to make sure that you
+have the freedom to distribute copies of free software (and charge for
+them if you wish), that you receive source code or can get it if you
+want it, that you can change the software or use pieces of it in new
+free programs, and that you know you can do these things.
+
+ To protect your rights, we need to prevent others from denying you
+these rights or asking you to surrender the rights. Therefore, you have
+certain responsibilities if you distribute copies of the software, or if
+you modify it: responsibilities to respect the freedom of others.
+
+ For example, if you distribute copies of such a program, whether
+gratis or for a fee, you must pass on to the recipients the same
+freedoms that you received. You must make sure that they, too, receive
+or can get the source code. And you must show them these terms so they
+know their rights.
+
+ Developers that use the GNU GPL protect your rights with two steps:
+(1) assert copyright on the software, and (2) offer you this License
+giving you legal permission to copy, distribute and/or modify it.
+
+ For the developers' and authors' protection, the GPL clearly explains
+that there is no warranty for this free software. For both users' and
+authors' sake, the GPL requires that modified versions be marked as
+changed, so that their problems will not be attributed erroneously to
+authors of previous versions.
+
+ Some devices are designed to deny users access to install or run
+modified versions of the software inside them, although the manufacturer
+can do so. This is fundamentally incompatible with the aim of
+protecting users' freedom to change the software. The systematic
+pattern of such abuse occurs in the area of products for individuals to
+use, which is precisely where it is most unacceptable. Therefore, we
+have designed this version of the GPL to prohibit the practice for those
+products. If such problems arise substantially in other domains, we
+stand ready to extend this provision to those domains in future versions
+of the GPL, as needed to protect the freedom of users.
+
+ Finally, every program is threatened constantly by software patents.
+States should not allow patents to restrict development and use of
+software on general-purpose computers, but in those that do, we wish to
+avoid the special danger that patents applied to a free program could
+make it effectively proprietary. To prevent this, the GPL assures that
+patents cannot be used to render the program non-free.
+
+ The precise terms and conditions for copying, distribution and
+modification follow.
+
+ TERMS AND CONDITIONS
+
+ 0. Definitions.
+
+ "This License" refers to version 3 of the GNU General Public License.
+
+ "Copyright" also means copyright-like laws that apply to other kinds of
+works, such as semiconductor masks.
+
+ "The Program" refers to any copyrightable work licensed under this
+License. Each licensee is addressed as "you". "Licensees" and
+"recipients" may be individuals or organizations.
+
+ To "modify" a work means to copy from or adapt all or part of the work
+in a fashion requiring copyright permission, other than the making of an
+exact copy. The resulting work is called a "modified version" of the
+earlier work or a work "based on" the earlier work.
+
+ A "covered work" means either the unmodified Program or a work based
+on the Program.
+
+ To "propagate" a work means to do anything with it that, without
+permission, would make you directly or secondarily liable for
+infringement under applicable copyright law, except executing it on a
+computer or modifying a private copy. Propagation includes copying,
+distribution (with or without modification), making available to the
+public, and in some countries other activities as well.
+
+ To "convey" a work means any kind of propagation that enables other
+parties to make or receive copies. Mere interaction with a user through
+a computer network, with no transfer of a copy, is not conveying.
+
+ An interactive user interface displays "Appropriate Legal Notices"
+to the extent that it includes a convenient and prominently visible
+feature that (1) displays an appropriate copyright notice, and (2)
+tells the user that there is no warranty for the work (except to the
+extent that warranties are provided), that licensees may convey the
+work under this License, and how to view a copy of this License. If
+the interface presents a list of user commands or options, such as a
+menu, a prominent item in the list meets this criterion.
+
+ 1. Source Code.
+
+ The "source code" for a work means the preferred form of the work
+for making modifications to it. "Object code" means any non-source
+form of a work.
+
+ A "Standard Interface" means an interface that either is an official
+standard defined by a recognized standards body, or, in the case of
+interfaces specified for a particular programming language, one that
+is widely used among developers working in that language.
+
+ The "System Libraries" of an executable work include anything, other
+than the work as a whole, that (a) is included in the normal form of
+packaging a Major Component, but which is not part of that Major
+Component, and (b) serves only to enable use of the work with that
+Major Component, or to implement a Standard Interface for which an
+implementation is available to the public in source code form. A
+"Major Component", in this context, means a major essential component
+(kernel, window system, and so on) of the specific operating system
+(if any) on which the executable work runs, or a compiler used to
+produce the work, or an object code interpreter used to run it.
+
+ The "Corresponding Source" for a work in object code form means all
+the source code needed to generate, install, and (for an executable
+work) run the object code and to modify the work, including scripts to
+control those activities. However, it does not include the work's
+System Libraries, or general-purpose tools or generally available free
+programs which are used unmodified in performing those activities but
+which are not part of the work. For example, Corresponding Source
+includes interface definition files associated with source files for
+the work, and the source code for shared libraries and dynamically
+linked subprograms that the work is specifically designed to require,
+such as by intimate data communication or control flow between those
+subprograms and other parts of the work.
+
+ The Corresponding Source need not include anything that users
+can regenerate automatically from other parts of the Corresponding
+Source.
+
+ The Corresponding Source for a work in source code form is that
+same work.
+
+ 2. Basic Permissions.
+
+ All rights granted under this License are granted for the term of
+copyright on the Program, and are irrevocable provided the stated
+conditions are met. This License explicitly affirms your unlimited
+permission to run the unmodified Program. The output from running a
+covered work is covered by this License only if the output, given its
+content, constitutes a covered work. This License acknowledges your
+rights of fair use or other equivalent, as provided by copyright law.
+
+ You may make, run and propagate covered works that you do not
+convey, without conditions so long as your license otherwise remains
+in force. You may convey covered works to others for the sole purpose
+of having them make modifications exclusively for you, or provide you
+with facilities for running those works, provided that you comply with
+the terms of this License in conveying all material for which you do
+not control copyright. Those thus making or running the covered works
+for you must do so exclusively on your behalf, under your direction
+and control, on terms that prohibit them from making any copies of
+your copyrighted material outside their relationship with you.
+
+ Conveying under any other circumstances is permitted solely under
+the conditions stated below. Sublicensing is not allowed; section 10
+makes it unnecessary.
+
+ 3. Protecting Users' Legal Rights From Anti-Circumvention Law.
+
+ No covered work shall be deemed part of an effective technological
+measure under any applicable law fulfilling obligations under article
+11 of the WIPO copyright treaty adopted on 20 December 1996, or
+similar laws prohibiting or restricting circumvention of such
+measures.
+
+ When you convey a covered work, you waive any legal power to forbid
+circumvention of technological measures to the extent such circumvention
+is effected by exercising rights under this License with respect to
+the covered work, and you disclaim any intention to limit operation or
+modification of the work as a means of enforcing, against the work's
+users, your or third parties' legal rights to forbid circumvention of
+technological measures.
+
+ 4. Conveying Verbatim Copies.
+
+ You may convey verbatim copies of the Program's source code as you
+receive it, in any medium, provided that you conspicuously and
+appropriately publish on each copy an appropriate copyright notice;
+keep intact all notices stating that this License and any
+non-permissive terms added in accord with section 7 apply to the code;
+keep intact all notices of the absence of any warranty; and give all
+recipients a copy of this License along with the Program.
+
+ You may charge any price or no price for each copy that you convey,
+and you may offer support or warranty protection for a fee.
+
+ 5. Conveying Modified Source Versions.
+
+ You may convey a work based on the Program, or the modifications to
+produce it from the Program, in the form of source code under the
+terms of section 4, provided that you also meet all of these conditions:
+
+ a) The work must carry prominent notices stating that you modified
+ it, and giving a relevant date.
+
+ b) The work must carry prominent notices stating that it is
+ released under this License and any conditions added under section
+ 7. This requirement modifies the requirement in section 4 to
+ "keep intact all notices".
+
+ c) You must license the entire work, as a whole, under this
+ License to anyone who comes into possession of a copy. This
+ License will therefore apply, along with any applicable section 7
+ additional terms, to the whole of the work, and all its parts,
+ regardless of how they are packaged. This License gives no
+ permission to license the work in any other way, but it does not
+ invalidate such permission if you have separately received it.
+
+ d) If the work has interactive user interfaces, each must display
+ Appropriate Legal Notices; however, if the Program has interactive
+ interfaces that do not display Appropriate Legal Notices, your
+ work need not make them do so.
+
+ A compilation of a covered work with other separate and independent
+works, which are not by their nature extensions of the covered work,
+and which are not combined with it such as to form a larger program,
+in or on a volume of a storage or distribution medium, is called an
+"aggregate" if the compilation and its resulting copyright are not
+used to limit the access or legal rights of the compilation's users
+beyond what the individual works permit. Inclusion of a covered work
+in an aggregate does not cause this License to apply to the other
+parts of the aggregate.
+
+ 6. Conveying Non-Source Forms.
+
+ You may convey a covered work in object code form under the terms
+of sections 4 and 5, provided that you also convey the
+machine-readable Corresponding Source under the terms of this License,
+in one of these ways:
+
+ a) Convey the object code in, or embodied in, a physical product
+ (including a physical distribution medium), accompanied by the
+ Corresponding Source fixed on a durable physical medium
+ customarily used for software interchange.
+
+ b) Convey the object code in, or embodied in, a physical product
+ (including a physical distribution medium), accompanied by a
+ written offer, valid for at least three years and valid for as
+ long as you offer spare parts or customer support for that product
+ model, to give anyone who possesses the object code either (1) a
+ copy of the Corresponding Source for all the software in the
+ product that is covered by this License, on a durable physical
+ medium customarily used for software interchange, for a price no
+ more than your reasonable cost of physically performing this
+ conveying of source, or (2) access to copy the
+ Corresponding Source from a network server at no charge.
+
+ c) Convey individual copies of the object code with a copy of the
+ written offer to provide the Corresponding Source. This
+ alternative is allowed only occasionally and noncommercially, and
+ only if you received the object code with such an offer, in accord
+ with subsection 6b.
+
+ d) Convey the object code by offering access from a designated
+ place (gratis or for a charge), and offer equivalent access to the
+ Corresponding Source in the same way through the same place at no
+ further charge. You need not require recipients to copy the
+ Corresponding Source along with the object code. If the place to
+ copy the object code is a network server, the Corresponding Source
+ may be on a different server (operated by you or a third party)
+ that supports equivalent copying facilities, provided you maintain
+ clear directions next to the object code saying where to find the
+ Corresponding Source. Regardless of what server hosts the
+ Corresponding Source, you remain obligated to ensure that it is
+ available for as long as needed to satisfy these requirements.
+
+ e) Convey the object code using peer-to-peer transmission, provided
+ you inform other peers where the object code and Corresponding
+ Source of the work are being offered to the general public at no
+ charge under subsection 6d.
+
+ A separable portion of the object code, whose source code is excluded
+from the Corresponding Source as a System Library, need not be
+included in conveying the object code work.
+
+ A "User Product" is either (1) a "consumer product", which means any
+tangible personal property which is normally used for personal, family,
+or household purposes, or (2) anything designed or sold for incorporation
+into a dwelling. In determining whether a product is a consumer product,
+doubtful cases shall be resolved in favor of coverage. For a particular
+product received by a particular user, "normally used" refers to a
+typical or common use of that class of product, regardless of the status
+of the particular user or of the way in which the particular user
+actually uses, or expects or is expected to use, the product. A product
+is a consumer product regardless of whether the product has substantial
+commercial, industrial or non-consumer uses, unless such uses represent
+the only significant mode of use of the product.
+
+ "Installation Information" for a User Product means any methods,
+procedures, authorization keys, or other information required to install
+and execute modified versions of a covered work in that User Product from
+a modified version of its Corresponding Source. The information must
+suffice to ensure that the continued functioning of the modified object
+code is in no case prevented or interfered with solely because
+modification has been made.
+
+ If you convey an object code work under this section in, or with, or
+specifically for use in, a User Product, and the conveying occurs as
+part of a transaction in which the right of possession and use of the
+User Product is transferred to the recipient in perpetuity or for a
+fixed term (regardless of how the transaction is characterized), the
+Corresponding Source conveyed under this section must be accompanied
+by the Installation Information. But this requirement does not apply
+if neither you nor any third party retains the ability to install
+modified object code on the User Product (for example, the work has
+been installed in ROM).
+
+ The requirement to provide Installation Information does not include a
+requirement to continue to provide support service, warranty, or updates
+for a work that has been modified or installed by the recipient, or for
+the User Product in which it has been modified or installed. Access to a
+network may be denied when the modification itself materially and
+adversely affects the operation of the network or violates the rules and
+protocols for communication across the network.
+
+ Corresponding Source conveyed, and Installation Information provided,
+in accord with this section must be in a format that is publicly
+documented (and with an implementation available to the public in
+source code form), and must require no special password or key for
+unpacking, reading or copying.
+
+ 7. Additional Terms.
+
+ "Additional permissions" are terms that supplement the terms of this
+License by making exceptions from one or more of its conditions.
+Additional permissions that are applicable to the entire Program shall
+be treated as though they were included in this License, to the extent
+that they are valid under applicable law. If additional permissions
+apply only to part of the Program, that part may be used separately
+under those permissions, but the entire Program remains governed by
+this License without regard to the additional permissions.
+
+ When you convey a copy of a covered work, you may at your option
+remove any additional permissions from that copy, or from any part of
+it. (Additional permissions may be written to require their own
+removal in certain cases when you modify the work.) You may place
+additional permissions on material, added by you to a covered work,
+for which you have or can give appropriate copyright permission.
+
+ Notwithstanding any other provision of this License, for material you
+add to a covered work, you may (if authorized by the copyright holders of
+that material) supplement the terms of this License with terms:
+
+ a) Disclaiming warranty or limiting liability differently from the
+ terms of sections 15 and 16 of this License; or
+
+ b) Requiring preservation of specified reasonable legal notices or
+ author attributions in that material or in the Appropriate Legal
+ Notices displayed by works containing it; or
+
+ c) Prohibiting misrepresentation of the origin of that material, or
+ requiring that modified versions of such material be marked in
+ reasonable ways as different from the original version; or
+
+ d) Limiting the use for publicity purposes of names of licensors or
+ authors of the material; or
+
+ e) Declining to grant rights under trademark law for use of some
+ trade names, trademarks, or service marks; or
+
+ f) Requiring indemnification of licensors and authors of that
+ material by anyone who conveys the material (or modified versions of
+ it) with contractual assumptions of liability to the recipient, for
+ any liability that these contractual assumptions directly impose on
+ those licensors and authors.
+
+ All other non-permissive additional terms are considered "further
+restrictions" within the meaning of section 10. If the Program as you
+received it, or any part of it, contains a notice stating that it is
+governed by this License along with a term that is a further
+restriction, you may remove that term. If a license document contains
+a further restriction but permits relicensing or conveying under this
+License, you may add to a covered work material governed by the terms
+of that license document, provided that the further restriction does
+not survive such relicensing or conveying.
+
+ If you add terms to a covered work in accord with this section, you
+must place, in the relevant source files, a statement of the
+additional terms that apply to those files, or a notice indicating
+where to find the applicable terms.
+
+ Additional terms, permissive or non-permissive, may be stated in the
+form of a separately written license, or stated as exceptions;
+the above requirements apply either way.
+
+ 8. Termination.
+
+ You may not propagate or modify a covered work except as expressly
+provided under this License. Any attempt otherwise to propagate or
+modify it is void, and will automatically terminate your rights under
+this License (including any patent licenses granted under the third
+paragraph of section 11).
+
+ However, if you cease all violation of this License, then your
+license from a particular copyright holder is reinstated (a)
+provisionally, unless and until the copyright holder explicitly and
+finally terminates your license, and (b) permanently, if the copyright
+holder fails to notify you of the violation by some reasonable means
+prior to 60 days after the cessation.
+
+ Moreover, your license from a particular copyright holder is
+reinstated permanently if the copyright holder notifies you of the
+violation by some reasonable means, this is the first time you have
+received notice of violation of this License (for any work) from that
+copyright holder, and you cure the violation prior to 30 days after
+your receipt of the notice.
+
+ Termination of your rights under this section does not terminate the
+licenses of parties who have received copies or rights from you under
+this License. If your rights have been terminated and not permanently
+reinstated, you do not qualify to receive new licenses for the same
+material under section 10.
+
+ 9. Acceptance Not Required for Having Copies.
+
+ You are not required to accept this License in order to receive or
+run a copy of the Program. Ancillary propagation of a covered work
+occurring solely as a consequence of using peer-to-peer transmission
+to receive a copy likewise does not require acceptance. However,
+nothing other than this License grants you permission to propagate or
+modify any covered work. These actions infringe copyright if you do
+not accept this License. Therefore, by modifying or propagating a
+covered work, you indicate your acceptance of this License to do so.
+
+ 10. Automatic Licensing of Downstream Recipients.
+
+ Each time you convey a covered work, the recipient automatically
+receives a license from the original licensors, to run, modify and
+propagate that work, subject to this License. You are not responsible
+for enforcing compliance by third parties with this License.
+
+ An "entity transaction" is a transaction transferring control of an
+organization, or substantially all assets of one, or subdividing an
+organization, or merging organizations. If propagation of a covered
+work results from an entity transaction, each party to that
+transaction who receives a copy of the work also receives whatever
+licenses to the work the party's predecessor in interest had or could
+give under the previous paragraph, plus a right to possession of the
+Corresponding Source of the work from the predecessor in interest, if
+the predecessor has it or can get it with reasonable efforts.
+
+ You may not impose any further restrictions on the exercise of the
+rights granted or affirmed under this License. For example, you may
+not impose a license fee, royalty, or other charge for exercise of
+rights granted under this License, and you may not initiate litigation
+(including a cross-claim or counterclaim in a lawsuit) alleging that
+any patent claim is infringed by making, using, selling, offering for
+sale, or importing the Program or any portion of it.
+
+ 11. Patents.
+
+ A "contributor" is a copyright holder who authorizes use under this
+License of the Program or a work on which the Program is based. The
+work thus licensed is called the contributor's "contributor version".
+
+ A contributor's "essential patent claims" are all patent claims
+owned or controlled by the contributor, whether already acquired or
+hereafter acquired, that would be infringed by some manner, permitted
+by this License, of making, using, or selling its contributor version,
+but do not include claims that would be infringed only as a
+consequence of further modification of the contributor version. For
+purposes of this definition, "control" includes the right to grant
+patent sublicenses in a manner consistent with the requirements of
+this License.
+
+ Each contributor grants you a non-exclusive, worldwide, royalty-free
+patent license under the contributor's essential patent claims, to
+make, use, sell, offer for sale, import and otherwise run, modify and
+propagate the contents of its contributor version.
+
+ In the following three paragraphs, a "patent license" is any express
+agreement or commitment, however denominated, not to enforce a patent
+(such as an express permission to practice a patent or covenant not to
+sue for patent infringement). To "grant" such a patent license to a
+party means to make such an agreement or commitment not to enforce a
+patent against the party.
+
+ If you convey a covered work, knowingly relying on a patent license,
+and the Corresponding Source of the work is not available for anyone
+to copy, free of charge and under the terms of this License, through a
+publicly available network server or other readily accessible means,
+then you must either (1) cause the Corresponding Source to be so
+available, or (2) arrange to deprive yourself of the benefit of the
+patent license for this particular work, or (3) arrange, in a manner
+consistent with the requirements of this License, to extend the patent
+license to downstream recipients. "Knowingly relying" means you have
+actual knowledge that, but for the patent license, your conveying the
+covered work in a country, or your recipient's use of the covered work
+in a country, would infringe one or more identifiable patents in that
+country that you have reason to believe are valid.
+
+ If, pursuant to or in connection with a single transaction or
+arrangement, you convey, or propagate by procuring conveyance of, a
+covered work, and grant a patent license to some of the parties
+receiving the covered work authorizing them to use, propagate, modify
+or convey a specific copy of the covered work, then the patent license
+you grant is automatically extended to all recipients of the covered
+work and works based on it.
+
+ A patent license is "discriminatory" if it does not include within
+the scope of its coverage, prohibits the exercise of, or is
+conditioned on the non-exercise of one or more of the rights that are
+specifically granted under this License. You may not convey a covered
+work if you are a party to an arrangement with a third party that is
+in the business of distributing software, under which you make payment
+to the third party based on the extent of your activity of conveying
+the work, and under which the third party grants, to any of the
+parties who would receive the covered work from you, a discriminatory
+patent license (a) in connection with copies of the covered work
+conveyed by you (or copies made from those copies), or (b) primarily
+for and in connection with specific products or compilations that
+contain the covered work, unless you entered into that arrangement,
+or that patent license was granted, prior to 28 March 2007.
+
+ Nothing in this License shall be construed as excluding or limiting
+any implied license or other defenses to infringement that may
+otherwise be available to you under applicable patent law.
+
+ 12. No Surrender of Others' Freedom.
+
+ If conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License. If you cannot convey a
+covered work so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you may
+not convey it at all. For example, if you agree to terms that obligate you
+to collect a royalty for further conveying from those to whom you convey
+the Program, the only way you could satisfy both those terms and this
+License would be to refrain entirely from conveying the Program.
+
+ 13. Use with the GNU Affero General Public License.
+
+ Notwithstanding any other provision of this License, you have
+permission to link or combine any covered work with a work licensed
+under version 3 of the GNU Affero General Public License into a single
+combined work, and to convey the resulting work. The terms of this
+License will continue to apply to the part which is the covered work,
+but the special requirements of the GNU Affero General Public License,
+section 13, concerning interaction through a network will apply to the
+combination as such.
+
+ 14. Revised Versions of this License.
+
+ The Free Software Foundation may publish revised and/or new versions of
+the GNU General Public License from time to time. Such new versions will
+be similar in spirit to the present version, but may differ in detail to
+address new problems or concerns.
+
+ Each version is given a distinguishing version number. If the
+Program specifies that a certain numbered version of the GNU General
+Public License "or any later version" applies to it, you have the
+option of following the terms and conditions either of that numbered
+version or of any later version published by the Free Software
+Foundation. If the Program does not specify a version number of the
+GNU General Public License, you may choose any version ever published
+by the Free Software Foundation.
+
+ If the Program specifies that a proxy can decide which future
+versions of the GNU General Public License can be used, that proxy's
+public statement of acceptance of a version permanently authorizes you
+to choose that version for the Program.
+
+ Later license versions may give you additional or different
+permissions. However, no additional obligations are imposed on any
+author or copyright holder as a result of your choosing to follow a
+later version.
+
+ 15. Disclaimer of Warranty.
+
+ THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY
+APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT
+HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY
+OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO,
+THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM
+IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF
+ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
+
+ 16. Limitation of Liability.
+
+ IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS
+THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY
+GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE
+USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF
+DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD
+PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS),
+EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF
+SUCH DAMAGES.
+
+ 17. Interpretation of Sections 15 and 16.
+
+ If the disclaimer of warranty and limitation of liability provided
+above cannot be given local legal effect according to their terms,
+reviewing courts shall apply local law that most closely approximates
+an absolute waiver of all civil liability in connection with the
+Program, unless a warranty or assumption of liability accompanies a
+copy of the Program in return for a fee.
+
+ END OF TERMS AND CONDITIONS
+
+ How to Apply These Terms to Your New Programs
+
+ If you develop a new program, and you want it to be of the greatest
+possible use to the public, the best way to achieve this is to make it
+free software which everyone can redistribute and change under these terms.
+
+ To do so, attach the following notices to the program. It is safest
+to attach them to the start of each source file to most effectively
+state the exclusion of warranty; and each file should have at least
+the "copyright" line and a pointer to where the full notice is found.
+
+
+ Copyright (C)
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see .
+
+Also add information on how to contact you by electronic and paper mail.
+
+ If the program does terminal interaction, make it output a short
+notice like this when it starts in an interactive mode:
+
+ Copyright (C)
+ This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
+ This is free software, and you are welcome to redistribute it
+ under certain conditions; type `show c' for details.
+
+The hypothetical commands `show w' and `show c' should show the appropriate
+parts of the General Public License. Of course, your program's commands
+might be different; for a GUI interface, you would use an "about box".
+
+ You should also get your employer (if you work as a programmer) or school,
+if any, to sign a "copyright disclaimer" for the program, if necessary.
+For more information on this, and how to apply and follow the GNU GPL, see
+.
+
+ The GNU General Public License does not permit incorporating your program
+into proprietary programs. If your program is a subroutine library, you
+may consider it more useful to permit linking proprietary applications with
+the library. If this is what you want to do, use the GNU Lesser General
+Public License instead of this License. But first, please read
+.
diff --git a/modules/sale_amendment/MANIFEST.in b/modules/sale_amendment/MANIFEST.in
new file mode 100644
index 0000000000..e88b2348a3
--- /dev/null
+++ b/modules/sale_amendment/MANIFEST.in
@@ -0,0 +1,5 @@
+include CHANGELOG
+include COPYRIGHT
+include LICENSE
+include README.rst
+include doc/*
diff --git a/modules/sale_amendment/README.rst b/modules/sale_amendment/README.rst
new file mode 120000
index 0000000000..176d9c2695
--- /dev/null
+++ b/modules/sale_amendment/README.rst
@@ -0,0 +1 @@
+doc/index.rst
\ No newline at end of file
diff --git a/modules/sale_amendment/__init__.py b/modules/sale_amendment/__init__.py
new file mode 100644
index 0000000000..32e4882240
--- /dev/null
+++ b/modules/sale_amendment/__init__.py
@@ -0,0 +1,15 @@
+# This file is part of Tryton. The COPYRIGHT file at the top level of
+# this repository contains the full copyright notices and license terms.
+
+from trytond.pool import Pool
+from . import sale
+
+__all__ = ['register']
+
+
+def register():
+ Pool.register(
+ sale.Sale,
+ sale.Amendment,
+ sale.AmendmentLine,
+ module='sale_amendment', type_='model')
diff --git a/modules/sale_amendment/doc/index.rst b/modules/sale_amendment/doc/index.rst
new file mode 100644
index 0000000000..948305d6b5
--- /dev/null
+++ b/modules/sale_amendment/doc/index.rst
@@ -0,0 +1,28 @@
+Sale Amendment Module
+#####################
+
+The sale amendment module allows you to change sales that are being processed
+and keep track of the changes.
+An amendment is composed of action lines which can:
+
+* Recompute taxes (if the customer tax rules or product taxes have changed).
+
+* Change the payment term
+
+* Change parties and addresses
+
+* Change the warehouse
+
+* Change a sale line:
+
+ * the product (for one with the same UoM category)
+
+ * the quantity and unit of measure
+
+ * the unit price
+
+ * the description
+
+When the amendment is validated the sale is updated and given a new revision.
+Generated documents (like shipments and invoices) that are still in a draft
+state are replaced with new ones based on the new values.
diff --git a/modules/sale_amendment/exceptions.py b/modules/sale_amendment/exceptions.py
new file mode 100644
index 0000000000..0cd8a3212a
--- /dev/null
+++ b/modules/sale_amendment/exceptions.py
@@ -0,0 +1,8 @@
+# This file is part of Tryton. The COPYRIGHT file at the top level of
+# this repository contains the full copyright notices and license terms.
+
+from trytond.exceptions import UserError
+
+
+class AmendmentValidateError(UserError):
+ pass
diff --git a/modules/sale_amendment/locale/bg.po b/modules/sale_amendment/locale/bg.po
new file mode 100644
index 0000000000..18c95a56fe
--- /dev/null
+++ b/modules/sale_amendment/locale/bg.po
@@ -0,0 +1,178 @@
+#
+msgid ""
+msgstr "Content-Type: text/plain; charset=utf-8\n"
+
+msgctxt "field:sale.amendment,date:"
+msgid "Date"
+msgstr ""
+
+msgctxt "field:sale.amendment,description:"
+msgid "Description"
+msgstr ""
+
+msgctxt "field:sale.amendment,lines:"
+msgid "Lines"
+msgstr ""
+
+msgctxt "field:sale.amendment,sale:"
+msgid "Sale"
+msgstr ""
+
+msgctxt "field:sale.amendment,state:"
+msgid "State"
+msgstr ""
+
+msgctxt "field:sale.amendment.line,action:"
+msgid "Action"
+msgstr ""
+
+msgctxt "field:sale.amendment.line,amendment:"
+msgid "Amendment"
+msgstr ""
+
+msgctxt "field:sale.amendment.line,description:"
+msgid "Description"
+msgstr ""
+
+msgctxt "field:sale.amendment.line,invoice_address:"
+msgid "Invoice Address"
+msgstr ""
+
+msgctxt "field:sale.amendment.line,line:"
+msgid "Line"
+msgstr ""
+
+msgctxt "field:sale.amendment.line,party:"
+msgid "Party"
+msgstr ""
+
+msgctxt "field:sale.amendment.line,payment_term:"
+msgid "Payment Term"
+msgstr ""
+
+msgctxt "field:sale.amendment.line,product:"
+msgid "Product"
+msgstr ""
+
+msgctxt "field:sale.amendment.line,product_uom_category:"
+msgid "Product UoM Category"
+msgstr ""
+
+msgctxt "field:sale.amendment.line,quantity:"
+msgid "Quantity"
+msgstr ""
+
+msgctxt "field:sale.amendment.line,sale:"
+msgid "Sale"
+msgstr ""
+
+msgctxt "field:sale.amendment.line,shipment_address:"
+msgid "Shipment Address"
+msgstr ""
+
+msgctxt "field:sale.amendment.line,shipment_party:"
+msgid "Shipment Party"
+msgstr ""
+
+msgctxt "field:sale.amendment.line,state:"
+msgid "State"
+msgstr ""
+
+msgctxt "field:sale.amendment.line,unit:"
+msgid "Unit"
+msgstr ""
+
+msgctxt "field:sale.amendment.line,unit_digits:"
+msgid "Unit Digits"
+msgstr ""
+
+msgctxt "field:sale.amendment.line,unit_price:"
+msgid "Unit Price"
+msgstr ""
+
+msgctxt "field:sale.amendment.line,warehouse:"
+msgid "Warehouse"
+msgstr ""
+
+msgctxt "field:sale.sale,amendments:"
+msgid "Amendments"
+msgstr ""
+
+msgctxt "model:ir.action,name:act_sale_amendment_form"
+msgid "Amendments"
+msgstr ""
+
+msgctxt ""
+"model:ir.action.act_window.domain,name:act_sale_amendment_form_domain_all"
+msgid "All"
+msgstr ""
+
+msgctxt ""
+"model:ir.action.act_window.domain,name:act_sale_amendment_form_domain_draft"
+msgid "Draft"
+msgstr ""
+
+msgctxt ""
+"model:ir.action.act_window.domain,name:act_sale_amendment_form_domain_validated"
+msgid "Validated"
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_one_sale_at_time"
+msgid ""
+"You cannot validate more than one amendment at the same time for sale "
+"\"%(sale)s\"."
+msgstr ""
+
+msgctxt ""
+"model:ir.model.button,confirm:sale_amendment_validation_amendment_button"
+msgid "Are you sure you want to validate the amendments?"
+msgstr ""
+
+msgctxt ""
+"model:ir.model.button,string:sale_amendment_validation_amendment_button"
+msgid "Validate"
+msgstr ""
+
+msgctxt "model:ir.ui.menu,name:menu_sale_amendment"
+msgid "Amendments"
+msgstr ""
+
+msgctxt "model:res.group,name:group_sale_amendment"
+msgid "Sale Amendment"
+msgstr ""
+
+msgctxt "model:sale.amendment,name:"
+msgid "Sale Amendment"
+msgstr ""
+
+msgctxt "model:sale.amendment.line,name:"
+msgid "Sale Amendment Line"
+msgstr ""
+
+msgctxt "selection:sale.amendment,state:"
+msgid "Draft"
+msgstr ""
+
+msgctxt "selection:sale.amendment,state:"
+msgid "Validated"
+msgstr ""
+
+msgctxt "selection:sale.amendment.line,action:"
+msgid "Change Line"
+msgstr ""
+
+msgctxt "selection:sale.amendment.line,action:"
+msgid "Change Parties and Addresses"
+msgstr ""
+
+msgctxt "selection:sale.amendment.line,action:"
+msgid "Change Payment Term"
+msgstr ""
+
+msgctxt "selection:sale.amendment.line,action:"
+msgid "Change Warehouse"
+msgstr ""
+
+msgctxt "selection:sale.amendment.line,action:"
+msgid "Recompute Taxes"
+msgstr ""
diff --git a/modules/sale_amendment/locale/ca.po b/modules/sale_amendment/locale/ca.po
new file mode 100644
index 0000000000..1ffa66d7a7
--- /dev/null
+++ b/modules/sale_amendment/locale/ca.po
@@ -0,0 +1,180 @@
+#
+msgid ""
+msgstr "Content-Type: text/plain; charset=utf-8\n"
+
+msgctxt "field:sale.amendment,date:"
+msgid "Date"
+msgstr "Data"
+
+msgctxt "field:sale.amendment,description:"
+msgid "Description"
+msgstr "Descripció"
+
+msgctxt "field:sale.amendment,lines:"
+msgid "Lines"
+msgstr "Línies"
+
+msgctxt "field:sale.amendment,sale:"
+msgid "Sale"
+msgstr "Venda"
+
+msgctxt "field:sale.amendment,state:"
+msgid "State"
+msgstr "Estat"
+
+msgctxt "field:sale.amendment.line,action:"
+msgid "Action"
+msgstr "Acció"
+
+msgctxt "field:sale.amendment.line,amendment:"
+msgid "Amendment"
+msgstr "Correcció"
+
+msgctxt "field:sale.amendment.line,description:"
+msgid "Description"
+msgstr "Descripció"
+
+msgctxt "field:sale.amendment.line,invoice_address:"
+msgid "Invoice Address"
+msgstr "Adreça de facturació"
+
+msgctxt "field:sale.amendment.line,line:"
+msgid "Line"
+msgstr "Línia"
+
+msgctxt "field:sale.amendment.line,party:"
+msgid "Party"
+msgstr "Tercer"
+
+msgctxt "field:sale.amendment.line,payment_term:"
+msgid "Payment Term"
+msgstr "Termini de pagament"
+
+msgctxt "field:sale.amendment.line,product:"
+msgid "Product"
+msgstr "Producte"
+
+msgctxt "field:sale.amendment.line,product_uom_category:"
+msgid "Product UoM Category"
+msgstr "Categoria UdM del producte"
+
+msgctxt "field:sale.amendment.line,quantity:"
+msgid "Quantity"
+msgstr "Quantitat"
+
+msgctxt "field:sale.amendment.line,sale:"
+msgid "Sale"
+msgstr "Venda"
+
+msgctxt "field:sale.amendment.line,shipment_address:"
+msgid "Shipment Address"
+msgstr "Adreça d'enviament"
+
+msgctxt "field:sale.amendment.line,shipment_party:"
+msgid "Shipment Party"
+msgstr "Tercer de l'enviament"
+
+msgctxt "field:sale.amendment.line,state:"
+msgid "State"
+msgstr "Estat"
+
+msgctxt "field:sale.amendment.line,unit:"
+msgid "Unit"
+msgstr "Unitat"
+
+msgctxt "field:sale.amendment.line,unit_digits:"
+msgid "Unit Digits"
+msgstr "Dígits de la unitat"
+
+msgctxt "field:sale.amendment.line,unit_price:"
+msgid "Unit Price"
+msgstr "Preu unitari"
+
+msgctxt "field:sale.amendment.line,warehouse:"
+msgid "Warehouse"
+msgstr "Magatzem"
+
+msgctxt "field:sale.sale,amendments:"
+msgid "Amendments"
+msgstr "Correccions"
+
+msgctxt "model:ir.action,name:act_sale_amendment_form"
+msgid "Amendments"
+msgstr "Correccions"
+
+msgctxt ""
+"model:ir.action.act_window.domain,name:act_sale_amendment_form_domain_all"
+msgid "All"
+msgstr "Tot"
+
+msgctxt ""
+"model:ir.action.act_window.domain,name:act_sale_amendment_form_domain_draft"
+msgid "Draft"
+msgstr "Esborrany"
+
+msgctxt ""
+"model:ir.action.act_window.domain,name:act_sale_amendment_form_domain_validated"
+msgid "Validated"
+msgstr "Validada"
+
+msgctxt "model:ir.message,text:msg_one_sale_at_time"
+msgid ""
+"You cannot validate more than one amendment at the same time for sale "
+"\"%(sale)s\"."
+msgstr ""
+"No es pot validar al mateix temps més d'una correció de la mateixa venta "
+"\"%(sale)s\"."
+
+msgctxt ""
+"model:ir.model.button,confirm:sale_amendment_validation_amendment_button"
+msgid "Are you sure you want to validate the amendments?"
+msgstr "Esteu segurs que voleu validar les correccions?"
+
+msgctxt ""
+"model:ir.model.button,string:sale_amendment_validation_amendment_button"
+msgid "Validate"
+msgstr "Valida"
+
+msgctxt "model:ir.ui.menu,name:menu_sale_amendment"
+msgid "Amendments"
+msgstr "Correccions"
+
+msgctxt "model:res.group,name:group_sale_amendment"
+msgid "Sale Amendment"
+msgstr "Correcció de venta"
+
+msgctxt "model:sale.amendment,name:"
+msgid "Sale Amendment"
+msgstr "Correcció de venta"
+
+msgctxt "model:sale.amendment.line,name:"
+msgid "Sale Amendment Line"
+msgstr "Línia de correció de venta"
+
+msgctxt "selection:sale.amendment,state:"
+msgid "Draft"
+msgstr "Esborrany"
+
+msgctxt "selection:sale.amendment,state:"
+msgid "Validated"
+msgstr "Validada"
+
+msgctxt "selection:sale.amendment.line,action:"
+msgid "Change Line"
+msgstr "Canvia línia"
+
+msgctxt "selection:sale.amendment.line,action:"
+msgid "Change Parties and Addresses"
+msgstr "Canvia tercer i adreces"
+
+msgctxt "selection:sale.amendment.line,action:"
+msgid "Change Payment Term"
+msgstr "Canvia termini de pagament"
+
+msgctxt "selection:sale.amendment.line,action:"
+msgid "Change Warehouse"
+msgstr "Canvia magatzem"
+
+msgctxt "selection:sale.amendment.line,action:"
+msgid "Recompute Taxes"
+msgstr "Recalcula impostos"
diff --git a/modules/sale_amendment/locale/cs.po b/modules/sale_amendment/locale/cs.po
new file mode 100644
index 0000000000..18c95a56fe
--- /dev/null
+++ b/modules/sale_amendment/locale/cs.po
@@ -0,0 +1,178 @@
+#
+msgid ""
+msgstr "Content-Type: text/plain; charset=utf-8\n"
+
+msgctxt "field:sale.amendment,date:"
+msgid "Date"
+msgstr ""
+
+msgctxt "field:sale.amendment,description:"
+msgid "Description"
+msgstr ""
+
+msgctxt "field:sale.amendment,lines:"
+msgid "Lines"
+msgstr ""
+
+msgctxt "field:sale.amendment,sale:"
+msgid "Sale"
+msgstr ""
+
+msgctxt "field:sale.amendment,state:"
+msgid "State"
+msgstr ""
+
+msgctxt "field:sale.amendment.line,action:"
+msgid "Action"
+msgstr ""
+
+msgctxt "field:sale.amendment.line,amendment:"
+msgid "Amendment"
+msgstr ""
+
+msgctxt "field:sale.amendment.line,description:"
+msgid "Description"
+msgstr ""
+
+msgctxt "field:sale.amendment.line,invoice_address:"
+msgid "Invoice Address"
+msgstr ""
+
+msgctxt "field:sale.amendment.line,line:"
+msgid "Line"
+msgstr ""
+
+msgctxt "field:sale.amendment.line,party:"
+msgid "Party"
+msgstr ""
+
+msgctxt "field:sale.amendment.line,payment_term:"
+msgid "Payment Term"
+msgstr ""
+
+msgctxt "field:sale.amendment.line,product:"
+msgid "Product"
+msgstr ""
+
+msgctxt "field:sale.amendment.line,product_uom_category:"
+msgid "Product UoM Category"
+msgstr ""
+
+msgctxt "field:sale.amendment.line,quantity:"
+msgid "Quantity"
+msgstr ""
+
+msgctxt "field:sale.amendment.line,sale:"
+msgid "Sale"
+msgstr ""
+
+msgctxt "field:sale.amendment.line,shipment_address:"
+msgid "Shipment Address"
+msgstr ""
+
+msgctxt "field:sale.amendment.line,shipment_party:"
+msgid "Shipment Party"
+msgstr ""
+
+msgctxt "field:sale.amendment.line,state:"
+msgid "State"
+msgstr ""
+
+msgctxt "field:sale.amendment.line,unit:"
+msgid "Unit"
+msgstr ""
+
+msgctxt "field:sale.amendment.line,unit_digits:"
+msgid "Unit Digits"
+msgstr ""
+
+msgctxt "field:sale.amendment.line,unit_price:"
+msgid "Unit Price"
+msgstr ""
+
+msgctxt "field:sale.amendment.line,warehouse:"
+msgid "Warehouse"
+msgstr ""
+
+msgctxt "field:sale.sale,amendments:"
+msgid "Amendments"
+msgstr ""
+
+msgctxt "model:ir.action,name:act_sale_amendment_form"
+msgid "Amendments"
+msgstr ""
+
+msgctxt ""
+"model:ir.action.act_window.domain,name:act_sale_amendment_form_domain_all"
+msgid "All"
+msgstr ""
+
+msgctxt ""
+"model:ir.action.act_window.domain,name:act_sale_amendment_form_domain_draft"
+msgid "Draft"
+msgstr ""
+
+msgctxt ""
+"model:ir.action.act_window.domain,name:act_sale_amendment_form_domain_validated"
+msgid "Validated"
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_one_sale_at_time"
+msgid ""
+"You cannot validate more than one amendment at the same time for sale "
+"\"%(sale)s\"."
+msgstr ""
+
+msgctxt ""
+"model:ir.model.button,confirm:sale_amendment_validation_amendment_button"
+msgid "Are you sure you want to validate the amendments?"
+msgstr ""
+
+msgctxt ""
+"model:ir.model.button,string:sale_amendment_validation_amendment_button"
+msgid "Validate"
+msgstr ""
+
+msgctxt "model:ir.ui.menu,name:menu_sale_amendment"
+msgid "Amendments"
+msgstr ""
+
+msgctxt "model:res.group,name:group_sale_amendment"
+msgid "Sale Amendment"
+msgstr ""
+
+msgctxt "model:sale.amendment,name:"
+msgid "Sale Amendment"
+msgstr ""
+
+msgctxt "model:sale.amendment.line,name:"
+msgid "Sale Amendment Line"
+msgstr ""
+
+msgctxt "selection:sale.amendment,state:"
+msgid "Draft"
+msgstr ""
+
+msgctxt "selection:sale.amendment,state:"
+msgid "Validated"
+msgstr ""
+
+msgctxt "selection:sale.amendment.line,action:"
+msgid "Change Line"
+msgstr ""
+
+msgctxt "selection:sale.amendment.line,action:"
+msgid "Change Parties and Addresses"
+msgstr ""
+
+msgctxt "selection:sale.amendment.line,action:"
+msgid "Change Payment Term"
+msgstr ""
+
+msgctxt "selection:sale.amendment.line,action:"
+msgid "Change Warehouse"
+msgstr ""
+
+msgctxt "selection:sale.amendment.line,action:"
+msgid "Recompute Taxes"
+msgstr ""
diff --git a/modules/sale_amendment/locale/de.po b/modules/sale_amendment/locale/de.po
new file mode 100644
index 0000000000..ce4cb0ae93
--- /dev/null
+++ b/modules/sale_amendment/locale/de.po
@@ -0,0 +1,180 @@
+#
+msgid ""
+msgstr "Content-Type: text/plain; charset=utf-8\n"
+
+msgctxt "field:sale.amendment,date:"
+msgid "Date"
+msgstr "Datum"
+
+msgctxt "field:sale.amendment,description:"
+msgid "Description"
+msgstr "Beschreibung"
+
+msgctxt "field:sale.amendment,lines:"
+msgid "Lines"
+msgstr "Positionen"
+
+msgctxt "field:sale.amendment,sale:"
+msgid "Sale"
+msgstr "Verkauf"
+
+msgctxt "field:sale.amendment,state:"
+msgid "State"
+msgstr "Status"
+
+msgctxt "field:sale.amendment.line,action:"
+msgid "Action"
+msgstr "Aktion"
+
+msgctxt "field:sale.amendment.line,amendment:"
+msgid "Amendment"
+msgstr "Änderung"
+
+msgctxt "field:sale.amendment.line,description:"
+msgid "Description"
+msgstr "Beschreibung"
+
+msgctxt "field:sale.amendment.line,invoice_address:"
+msgid "Invoice Address"
+msgstr "Rechnungsadresse"
+
+msgctxt "field:sale.amendment.line,line:"
+msgid "Line"
+msgstr "Position"
+
+msgctxt "field:sale.amendment.line,party:"
+msgid "Party"
+msgstr "Partei"
+
+msgctxt "field:sale.amendment.line,payment_term:"
+msgid "Payment Term"
+msgstr "Zahlungsbedingung"
+
+msgctxt "field:sale.amendment.line,product:"
+msgid "Product"
+msgstr "Artikel"
+
+msgctxt "field:sale.amendment.line,product_uom_category:"
+msgid "Product UoM Category"
+msgstr "Maßeinheitenkategorie"
+
+msgctxt "field:sale.amendment.line,quantity:"
+msgid "Quantity"
+msgstr "Menge"
+
+msgctxt "field:sale.amendment.line,sale:"
+msgid "Sale"
+msgstr "Verkauf"
+
+msgctxt "field:sale.amendment.line,shipment_address:"
+msgid "Shipment Address"
+msgstr "Lieferadresse"
+
+msgctxt "field:sale.amendment.line,shipment_party:"
+msgid "Shipment Party"
+msgstr "Lieferpartei"
+
+msgctxt "field:sale.amendment.line,state:"
+msgid "State"
+msgstr "Status"
+
+msgctxt "field:sale.amendment.line,unit:"
+msgid "Unit"
+msgstr "Einheit"
+
+msgctxt "field:sale.amendment.line,unit_digits:"
+msgid "Unit Digits"
+msgstr "Nachkommastellen"
+
+msgctxt "field:sale.amendment.line,unit_price:"
+msgid "Unit Price"
+msgstr "Einzelpreis"
+
+msgctxt "field:sale.amendment.line,warehouse:"
+msgid "Warehouse"
+msgstr "Warenlager"
+
+msgctxt "field:sale.sale,amendments:"
+msgid "Amendments"
+msgstr "Änderungen"
+
+msgctxt "model:ir.action,name:act_sale_amendment_form"
+msgid "Amendments"
+msgstr "Änderungen"
+
+msgctxt ""
+"model:ir.action.act_window.domain,name:act_sale_amendment_form_domain_all"
+msgid "All"
+msgstr "Alle"
+
+msgctxt ""
+"model:ir.action.act_window.domain,name:act_sale_amendment_form_domain_draft"
+msgid "Draft"
+msgstr "Entwurf"
+
+msgctxt ""
+"model:ir.action.act_window.domain,name:act_sale_amendment_form_domain_validated"
+msgid "Validated"
+msgstr "Bestätigt"
+
+msgctxt "model:ir.message,text:msg_one_sale_at_time"
+msgid ""
+"You cannot validate more than one amendment at the same time for sale "
+"\"%(sale)s\"."
+msgstr ""
+"Es kann zum selben Zeitpunkt nicht mehr als eine Änderung für Verkauf "
+"\"%(sale)s\" bestätigt werden."
+
+msgctxt ""
+"model:ir.model.button,confirm:sale_amendment_validation_amendment_button"
+msgid "Are you sure you want to validate the amendments?"
+msgstr "Änderung tatsächlich bestätigen?"
+
+msgctxt ""
+"model:ir.model.button,string:sale_amendment_validation_amendment_button"
+msgid "Validate"
+msgstr "Bestätigen"
+
+msgctxt "model:ir.ui.menu,name:menu_sale_amendment"
+msgid "Amendments"
+msgstr "Änderungen"
+
+msgctxt "model:res.group,name:group_sale_amendment"
+msgid "Sale Amendment"
+msgstr "Verkauf Änderung"
+
+msgctxt "model:sale.amendment,name:"
+msgid "Sale Amendment"
+msgstr "Verkauf Änderung"
+
+msgctxt "model:sale.amendment.line,name:"
+msgid "Sale Amendment Line"
+msgstr "Verkauf Änderungsposition"
+
+msgctxt "selection:sale.amendment,state:"
+msgid "Draft"
+msgstr "Entwurf"
+
+msgctxt "selection:sale.amendment,state:"
+msgid "Validated"
+msgstr "Bestätigt"
+
+msgctxt "selection:sale.amendment.line,action:"
+msgid "Change Line"
+msgstr "Position ändern"
+
+msgctxt "selection:sale.amendment.line,action:"
+msgid "Change Parties and Addresses"
+msgstr "Parteien und Adressen ändern"
+
+msgctxt "selection:sale.amendment.line,action:"
+msgid "Change Payment Term"
+msgstr "Zahlungsbedingung ändern"
+
+msgctxt "selection:sale.amendment.line,action:"
+msgid "Change Warehouse"
+msgstr "Warenlager ändern"
+
+msgctxt "selection:sale.amendment.line,action:"
+msgid "Recompute Taxes"
+msgstr "Steuern neu berechnen"
diff --git a/modules/sale_amendment/locale/es.po b/modules/sale_amendment/locale/es.po
new file mode 100644
index 0000000000..6ac925ec2d
--- /dev/null
+++ b/modules/sale_amendment/locale/es.po
@@ -0,0 +1,180 @@
+#
+msgid ""
+msgstr "Content-Type: text/plain; charset=utf-8\n"
+
+msgctxt "field:sale.amendment,date:"
+msgid "Date"
+msgstr "Fecha"
+
+msgctxt "field:sale.amendment,description:"
+msgid "Description"
+msgstr "Descripción"
+
+msgctxt "field:sale.amendment,lines:"
+msgid "Lines"
+msgstr "Líneas"
+
+msgctxt "field:sale.amendment,sale:"
+msgid "Sale"
+msgstr "Venta"
+
+msgctxt "field:sale.amendment,state:"
+msgid "State"
+msgstr "Estado"
+
+msgctxt "field:sale.amendment.line,action:"
+msgid "Action"
+msgstr "Acción"
+
+msgctxt "field:sale.amendment.line,amendment:"
+msgid "Amendment"
+msgstr "Corrección"
+
+msgctxt "field:sale.amendment.line,description:"
+msgid "Description"
+msgstr "Descripción"
+
+msgctxt "field:sale.amendment.line,invoice_address:"
+msgid "Invoice Address"
+msgstr "Dirección de facturación"
+
+msgctxt "field:sale.amendment.line,line:"
+msgid "Line"
+msgstr "Línea"
+
+msgctxt "field:sale.amendment.line,party:"
+msgid "Party"
+msgstr "Tercero"
+
+msgctxt "field:sale.amendment.line,payment_term:"
+msgid "Payment Term"
+msgstr "Plazo de pago"
+
+msgctxt "field:sale.amendment.line,product:"
+msgid "Product"
+msgstr "Producto"
+
+msgctxt "field:sale.amendment.line,product_uom_category:"
+msgid "Product UoM Category"
+msgstr "Categoría UdM del producto"
+
+msgctxt "field:sale.amendment.line,quantity:"
+msgid "Quantity"
+msgstr "Cantidad"
+
+msgctxt "field:sale.amendment.line,sale:"
+msgid "Sale"
+msgstr "Venta"
+
+msgctxt "field:sale.amendment.line,shipment_address:"
+msgid "Shipment Address"
+msgstr "Dirección de envío"
+
+msgctxt "field:sale.amendment.line,shipment_party:"
+msgid "Shipment Party"
+msgstr "Tercero del envío"
+
+msgctxt "field:sale.amendment.line,state:"
+msgid "State"
+msgstr "Estado"
+
+msgctxt "field:sale.amendment.line,unit:"
+msgid "Unit"
+msgstr "Unidad"
+
+msgctxt "field:sale.amendment.line,unit_digits:"
+msgid "Unit Digits"
+msgstr "Dígitos de la unidad"
+
+msgctxt "field:sale.amendment.line,unit_price:"
+msgid "Unit Price"
+msgstr "Precio unitario"
+
+msgctxt "field:sale.amendment.line,warehouse:"
+msgid "Warehouse"
+msgstr "Almacén"
+
+msgctxt "field:sale.sale,amendments:"
+msgid "Amendments"
+msgstr "Correcciones"
+
+msgctxt "model:ir.action,name:act_sale_amendment_form"
+msgid "Amendments"
+msgstr "Correcciones"
+
+msgctxt ""
+"model:ir.action.act_window.domain,name:act_sale_amendment_form_domain_all"
+msgid "All"
+msgstr "Todo"
+
+msgctxt ""
+"model:ir.action.act_window.domain,name:act_sale_amendment_form_domain_draft"
+msgid "Draft"
+msgstr "Borrador"
+
+msgctxt ""
+"model:ir.action.act_window.domain,name:act_sale_amendment_form_domain_validated"
+msgid "Validated"
+msgstr "Validada"
+
+msgctxt "model:ir.message,text:msg_one_sale_at_time"
+msgid ""
+"You cannot validate more than one amendment at the same time for sale "
+"\"%(sale)s\"."
+msgstr ""
+"No se puede validar al mismo teimpo mas de una corrección para la misma "
+"venta \"%(sale)s\"."
+
+msgctxt ""
+"model:ir.model.button,confirm:sale_amendment_validation_amendment_button"
+msgid "Are you sure you want to validate the amendments?"
+msgstr "Estas seguro que quieres validar las correciones?"
+
+msgctxt ""
+"model:ir.model.button,string:sale_amendment_validation_amendment_button"
+msgid "Validate"
+msgstr "Validar"
+
+msgctxt "model:ir.ui.menu,name:menu_sale_amendment"
+msgid "Amendments"
+msgstr "Correcciones"
+
+msgctxt "model:res.group,name:group_sale_amendment"
+msgid "Sale Amendment"
+msgstr "Correción de venta"
+
+msgctxt "model:sale.amendment,name:"
+msgid "Sale Amendment"
+msgstr "Correción de venta"
+
+msgctxt "model:sale.amendment.line,name:"
+msgid "Sale Amendment Line"
+msgstr "Linea de correción de venta"
+
+msgctxt "selection:sale.amendment,state:"
+msgid "Draft"
+msgstr "Borrador"
+
+msgctxt "selection:sale.amendment,state:"
+msgid "Validated"
+msgstr "Validada"
+
+msgctxt "selection:sale.amendment.line,action:"
+msgid "Change Line"
+msgstr "Modificar línea"
+
+msgctxt "selection:sale.amendment.line,action:"
+msgid "Change Parties and Addresses"
+msgstr "Modificar terceros y direcciones"
+
+msgctxt "selection:sale.amendment.line,action:"
+msgid "Change Payment Term"
+msgstr "Modificar plazo de pago"
+
+msgctxt "selection:sale.amendment.line,action:"
+msgid "Change Warehouse"
+msgstr "Modificar almacén"
+
+msgctxt "selection:sale.amendment.line,action:"
+msgid "Recompute Taxes"
+msgstr "Recalcular impuestos"
diff --git a/modules/sale_amendment/locale/es_419.po b/modules/sale_amendment/locale/es_419.po
new file mode 100644
index 0000000000..18c95a56fe
--- /dev/null
+++ b/modules/sale_amendment/locale/es_419.po
@@ -0,0 +1,178 @@
+#
+msgid ""
+msgstr "Content-Type: text/plain; charset=utf-8\n"
+
+msgctxt "field:sale.amendment,date:"
+msgid "Date"
+msgstr ""
+
+msgctxt "field:sale.amendment,description:"
+msgid "Description"
+msgstr ""
+
+msgctxt "field:sale.amendment,lines:"
+msgid "Lines"
+msgstr ""
+
+msgctxt "field:sale.amendment,sale:"
+msgid "Sale"
+msgstr ""
+
+msgctxt "field:sale.amendment,state:"
+msgid "State"
+msgstr ""
+
+msgctxt "field:sale.amendment.line,action:"
+msgid "Action"
+msgstr ""
+
+msgctxt "field:sale.amendment.line,amendment:"
+msgid "Amendment"
+msgstr ""
+
+msgctxt "field:sale.amendment.line,description:"
+msgid "Description"
+msgstr ""
+
+msgctxt "field:sale.amendment.line,invoice_address:"
+msgid "Invoice Address"
+msgstr ""
+
+msgctxt "field:sale.amendment.line,line:"
+msgid "Line"
+msgstr ""
+
+msgctxt "field:sale.amendment.line,party:"
+msgid "Party"
+msgstr ""
+
+msgctxt "field:sale.amendment.line,payment_term:"
+msgid "Payment Term"
+msgstr ""
+
+msgctxt "field:sale.amendment.line,product:"
+msgid "Product"
+msgstr ""
+
+msgctxt "field:sale.amendment.line,product_uom_category:"
+msgid "Product UoM Category"
+msgstr ""
+
+msgctxt "field:sale.amendment.line,quantity:"
+msgid "Quantity"
+msgstr ""
+
+msgctxt "field:sale.amendment.line,sale:"
+msgid "Sale"
+msgstr ""
+
+msgctxt "field:sale.amendment.line,shipment_address:"
+msgid "Shipment Address"
+msgstr ""
+
+msgctxt "field:sale.amendment.line,shipment_party:"
+msgid "Shipment Party"
+msgstr ""
+
+msgctxt "field:sale.amendment.line,state:"
+msgid "State"
+msgstr ""
+
+msgctxt "field:sale.amendment.line,unit:"
+msgid "Unit"
+msgstr ""
+
+msgctxt "field:sale.amendment.line,unit_digits:"
+msgid "Unit Digits"
+msgstr ""
+
+msgctxt "field:sale.amendment.line,unit_price:"
+msgid "Unit Price"
+msgstr ""
+
+msgctxt "field:sale.amendment.line,warehouse:"
+msgid "Warehouse"
+msgstr ""
+
+msgctxt "field:sale.sale,amendments:"
+msgid "Amendments"
+msgstr ""
+
+msgctxt "model:ir.action,name:act_sale_amendment_form"
+msgid "Amendments"
+msgstr ""
+
+msgctxt ""
+"model:ir.action.act_window.domain,name:act_sale_amendment_form_domain_all"
+msgid "All"
+msgstr ""
+
+msgctxt ""
+"model:ir.action.act_window.domain,name:act_sale_amendment_form_domain_draft"
+msgid "Draft"
+msgstr ""
+
+msgctxt ""
+"model:ir.action.act_window.domain,name:act_sale_amendment_form_domain_validated"
+msgid "Validated"
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_one_sale_at_time"
+msgid ""
+"You cannot validate more than one amendment at the same time for sale "
+"\"%(sale)s\"."
+msgstr ""
+
+msgctxt ""
+"model:ir.model.button,confirm:sale_amendment_validation_amendment_button"
+msgid "Are you sure you want to validate the amendments?"
+msgstr ""
+
+msgctxt ""
+"model:ir.model.button,string:sale_amendment_validation_amendment_button"
+msgid "Validate"
+msgstr ""
+
+msgctxt "model:ir.ui.menu,name:menu_sale_amendment"
+msgid "Amendments"
+msgstr ""
+
+msgctxt "model:res.group,name:group_sale_amendment"
+msgid "Sale Amendment"
+msgstr ""
+
+msgctxt "model:sale.amendment,name:"
+msgid "Sale Amendment"
+msgstr ""
+
+msgctxt "model:sale.amendment.line,name:"
+msgid "Sale Amendment Line"
+msgstr ""
+
+msgctxt "selection:sale.amendment,state:"
+msgid "Draft"
+msgstr ""
+
+msgctxt "selection:sale.amendment,state:"
+msgid "Validated"
+msgstr ""
+
+msgctxt "selection:sale.amendment.line,action:"
+msgid "Change Line"
+msgstr ""
+
+msgctxt "selection:sale.amendment.line,action:"
+msgid "Change Parties and Addresses"
+msgstr ""
+
+msgctxt "selection:sale.amendment.line,action:"
+msgid "Change Payment Term"
+msgstr ""
+
+msgctxt "selection:sale.amendment.line,action:"
+msgid "Change Warehouse"
+msgstr ""
+
+msgctxt "selection:sale.amendment.line,action:"
+msgid "Recompute Taxes"
+msgstr ""
diff --git a/modules/sale_amendment/locale/et.po b/modules/sale_amendment/locale/et.po
new file mode 100644
index 0000000000..18c95a56fe
--- /dev/null
+++ b/modules/sale_amendment/locale/et.po
@@ -0,0 +1,178 @@
+#
+msgid ""
+msgstr "Content-Type: text/plain; charset=utf-8\n"
+
+msgctxt "field:sale.amendment,date:"
+msgid "Date"
+msgstr ""
+
+msgctxt "field:sale.amendment,description:"
+msgid "Description"
+msgstr ""
+
+msgctxt "field:sale.amendment,lines:"
+msgid "Lines"
+msgstr ""
+
+msgctxt "field:sale.amendment,sale:"
+msgid "Sale"
+msgstr ""
+
+msgctxt "field:sale.amendment,state:"
+msgid "State"
+msgstr ""
+
+msgctxt "field:sale.amendment.line,action:"
+msgid "Action"
+msgstr ""
+
+msgctxt "field:sale.amendment.line,amendment:"
+msgid "Amendment"
+msgstr ""
+
+msgctxt "field:sale.amendment.line,description:"
+msgid "Description"
+msgstr ""
+
+msgctxt "field:sale.amendment.line,invoice_address:"
+msgid "Invoice Address"
+msgstr ""
+
+msgctxt "field:sale.amendment.line,line:"
+msgid "Line"
+msgstr ""
+
+msgctxt "field:sale.amendment.line,party:"
+msgid "Party"
+msgstr ""
+
+msgctxt "field:sale.amendment.line,payment_term:"
+msgid "Payment Term"
+msgstr ""
+
+msgctxt "field:sale.amendment.line,product:"
+msgid "Product"
+msgstr ""
+
+msgctxt "field:sale.amendment.line,product_uom_category:"
+msgid "Product UoM Category"
+msgstr ""
+
+msgctxt "field:sale.amendment.line,quantity:"
+msgid "Quantity"
+msgstr ""
+
+msgctxt "field:sale.amendment.line,sale:"
+msgid "Sale"
+msgstr ""
+
+msgctxt "field:sale.amendment.line,shipment_address:"
+msgid "Shipment Address"
+msgstr ""
+
+msgctxt "field:sale.amendment.line,shipment_party:"
+msgid "Shipment Party"
+msgstr ""
+
+msgctxt "field:sale.amendment.line,state:"
+msgid "State"
+msgstr ""
+
+msgctxt "field:sale.amendment.line,unit:"
+msgid "Unit"
+msgstr ""
+
+msgctxt "field:sale.amendment.line,unit_digits:"
+msgid "Unit Digits"
+msgstr ""
+
+msgctxt "field:sale.amendment.line,unit_price:"
+msgid "Unit Price"
+msgstr ""
+
+msgctxt "field:sale.amendment.line,warehouse:"
+msgid "Warehouse"
+msgstr ""
+
+msgctxt "field:sale.sale,amendments:"
+msgid "Amendments"
+msgstr ""
+
+msgctxt "model:ir.action,name:act_sale_amendment_form"
+msgid "Amendments"
+msgstr ""
+
+msgctxt ""
+"model:ir.action.act_window.domain,name:act_sale_amendment_form_domain_all"
+msgid "All"
+msgstr ""
+
+msgctxt ""
+"model:ir.action.act_window.domain,name:act_sale_amendment_form_domain_draft"
+msgid "Draft"
+msgstr ""
+
+msgctxt ""
+"model:ir.action.act_window.domain,name:act_sale_amendment_form_domain_validated"
+msgid "Validated"
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_one_sale_at_time"
+msgid ""
+"You cannot validate more than one amendment at the same time for sale "
+"\"%(sale)s\"."
+msgstr ""
+
+msgctxt ""
+"model:ir.model.button,confirm:sale_amendment_validation_amendment_button"
+msgid "Are you sure you want to validate the amendments?"
+msgstr ""
+
+msgctxt ""
+"model:ir.model.button,string:sale_amendment_validation_amendment_button"
+msgid "Validate"
+msgstr ""
+
+msgctxt "model:ir.ui.menu,name:menu_sale_amendment"
+msgid "Amendments"
+msgstr ""
+
+msgctxt "model:res.group,name:group_sale_amendment"
+msgid "Sale Amendment"
+msgstr ""
+
+msgctxt "model:sale.amendment,name:"
+msgid "Sale Amendment"
+msgstr ""
+
+msgctxt "model:sale.amendment.line,name:"
+msgid "Sale Amendment Line"
+msgstr ""
+
+msgctxt "selection:sale.amendment,state:"
+msgid "Draft"
+msgstr ""
+
+msgctxt "selection:sale.amendment,state:"
+msgid "Validated"
+msgstr ""
+
+msgctxt "selection:sale.amendment.line,action:"
+msgid "Change Line"
+msgstr ""
+
+msgctxt "selection:sale.amendment.line,action:"
+msgid "Change Parties and Addresses"
+msgstr ""
+
+msgctxt "selection:sale.amendment.line,action:"
+msgid "Change Payment Term"
+msgstr ""
+
+msgctxt "selection:sale.amendment.line,action:"
+msgid "Change Warehouse"
+msgstr ""
+
+msgctxt "selection:sale.amendment.line,action:"
+msgid "Recompute Taxes"
+msgstr ""
diff --git a/modules/sale_amendment/locale/fa.po b/modules/sale_amendment/locale/fa.po
new file mode 100644
index 0000000000..18c95a56fe
--- /dev/null
+++ b/modules/sale_amendment/locale/fa.po
@@ -0,0 +1,178 @@
+#
+msgid ""
+msgstr "Content-Type: text/plain; charset=utf-8\n"
+
+msgctxt "field:sale.amendment,date:"
+msgid "Date"
+msgstr ""
+
+msgctxt "field:sale.amendment,description:"
+msgid "Description"
+msgstr ""
+
+msgctxt "field:sale.amendment,lines:"
+msgid "Lines"
+msgstr ""
+
+msgctxt "field:sale.amendment,sale:"
+msgid "Sale"
+msgstr ""
+
+msgctxt "field:sale.amendment,state:"
+msgid "State"
+msgstr ""
+
+msgctxt "field:sale.amendment.line,action:"
+msgid "Action"
+msgstr ""
+
+msgctxt "field:sale.amendment.line,amendment:"
+msgid "Amendment"
+msgstr ""
+
+msgctxt "field:sale.amendment.line,description:"
+msgid "Description"
+msgstr ""
+
+msgctxt "field:sale.amendment.line,invoice_address:"
+msgid "Invoice Address"
+msgstr ""
+
+msgctxt "field:sale.amendment.line,line:"
+msgid "Line"
+msgstr ""
+
+msgctxt "field:sale.amendment.line,party:"
+msgid "Party"
+msgstr ""
+
+msgctxt "field:sale.amendment.line,payment_term:"
+msgid "Payment Term"
+msgstr ""
+
+msgctxt "field:sale.amendment.line,product:"
+msgid "Product"
+msgstr ""
+
+msgctxt "field:sale.amendment.line,product_uom_category:"
+msgid "Product UoM Category"
+msgstr ""
+
+msgctxt "field:sale.amendment.line,quantity:"
+msgid "Quantity"
+msgstr ""
+
+msgctxt "field:sale.amendment.line,sale:"
+msgid "Sale"
+msgstr ""
+
+msgctxt "field:sale.amendment.line,shipment_address:"
+msgid "Shipment Address"
+msgstr ""
+
+msgctxt "field:sale.amendment.line,shipment_party:"
+msgid "Shipment Party"
+msgstr ""
+
+msgctxt "field:sale.amendment.line,state:"
+msgid "State"
+msgstr ""
+
+msgctxt "field:sale.amendment.line,unit:"
+msgid "Unit"
+msgstr ""
+
+msgctxt "field:sale.amendment.line,unit_digits:"
+msgid "Unit Digits"
+msgstr ""
+
+msgctxt "field:sale.amendment.line,unit_price:"
+msgid "Unit Price"
+msgstr ""
+
+msgctxt "field:sale.amendment.line,warehouse:"
+msgid "Warehouse"
+msgstr ""
+
+msgctxt "field:sale.sale,amendments:"
+msgid "Amendments"
+msgstr ""
+
+msgctxt "model:ir.action,name:act_sale_amendment_form"
+msgid "Amendments"
+msgstr ""
+
+msgctxt ""
+"model:ir.action.act_window.domain,name:act_sale_amendment_form_domain_all"
+msgid "All"
+msgstr ""
+
+msgctxt ""
+"model:ir.action.act_window.domain,name:act_sale_amendment_form_domain_draft"
+msgid "Draft"
+msgstr ""
+
+msgctxt ""
+"model:ir.action.act_window.domain,name:act_sale_amendment_form_domain_validated"
+msgid "Validated"
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_one_sale_at_time"
+msgid ""
+"You cannot validate more than one amendment at the same time for sale "
+"\"%(sale)s\"."
+msgstr ""
+
+msgctxt ""
+"model:ir.model.button,confirm:sale_amendment_validation_amendment_button"
+msgid "Are you sure you want to validate the amendments?"
+msgstr ""
+
+msgctxt ""
+"model:ir.model.button,string:sale_amendment_validation_amendment_button"
+msgid "Validate"
+msgstr ""
+
+msgctxt "model:ir.ui.menu,name:menu_sale_amendment"
+msgid "Amendments"
+msgstr ""
+
+msgctxt "model:res.group,name:group_sale_amendment"
+msgid "Sale Amendment"
+msgstr ""
+
+msgctxt "model:sale.amendment,name:"
+msgid "Sale Amendment"
+msgstr ""
+
+msgctxt "model:sale.amendment.line,name:"
+msgid "Sale Amendment Line"
+msgstr ""
+
+msgctxt "selection:sale.amendment,state:"
+msgid "Draft"
+msgstr ""
+
+msgctxt "selection:sale.amendment,state:"
+msgid "Validated"
+msgstr ""
+
+msgctxt "selection:sale.amendment.line,action:"
+msgid "Change Line"
+msgstr ""
+
+msgctxt "selection:sale.amendment.line,action:"
+msgid "Change Parties and Addresses"
+msgstr ""
+
+msgctxt "selection:sale.amendment.line,action:"
+msgid "Change Payment Term"
+msgstr ""
+
+msgctxt "selection:sale.amendment.line,action:"
+msgid "Change Warehouse"
+msgstr ""
+
+msgctxt "selection:sale.amendment.line,action:"
+msgid "Recompute Taxes"
+msgstr ""
diff --git a/modules/sale_amendment/locale/fi.po b/modules/sale_amendment/locale/fi.po
new file mode 100644
index 0000000000..18c95a56fe
--- /dev/null
+++ b/modules/sale_amendment/locale/fi.po
@@ -0,0 +1,178 @@
+#
+msgid ""
+msgstr "Content-Type: text/plain; charset=utf-8\n"
+
+msgctxt "field:sale.amendment,date:"
+msgid "Date"
+msgstr ""
+
+msgctxt "field:sale.amendment,description:"
+msgid "Description"
+msgstr ""
+
+msgctxt "field:sale.amendment,lines:"
+msgid "Lines"
+msgstr ""
+
+msgctxt "field:sale.amendment,sale:"
+msgid "Sale"
+msgstr ""
+
+msgctxt "field:sale.amendment,state:"
+msgid "State"
+msgstr ""
+
+msgctxt "field:sale.amendment.line,action:"
+msgid "Action"
+msgstr ""
+
+msgctxt "field:sale.amendment.line,amendment:"
+msgid "Amendment"
+msgstr ""
+
+msgctxt "field:sale.amendment.line,description:"
+msgid "Description"
+msgstr ""
+
+msgctxt "field:sale.amendment.line,invoice_address:"
+msgid "Invoice Address"
+msgstr ""
+
+msgctxt "field:sale.amendment.line,line:"
+msgid "Line"
+msgstr ""
+
+msgctxt "field:sale.amendment.line,party:"
+msgid "Party"
+msgstr ""
+
+msgctxt "field:sale.amendment.line,payment_term:"
+msgid "Payment Term"
+msgstr ""
+
+msgctxt "field:sale.amendment.line,product:"
+msgid "Product"
+msgstr ""
+
+msgctxt "field:sale.amendment.line,product_uom_category:"
+msgid "Product UoM Category"
+msgstr ""
+
+msgctxt "field:sale.amendment.line,quantity:"
+msgid "Quantity"
+msgstr ""
+
+msgctxt "field:sale.amendment.line,sale:"
+msgid "Sale"
+msgstr ""
+
+msgctxt "field:sale.amendment.line,shipment_address:"
+msgid "Shipment Address"
+msgstr ""
+
+msgctxt "field:sale.amendment.line,shipment_party:"
+msgid "Shipment Party"
+msgstr ""
+
+msgctxt "field:sale.amendment.line,state:"
+msgid "State"
+msgstr ""
+
+msgctxt "field:sale.amendment.line,unit:"
+msgid "Unit"
+msgstr ""
+
+msgctxt "field:sale.amendment.line,unit_digits:"
+msgid "Unit Digits"
+msgstr ""
+
+msgctxt "field:sale.amendment.line,unit_price:"
+msgid "Unit Price"
+msgstr ""
+
+msgctxt "field:sale.amendment.line,warehouse:"
+msgid "Warehouse"
+msgstr ""
+
+msgctxt "field:sale.sale,amendments:"
+msgid "Amendments"
+msgstr ""
+
+msgctxt "model:ir.action,name:act_sale_amendment_form"
+msgid "Amendments"
+msgstr ""
+
+msgctxt ""
+"model:ir.action.act_window.domain,name:act_sale_amendment_form_domain_all"
+msgid "All"
+msgstr ""
+
+msgctxt ""
+"model:ir.action.act_window.domain,name:act_sale_amendment_form_domain_draft"
+msgid "Draft"
+msgstr ""
+
+msgctxt ""
+"model:ir.action.act_window.domain,name:act_sale_amendment_form_domain_validated"
+msgid "Validated"
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_one_sale_at_time"
+msgid ""
+"You cannot validate more than one amendment at the same time for sale "
+"\"%(sale)s\"."
+msgstr ""
+
+msgctxt ""
+"model:ir.model.button,confirm:sale_amendment_validation_amendment_button"
+msgid "Are you sure you want to validate the amendments?"
+msgstr ""
+
+msgctxt ""
+"model:ir.model.button,string:sale_amendment_validation_amendment_button"
+msgid "Validate"
+msgstr ""
+
+msgctxt "model:ir.ui.menu,name:menu_sale_amendment"
+msgid "Amendments"
+msgstr ""
+
+msgctxt "model:res.group,name:group_sale_amendment"
+msgid "Sale Amendment"
+msgstr ""
+
+msgctxt "model:sale.amendment,name:"
+msgid "Sale Amendment"
+msgstr ""
+
+msgctxt "model:sale.amendment.line,name:"
+msgid "Sale Amendment Line"
+msgstr ""
+
+msgctxt "selection:sale.amendment,state:"
+msgid "Draft"
+msgstr ""
+
+msgctxt "selection:sale.amendment,state:"
+msgid "Validated"
+msgstr ""
+
+msgctxt "selection:sale.amendment.line,action:"
+msgid "Change Line"
+msgstr ""
+
+msgctxt "selection:sale.amendment.line,action:"
+msgid "Change Parties and Addresses"
+msgstr ""
+
+msgctxt "selection:sale.amendment.line,action:"
+msgid "Change Payment Term"
+msgstr ""
+
+msgctxt "selection:sale.amendment.line,action:"
+msgid "Change Warehouse"
+msgstr ""
+
+msgctxt "selection:sale.amendment.line,action:"
+msgid "Recompute Taxes"
+msgstr ""
diff --git a/modules/sale_amendment/locale/fr.po b/modules/sale_amendment/locale/fr.po
new file mode 100644
index 0000000000..41edfceb7e
--- /dev/null
+++ b/modules/sale_amendment/locale/fr.po
@@ -0,0 +1,180 @@
+#
+msgid ""
+msgstr "Content-Type: text/plain; charset=utf-8\n"
+
+msgctxt "field:sale.amendment,date:"
+msgid "Date"
+msgstr "Date"
+
+msgctxt "field:sale.amendment,description:"
+msgid "Description"
+msgstr "Description"
+
+msgctxt "field:sale.amendment,lines:"
+msgid "Lines"
+msgstr "Lignes"
+
+msgctxt "field:sale.amendment,sale:"
+msgid "Sale"
+msgstr "Vente"
+
+msgctxt "field:sale.amendment,state:"
+msgid "State"
+msgstr "État"
+
+msgctxt "field:sale.amendment.line,action:"
+msgid "Action"
+msgstr "Action"
+
+msgctxt "field:sale.amendment.line,amendment:"
+msgid "Amendment"
+msgstr "Amendement"
+
+msgctxt "field:sale.amendment.line,description:"
+msgid "Description"
+msgstr "Description"
+
+msgctxt "field:sale.amendment.line,invoice_address:"
+msgid "Invoice Address"
+msgstr "Adresse de facturation"
+
+msgctxt "field:sale.amendment.line,line:"
+msgid "Line"
+msgstr "Ligne"
+
+msgctxt "field:sale.amendment.line,party:"
+msgid "Party"
+msgstr "Tiers"
+
+msgctxt "field:sale.amendment.line,payment_term:"
+msgid "Payment Term"
+msgstr "Conditions de paiement"
+
+msgctxt "field:sale.amendment.line,product:"
+msgid "Product"
+msgstr "Produit"
+
+msgctxt "field:sale.amendment.line,product_uom_category:"
+msgid "Product UoM Category"
+msgstr "Catégorie d'unité de mesure"
+
+msgctxt "field:sale.amendment.line,quantity:"
+msgid "Quantity"
+msgstr "Quantité"
+
+msgctxt "field:sale.amendment.line,sale:"
+msgid "Sale"
+msgstr "Vente"
+
+msgctxt "field:sale.amendment.line,shipment_address:"
+msgid "Shipment Address"
+msgstr "Adresse d'expédition"
+
+msgctxt "field:sale.amendment.line,shipment_party:"
+msgid "Shipment Party"
+msgstr "Tiers d'expédition"
+
+msgctxt "field:sale.amendment.line,state:"
+msgid "State"
+msgstr "État"
+
+msgctxt "field:sale.amendment.line,unit:"
+msgid "Unit"
+msgstr "Unité"
+
+msgctxt "field:sale.amendment.line,unit_digits:"
+msgid "Unit Digits"
+msgstr "Décimales de l'unité"
+
+msgctxt "field:sale.amendment.line,unit_price:"
+msgid "Unit Price"
+msgstr "Prix unitaire"
+
+msgctxt "field:sale.amendment.line,warehouse:"
+msgid "Warehouse"
+msgstr "Entrepôt"
+
+msgctxt "field:sale.sale,amendments:"
+msgid "Amendments"
+msgstr "Amendements"
+
+msgctxt "model:ir.action,name:act_sale_amendment_form"
+msgid "Amendments"
+msgstr "Amendements"
+
+msgctxt ""
+"model:ir.action.act_window.domain,name:act_sale_amendment_form_domain_all"
+msgid "All"
+msgstr "Tous"
+
+msgctxt ""
+"model:ir.action.act_window.domain,name:act_sale_amendment_form_domain_draft"
+msgid "Draft"
+msgstr "Brouillon"
+
+msgctxt ""
+"model:ir.action.act_window.domain,name:act_sale_amendment_form_domain_validated"
+msgid "Validated"
+msgstr "Validés"
+
+msgctxt "model:ir.message,text:msg_one_sale_at_time"
+msgid ""
+"You cannot validate more than one amendment at the same time for sale "
+"\"%(sale)s\"."
+msgstr ""
+"Vous ne pouvez pas valider plus d’un amendement à la fois pour la vente "
+"« %(sale)s »."
+
+msgctxt ""
+"model:ir.model.button,confirm:sale_amendment_validation_amendment_button"
+msgid "Are you sure you want to validate the amendments?"
+msgstr "Êtes-vous sûr de vouloir valider les amendements ?"
+
+msgctxt ""
+"model:ir.model.button,string:sale_amendment_validation_amendment_button"
+msgid "Validate"
+msgstr "Valider"
+
+msgctxt "model:ir.ui.menu,name:menu_sale_amendment"
+msgid "Amendments"
+msgstr "Amendements"
+
+msgctxt "model:res.group,name:group_sale_amendment"
+msgid "Sale Amendment"
+msgstr "Amendement de vente"
+
+msgctxt "model:sale.amendment,name:"
+msgid "Sale Amendment"
+msgstr "Amendement de vente"
+
+msgctxt "model:sale.amendment.line,name:"
+msgid "Sale Amendment Line"
+msgstr "Ligne d'amendement de vente"
+
+msgctxt "selection:sale.amendment,state:"
+msgid "Draft"
+msgstr "Brouillon"
+
+msgctxt "selection:sale.amendment,state:"
+msgid "Validated"
+msgstr "Validé"
+
+msgctxt "selection:sale.amendment.line,action:"
+msgid "Change Line"
+msgstr "Changer la ligne"
+
+msgctxt "selection:sale.amendment.line,action:"
+msgid "Change Parties and Addresses"
+msgstr "Changer les tiers et les adresses"
+
+msgctxt "selection:sale.amendment.line,action:"
+msgid "Change Payment Term"
+msgstr "Changer les conditions de paiement"
+
+msgctxt "selection:sale.amendment.line,action:"
+msgid "Change Warehouse"
+msgstr "Changer d'entrepôt"
+
+msgctxt "selection:sale.amendment.line,action:"
+msgid "Recompute Taxes"
+msgstr "Recalculer les taxes"
diff --git a/modules/sale_amendment/locale/hu.po b/modules/sale_amendment/locale/hu.po
new file mode 100644
index 0000000000..18c95a56fe
--- /dev/null
+++ b/modules/sale_amendment/locale/hu.po
@@ -0,0 +1,178 @@
+#
+msgid ""
+msgstr "Content-Type: text/plain; charset=utf-8\n"
+
+msgctxt "field:sale.amendment,date:"
+msgid "Date"
+msgstr ""
+
+msgctxt "field:sale.amendment,description:"
+msgid "Description"
+msgstr ""
+
+msgctxt "field:sale.amendment,lines:"
+msgid "Lines"
+msgstr ""
+
+msgctxt "field:sale.amendment,sale:"
+msgid "Sale"
+msgstr ""
+
+msgctxt "field:sale.amendment,state:"
+msgid "State"
+msgstr ""
+
+msgctxt "field:sale.amendment.line,action:"
+msgid "Action"
+msgstr ""
+
+msgctxt "field:sale.amendment.line,amendment:"
+msgid "Amendment"
+msgstr ""
+
+msgctxt "field:sale.amendment.line,description:"
+msgid "Description"
+msgstr ""
+
+msgctxt "field:sale.amendment.line,invoice_address:"
+msgid "Invoice Address"
+msgstr ""
+
+msgctxt "field:sale.amendment.line,line:"
+msgid "Line"
+msgstr ""
+
+msgctxt "field:sale.amendment.line,party:"
+msgid "Party"
+msgstr ""
+
+msgctxt "field:sale.amendment.line,payment_term:"
+msgid "Payment Term"
+msgstr ""
+
+msgctxt "field:sale.amendment.line,product:"
+msgid "Product"
+msgstr ""
+
+msgctxt "field:sale.amendment.line,product_uom_category:"
+msgid "Product UoM Category"
+msgstr ""
+
+msgctxt "field:sale.amendment.line,quantity:"
+msgid "Quantity"
+msgstr ""
+
+msgctxt "field:sale.amendment.line,sale:"
+msgid "Sale"
+msgstr ""
+
+msgctxt "field:sale.amendment.line,shipment_address:"
+msgid "Shipment Address"
+msgstr ""
+
+msgctxt "field:sale.amendment.line,shipment_party:"
+msgid "Shipment Party"
+msgstr ""
+
+msgctxt "field:sale.amendment.line,state:"
+msgid "State"
+msgstr ""
+
+msgctxt "field:sale.amendment.line,unit:"
+msgid "Unit"
+msgstr ""
+
+msgctxt "field:sale.amendment.line,unit_digits:"
+msgid "Unit Digits"
+msgstr ""
+
+msgctxt "field:sale.amendment.line,unit_price:"
+msgid "Unit Price"
+msgstr ""
+
+msgctxt "field:sale.amendment.line,warehouse:"
+msgid "Warehouse"
+msgstr ""
+
+msgctxt "field:sale.sale,amendments:"
+msgid "Amendments"
+msgstr ""
+
+msgctxt "model:ir.action,name:act_sale_amendment_form"
+msgid "Amendments"
+msgstr ""
+
+msgctxt ""
+"model:ir.action.act_window.domain,name:act_sale_amendment_form_domain_all"
+msgid "All"
+msgstr ""
+
+msgctxt ""
+"model:ir.action.act_window.domain,name:act_sale_amendment_form_domain_draft"
+msgid "Draft"
+msgstr ""
+
+msgctxt ""
+"model:ir.action.act_window.domain,name:act_sale_amendment_form_domain_validated"
+msgid "Validated"
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_one_sale_at_time"
+msgid ""
+"You cannot validate more than one amendment at the same time for sale "
+"\"%(sale)s\"."
+msgstr ""
+
+msgctxt ""
+"model:ir.model.button,confirm:sale_amendment_validation_amendment_button"
+msgid "Are you sure you want to validate the amendments?"
+msgstr ""
+
+msgctxt ""
+"model:ir.model.button,string:sale_amendment_validation_amendment_button"
+msgid "Validate"
+msgstr ""
+
+msgctxt "model:ir.ui.menu,name:menu_sale_amendment"
+msgid "Amendments"
+msgstr ""
+
+msgctxt "model:res.group,name:group_sale_amendment"
+msgid "Sale Amendment"
+msgstr ""
+
+msgctxt "model:sale.amendment,name:"
+msgid "Sale Amendment"
+msgstr ""
+
+msgctxt "model:sale.amendment.line,name:"
+msgid "Sale Amendment Line"
+msgstr ""
+
+msgctxt "selection:sale.amendment,state:"
+msgid "Draft"
+msgstr ""
+
+msgctxt "selection:sale.amendment,state:"
+msgid "Validated"
+msgstr ""
+
+msgctxt "selection:sale.amendment.line,action:"
+msgid "Change Line"
+msgstr ""
+
+msgctxt "selection:sale.amendment.line,action:"
+msgid "Change Parties and Addresses"
+msgstr ""
+
+msgctxt "selection:sale.amendment.line,action:"
+msgid "Change Payment Term"
+msgstr ""
+
+msgctxt "selection:sale.amendment.line,action:"
+msgid "Change Warehouse"
+msgstr ""
+
+msgctxt "selection:sale.amendment.line,action:"
+msgid "Recompute Taxes"
+msgstr ""
diff --git a/modules/sale_amendment/locale/id.po b/modules/sale_amendment/locale/id.po
new file mode 100644
index 0000000000..36c5e38264
--- /dev/null
+++ b/modules/sale_amendment/locale/id.po
@@ -0,0 +1,178 @@
+#
+msgid ""
+msgstr "Content-Type: text/plain; charset=utf-8\n"
+
+msgctxt "field:sale.amendment,date:"
+msgid "Date"
+msgstr "Tanggal"
+
+msgctxt "field:sale.amendment,description:"
+msgid "Description"
+msgstr "Deskripsi"
+
+msgctxt "field:sale.amendment,lines:"
+msgid "Lines"
+msgstr "Baris"
+
+msgctxt "field:sale.amendment,sale:"
+msgid "Sale"
+msgstr "Penjualan"
+
+msgctxt "field:sale.amendment,state:"
+msgid "State"
+msgstr ""
+
+msgctxt "field:sale.amendment.line,action:"
+msgid "Action"
+msgstr ""
+
+msgctxt "field:sale.amendment.line,amendment:"
+msgid "Amendment"
+msgstr ""
+
+msgctxt "field:sale.amendment.line,description:"
+msgid "Description"
+msgstr "Deskripsi"
+
+msgctxt "field:sale.amendment.line,invoice_address:"
+msgid "Invoice Address"
+msgstr "Alamat Faktur"
+
+msgctxt "field:sale.amendment.line,line:"
+msgid "Line"
+msgstr "Baris"
+
+msgctxt "field:sale.amendment.line,party:"
+msgid "Party"
+msgstr "Pihak"
+
+msgctxt "field:sale.amendment.line,payment_term:"
+msgid "Payment Term"
+msgstr "Masa Pembayaran"
+
+msgctxt "field:sale.amendment.line,product:"
+msgid "Product"
+msgstr "Produk"
+
+msgctxt "field:sale.amendment.line,product_uom_category:"
+msgid "Product UoM Category"
+msgstr ""
+
+msgctxt "field:sale.amendment.line,quantity:"
+msgid "Quantity"
+msgstr ""
+
+msgctxt "field:sale.amendment.line,sale:"
+msgid "Sale"
+msgstr "Penjualan"
+
+msgctxt "field:sale.amendment.line,shipment_address:"
+msgid "Shipment Address"
+msgstr "Alamat Pengiriman"
+
+msgctxt "field:sale.amendment.line,shipment_party:"
+msgid "Shipment Party"
+msgstr "Pihak Pengiriman"
+
+msgctxt "field:sale.amendment.line,state:"
+msgid "State"
+msgstr ""
+
+msgctxt "field:sale.amendment.line,unit:"
+msgid "Unit"
+msgstr ""
+
+msgctxt "field:sale.amendment.line,unit_digits:"
+msgid "Unit Digits"
+msgstr ""
+
+msgctxt "field:sale.amendment.line,unit_price:"
+msgid "Unit Price"
+msgstr ""
+
+msgctxt "field:sale.amendment.line,warehouse:"
+msgid "Warehouse"
+msgstr ""
+
+msgctxt "field:sale.sale,amendments:"
+msgid "Amendments"
+msgstr ""
+
+msgctxt "model:ir.action,name:act_sale_amendment_form"
+msgid "Amendments"
+msgstr ""
+
+msgctxt ""
+"model:ir.action.act_window.domain,name:act_sale_amendment_form_domain_all"
+msgid "All"
+msgstr ""
+
+msgctxt ""
+"model:ir.action.act_window.domain,name:act_sale_amendment_form_domain_draft"
+msgid "Draft"
+msgstr ""
+
+msgctxt ""
+"model:ir.action.act_window.domain,name:act_sale_amendment_form_domain_validated"
+msgid "Validated"
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_one_sale_at_time"
+msgid ""
+"You cannot validate more than one amendment at the same time for sale "
+"\"%(sale)s\"."
+msgstr ""
+
+msgctxt ""
+"model:ir.model.button,confirm:sale_amendment_validation_amendment_button"
+msgid "Are you sure you want to validate the amendments?"
+msgstr ""
+
+msgctxt ""
+"model:ir.model.button,string:sale_amendment_validation_amendment_button"
+msgid "Validate"
+msgstr ""
+
+msgctxt "model:ir.ui.menu,name:menu_sale_amendment"
+msgid "Amendments"
+msgstr ""
+
+msgctxt "model:res.group,name:group_sale_amendment"
+msgid "Sale Amendment"
+msgstr ""
+
+msgctxt "model:sale.amendment,name:"
+msgid "Sale Amendment"
+msgstr ""
+
+msgctxt "model:sale.amendment.line,name:"
+msgid "Sale Amendment Line"
+msgstr ""
+
+msgctxt "selection:sale.amendment,state:"
+msgid "Draft"
+msgstr ""
+
+msgctxt "selection:sale.amendment,state:"
+msgid "Validated"
+msgstr ""
+
+msgctxt "selection:sale.amendment.line,action:"
+msgid "Change Line"
+msgstr ""
+
+msgctxt "selection:sale.amendment.line,action:"
+msgid "Change Parties and Addresses"
+msgstr ""
+
+msgctxt "selection:sale.amendment.line,action:"
+msgid "Change Payment Term"
+msgstr ""
+
+msgctxt "selection:sale.amendment.line,action:"
+msgid "Change Warehouse"
+msgstr ""
+
+msgctxt "selection:sale.amendment.line,action:"
+msgid "Recompute Taxes"
+msgstr ""
diff --git a/modules/sale_amendment/locale/it.po b/modules/sale_amendment/locale/it.po
new file mode 100644
index 0000000000..511c646549
--- /dev/null
+++ b/modules/sale_amendment/locale/it.po
@@ -0,0 +1,183 @@
+#
+msgid ""
+msgstr "Content-Type: text/plain; charset=utf-8\n"
+
+msgctxt "field:sale.amendment,date:"
+msgid "Date"
+msgstr "Data"
+
+msgctxt "field:sale.amendment,description:"
+msgid "Description"
+msgstr "Descrizione"
+
+msgctxt "field:sale.amendment,lines:"
+msgid "Lines"
+msgstr "Righe"
+
+msgctxt "field:sale.amendment,sale:"
+msgid "Sale"
+msgstr "Vendita"
+
+msgctxt "field:sale.amendment,state:"
+msgid "State"
+msgstr "Stato"
+
+msgctxt "field:sale.amendment.line,action:"
+msgid "Action"
+msgstr "Azione"
+
+msgctxt "field:sale.amendment.line,amendment:"
+msgid "Amendment"
+msgstr ""
+
+msgctxt "field:sale.amendment.line,description:"
+msgid "Description"
+msgstr "Descrizione"
+
+msgctxt "field:sale.amendment.line,invoice_address:"
+msgid "Invoice Address"
+msgstr "Indirizzo di fatturazione"
+
+msgctxt "field:sale.amendment.line,line:"
+msgid "Line"
+msgstr "Riga"
+
+msgctxt "field:sale.amendment.line,party:"
+msgid "Party"
+msgstr "Controparte"
+
+msgctxt "field:sale.amendment.line,payment_term:"
+msgid "Payment Term"
+msgstr "Termine di pagamento"
+
+msgctxt "field:sale.amendment.line,product:"
+msgid "Product"
+msgstr "Prodotto"
+
+msgctxt "field:sale.amendment.line,product_uom_category:"
+msgid "Product UoM Category"
+msgstr ""
+
+msgctxt "field:sale.amendment.line,quantity:"
+msgid "Quantity"
+msgstr "Quantità"
+
+msgctxt "field:sale.amendment.line,sale:"
+msgid "Sale"
+msgstr "Vendita"
+
+msgctxt "field:sale.amendment.line,shipment_address:"
+msgid "Shipment Address"
+msgstr "Indirizzo di spedizione"
+
+msgctxt "field:sale.amendment.line,shipment_party:"
+msgid "Shipment Party"
+msgstr ""
+
+msgctxt "field:sale.amendment.line,state:"
+msgid "State"
+msgstr "Stato"
+
+msgctxt "field:sale.amendment.line,unit:"
+msgid "Unit"
+msgstr "Unità"
+
+msgctxt "field:sale.amendment.line,unit_digits:"
+msgid "Unit Digits"
+msgstr ""
+
+msgctxt "field:sale.amendment.line,unit_price:"
+msgid "Unit Price"
+msgstr "Prezzo Unitario"
+
+msgctxt "field:sale.amendment.line,warehouse:"
+msgid "Warehouse"
+msgstr "Magazzino"
+
+msgctxt "field:sale.sale,amendments:"
+msgid "Amendments"
+msgstr "Modifiche"
+
+#, fuzzy
+msgctxt "model:ir.action,name:act_sale_amendment_form"
+msgid "Amendments"
+msgstr "Modifiche"
+
+msgctxt ""
+"model:ir.action.act_window.domain,name:act_sale_amendment_form_domain_all"
+msgid "All"
+msgstr "Tutti"
+
+msgctxt ""
+"model:ir.action.act_window.domain,name:act_sale_amendment_form_domain_draft"
+msgid "Draft"
+msgstr "Bozza"
+
+msgctxt ""
+"model:ir.action.act_window.domain,name:act_sale_amendment_form_domain_validated"
+msgid "Validated"
+msgstr "Validata"
+
+#, fuzzy
+msgctxt "model:ir.message,text:msg_one_sale_at_time"
+msgid ""
+"You cannot validate more than one amendment at the same time for sale "
+"\"%(sale)s\"."
+msgstr ""
+"Non è possibile convalidare più di una modifica contemporaneamente per la "
+"vendita \"%(sale)s\"."
+
+msgctxt ""
+"model:ir.model.button,confirm:sale_amendment_validation_amendment_button"
+msgid "Are you sure you want to validate the amendments?"
+msgstr ""
+
+msgctxt ""
+"model:ir.model.button,string:sale_amendment_validation_amendment_button"
+msgid "Validate"
+msgstr ""
+
+#, fuzzy
+msgctxt "model:ir.ui.menu,name:menu_sale_amendment"
+msgid "Amendments"
+msgstr "Modifiche"
+
+msgctxt "model:res.group,name:group_sale_amendment"
+msgid "Sale Amendment"
+msgstr "Modifiche sulla vendita"
+
+msgctxt "model:sale.amendment,name:"
+msgid "Sale Amendment"
+msgstr "Modifiche sulla vendita"
+
+msgctxt "model:sale.amendment.line,name:"
+msgid "Sale Amendment Line"
+msgstr ""
+
+msgctxt "selection:sale.amendment,state:"
+msgid "Draft"
+msgstr "Bozza"
+
+msgctxt "selection:sale.amendment,state:"
+msgid "Validated"
+msgstr ""
+
+msgctxt "selection:sale.amendment.line,action:"
+msgid "Change Line"
+msgstr ""
+
+msgctxt "selection:sale.amendment.line,action:"
+msgid "Change Parties and Addresses"
+msgstr "Cambia controparti e indirizzi"
+
+msgctxt "selection:sale.amendment.line,action:"
+msgid "Change Payment Term"
+msgstr "Modifica il termine di pagamento"
+
+msgctxt "selection:sale.amendment.line,action:"
+msgid "Change Warehouse"
+msgstr "Cambia magazzino"
+
+msgctxt "selection:sale.amendment.line,action:"
+msgid "Recompute Taxes"
+msgstr "Ricalcola le tasse"
diff --git a/modules/sale_amendment/locale/lo.po b/modules/sale_amendment/locale/lo.po
new file mode 100644
index 0000000000..18c95a56fe
--- /dev/null
+++ b/modules/sale_amendment/locale/lo.po
@@ -0,0 +1,178 @@
+#
+msgid ""
+msgstr "Content-Type: text/plain; charset=utf-8\n"
+
+msgctxt "field:sale.amendment,date:"
+msgid "Date"
+msgstr ""
+
+msgctxt "field:sale.amendment,description:"
+msgid "Description"
+msgstr ""
+
+msgctxt "field:sale.amendment,lines:"
+msgid "Lines"
+msgstr ""
+
+msgctxt "field:sale.amendment,sale:"
+msgid "Sale"
+msgstr ""
+
+msgctxt "field:sale.amendment,state:"
+msgid "State"
+msgstr ""
+
+msgctxt "field:sale.amendment.line,action:"
+msgid "Action"
+msgstr ""
+
+msgctxt "field:sale.amendment.line,amendment:"
+msgid "Amendment"
+msgstr ""
+
+msgctxt "field:sale.amendment.line,description:"
+msgid "Description"
+msgstr ""
+
+msgctxt "field:sale.amendment.line,invoice_address:"
+msgid "Invoice Address"
+msgstr ""
+
+msgctxt "field:sale.amendment.line,line:"
+msgid "Line"
+msgstr ""
+
+msgctxt "field:sale.amendment.line,party:"
+msgid "Party"
+msgstr ""
+
+msgctxt "field:sale.amendment.line,payment_term:"
+msgid "Payment Term"
+msgstr ""
+
+msgctxt "field:sale.amendment.line,product:"
+msgid "Product"
+msgstr ""
+
+msgctxt "field:sale.amendment.line,product_uom_category:"
+msgid "Product UoM Category"
+msgstr ""
+
+msgctxt "field:sale.amendment.line,quantity:"
+msgid "Quantity"
+msgstr ""
+
+msgctxt "field:sale.amendment.line,sale:"
+msgid "Sale"
+msgstr ""
+
+msgctxt "field:sale.amendment.line,shipment_address:"
+msgid "Shipment Address"
+msgstr ""
+
+msgctxt "field:sale.amendment.line,shipment_party:"
+msgid "Shipment Party"
+msgstr ""
+
+msgctxt "field:sale.amendment.line,state:"
+msgid "State"
+msgstr ""
+
+msgctxt "field:sale.amendment.line,unit:"
+msgid "Unit"
+msgstr ""
+
+msgctxt "field:sale.amendment.line,unit_digits:"
+msgid "Unit Digits"
+msgstr ""
+
+msgctxt "field:sale.amendment.line,unit_price:"
+msgid "Unit Price"
+msgstr ""
+
+msgctxt "field:sale.amendment.line,warehouse:"
+msgid "Warehouse"
+msgstr ""
+
+msgctxt "field:sale.sale,amendments:"
+msgid "Amendments"
+msgstr ""
+
+msgctxt "model:ir.action,name:act_sale_amendment_form"
+msgid "Amendments"
+msgstr ""
+
+msgctxt ""
+"model:ir.action.act_window.domain,name:act_sale_amendment_form_domain_all"
+msgid "All"
+msgstr ""
+
+msgctxt ""
+"model:ir.action.act_window.domain,name:act_sale_amendment_form_domain_draft"
+msgid "Draft"
+msgstr ""
+
+msgctxt ""
+"model:ir.action.act_window.domain,name:act_sale_amendment_form_domain_validated"
+msgid "Validated"
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_one_sale_at_time"
+msgid ""
+"You cannot validate more than one amendment at the same time for sale "
+"\"%(sale)s\"."
+msgstr ""
+
+msgctxt ""
+"model:ir.model.button,confirm:sale_amendment_validation_amendment_button"
+msgid "Are you sure you want to validate the amendments?"
+msgstr ""
+
+msgctxt ""
+"model:ir.model.button,string:sale_amendment_validation_amendment_button"
+msgid "Validate"
+msgstr ""
+
+msgctxt "model:ir.ui.menu,name:menu_sale_amendment"
+msgid "Amendments"
+msgstr ""
+
+msgctxt "model:res.group,name:group_sale_amendment"
+msgid "Sale Amendment"
+msgstr ""
+
+msgctxt "model:sale.amendment,name:"
+msgid "Sale Amendment"
+msgstr ""
+
+msgctxt "model:sale.amendment.line,name:"
+msgid "Sale Amendment Line"
+msgstr ""
+
+msgctxt "selection:sale.amendment,state:"
+msgid "Draft"
+msgstr ""
+
+msgctxt "selection:sale.amendment,state:"
+msgid "Validated"
+msgstr ""
+
+msgctxt "selection:sale.amendment.line,action:"
+msgid "Change Line"
+msgstr ""
+
+msgctxt "selection:sale.amendment.line,action:"
+msgid "Change Parties and Addresses"
+msgstr ""
+
+msgctxt "selection:sale.amendment.line,action:"
+msgid "Change Payment Term"
+msgstr ""
+
+msgctxt "selection:sale.amendment.line,action:"
+msgid "Change Warehouse"
+msgstr ""
+
+msgctxt "selection:sale.amendment.line,action:"
+msgid "Recompute Taxes"
+msgstr ""
diff --git a/modules/sale_amendment/locale/lt.po b/modules/sale_amendment/locale/lt.po
new file mode 100644
index 0000000000..18c95a56fe
--- /dev/null
+++ b/modules/sale_amendment/locale/lt.po
@@ -0,0 +1,178 @@
+#
+msgid ""
+msgstr "Content-Type: text/plain; charset=utf-8\n"
+
+msgctxt "field:sale.amendment,date:"
+msgid "Date"
+msgstr ""
+
+msgctxt "field:sale.amendment,description:"
+msgid "Description"
+msgstr ""
+
+msgctxt "field:sale.amendment,lines:"
+msgid "Lines"
+msgstr ""
+
+msgctxt "field:sale.amendment,sale:"
+msgid "Sale"
+msgstr ""
+
+msgctxt "field:sale.amendment,state:"
+msgid "State"
+msgstr ""
+
+msgctxt "field:sale.amendment.line,action:"
+msgid "Action"
+msgstr ""
+
+msgctxt "field:sale.amendment.line,amendment:"
+msgid "Amendment"
+msgstr ""
+
+msgctxt "field:sale.amendment.line,description:"
+msgid "Description"
+msgstr ""
+
+msgctxt "field:sale.amendment.line,invoice_address:"
+msgid "Invoice Address"
+msgstr ""
+
+msgctxt "field:sale.amendment.line,line:"
+msgid "Line"
+msgstr ""
+
+msgctxt "field:sale.amendment.line,party:"
+msgid "Party"
+msgstr ""
+
+msgctxt "field:sale.amendment.line,payment_term:"
+msgid "Payment Term"
+msgstr ""
+
+msgctxt "field:sale.amendment.line,product:"
+msgid "Product"
+msgstr ""
+
+msgctxt "field:sale.amendment.line,product_uom_category:"
+msgid "Product UoM Category"
+msgstr ""
+
+msgctxt "field:sale.amendment.line,quantity:"
+msgid "Quantity"
+msgstr ""
+
+msgctxt "field:sale.amendment.line,sale:"
+msgid "Sale"
+msgstr ""
+
+msgctxt "field:sale.amendment.line,shipment_address:"
+msgid "Shipment Address"
+msgstr ""
+
+msgctxt "field:sale.amendment.line,shipment_party:"
+msgid "Shipment Party"
+msgstr ""
+
+msgctxt "field:sale.amendment.line,state:"
+msgid "State"
+msgstr ""
+
+msgctxt "field:sale.amendment.line,unit:"
+msgid "Unit"
+msgstr ""
+
+msgctxt "field:sale.amendment.line,unit_digits:"
+msgid "Unit Digits"
+msgstr ""
+
+msgctxt "field:sale.amendment.line,unit_price:"
+msgid "Unit Price"
+msgstr ""
+
+msgctxt "field:sale.amendment.line,warehouse:"
+msgid "Warehouse"
+msgstr ""
+
+msgctxt "field:sale.sale,amendments:"
+msgid "Amendments"
+msgstr ""
+
+msgctxt "model:ir.action,name:act_sale_amendment_form"
+msgid "Amendments"
+msgstr ""
+
+msgctxt ""
+"model:ir.action.act_window.domain,name:act_sale_amendment_form_domain_all"
+msgid "All"
+msgstr ""
+
+msgctxt ""
+"model:ir.action.act_window.domain,name:act_sale_amendment_form_domain_draft"
+msgid "Draft"
+msgstr ""
+
+msgctxt ""
+"model:ir.action.act_window.domain,name:act_sale_amendment_form_domain_validated"
+msgid "Validated"
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_one_sale_at_time"
+msgid ""
+"You cannot validate more than one amendment at the same time for sale "
+"\"%(sale)s\"."
+msgstr ""
+
+msgctxt ""
+"model:ir.model.button,confirm:sale_amendment_validation_amendment_button"
+msgid "Are you sure you want to validate the amendments?"
+msgstr ""
+
+msgctxt ""
+"model:ir.model.button,string:sale_amendment_validation_amendment_button"
+msgid "Validate"
+msgstr ""
+
+msgctxt "model:ir.ui.menu,name:menu_sale_amendment"
+msgid "Amendments"
+msgstr ""
+
+msgctxt "model:res.group,name:group_sale_amendment"
+msgid "Sale Amendment"
+msgstr ""
+
+msgctxt "model:sale.amendment,name:"
+msgid "Sale Amendment"
+msgstr ""
+
+msgctxt "model:sale.amendment.line,name:"
+msgid "Sale Amendment Line"
+msgstr ""
+
+msgctxt "selection:sale.amendment,state:"
+msgid "Draft"
+msgstr ""
+
+msgctxt "selection:sale.amendment,state:"
+msgid "Validated"
+msgstr ""
+
+msgctxt "selection:sale.amendment.line,action:"
+msgid "Change Line"
+msgstr ""
+
+msgctxt "selection:sale.amendment.line,action:"
+msgid "Change Parties and Addresses"
+msgstr ""
+
+msgctxt "selection:sale.amendment.line,action:"
+msgid "Change Payment Term"
+msgstr ""
+
+msgctxt "selection:sale.amendment.line,action:"
+msgid "Change Warehouse"
+msgstr ""
+
+msgctxt "selection:sale.amendment.line,action:"
+msgid "Recompute Taxes"
+msgstr ""
diff --git a/modules/sale_amendment/locale/nl.po b/modules/sale_amendment/locale/nl.po
new file mode 100644
index 0000000000..a65ce8992b
--- /dev/null
+++ b/modules/sale_amendment/locale/nl.po
@@ -0,0 +1,182 @@
+#
+msgid ""
+msgstr "Content-Type: text/plain; charset=utf-8\n"
+
+msgctxt "field:sale.amendment,date:"
+msgid "Date"
+msgstr "Datum"
+
+msgctxt "field:sale.amendment,description:"
+msgid "Description"
+msgstr "Omschrijving"
+
+msgctxt "field:sale.amendment,lines:"
+msgid "Lines"
+msgstr "Regels"
+
+msgctxt "field:sale.amendment,sale:"
+msgid "Sale"
+msgstr "Verkoop"
+
+msgctxt "field:sale.amendment,state:"
+msgid "State"
+msgstr "Status"
+
+msgctxt "field:sale.amendment.line,action:"
+msgid "Action"
+msgstr "Actie"
+
+msgctxt "field:sale.amendment.line,amendment:"
+msgid "Amendment"
+msgstr "wijziging"
+
+msgctxt "field:sale.amendment.line,description:"
+msgid "Description"
+msgstr "Omschrijving"
+
+msgctxt "field:sale.amendment.line,invoice_address:"
+msgid "Invoice Address"
+msgstr "Factuuradres"
+
+msgctxt "field:sale.amendment.line,line:"
+msgid "Line"
+msgstr "Regel"
+
+msgctxt "field:sale.amendment.line,party:"
+msgid "Party"
+msgstr "Relatie"
+
+msgctxt "field:sale.amendment.line,payment_term:"
+msgid "Payment Term"
+msgstr "Betalingstermijn"
+
+msgctxt "field:sale.amendment.line,product:"
+msgid "Product"
+msgstr "Product"
+
+msgctxt "field:sale.amendment.line,product_uom_category:"
+msgid "Product UoM Category"
+msgstr "product eenheidsmaat categorie"
+
+msgctxt "field:sale.amendment.line,quantity:"
+msgid "Quantity"
+msgstr "Hoeveelheid"
+
+msgctxt "field:sale.amendment.line,sale:"
+msgid "Sale"
+msgstr "Verkoop"
+
+msgctxt "field:sale.amendment.line,shipment_address:"
+msgid "Shipment Address"
+msgstr "Afleveradres"
+
+msgctxt "field:sale.amendment.line,shipment_party:"
+msgid "Shipment Party"
+msgstr "courierdienst (shipment paty)"
+
+msgctxt "field:sale.amendment.line,state:"
+msgid "State"
+msgstr "Status"
+
+msgctxt "field:sale.amendment.line,unit:"
+msgid "Unit"
+msgstr "Eenheid"
+
+msgctxt "field:sale.amendment.line,unit_digits:"
+msgid "Unit Digits"
+msgstr "Decimalen eenheid"
+
+msgctxt "field:sale.amendment.line,unit_price:"
+msgid "Unit Price"
+msgstr "Eenheidsprijs"
+
+msgctxt "field:sale.amendment.line,warehouse:"
+msgid "Warehouse"
+msgstr "Magazijn"
+
+msgctxt "field:sale.sale,amendments:"
+msgid "Amendments"
+msgstr "wijzigingen"
+
+#, fuzzy
+msgctxt "model:ir.action,name:act_sale_amendment_form"
+msgid "Amendments"
+msgstr "wijzigingen"
+
+msgctxt ""
+"model:ir.action.act_window.domain,name:act_sale_amendment_form_domain_all"
+msgid "All"
+msgstr "Alle"
+
+msgctxt ""
+"model:ir.action.act_window.domain,name:act_sale_amendment_form_domain_draft"
+msgid "Draft"
+msgstr "Concept"
+
+msgctxt ""
+"model:ir.action.act_window.domain,name:act_sale_amendment_form_domain_validated"
+msgid "Validated"
+msgstr "Goedgekeurd"
+
+msgctxt "model:ir.message,text:msg_one_sale_at_time"
+msgid ""
+"You cannot validate more than one amendment at the same time for sale "
+"\"%(sale)s\"."
+msgstr ""
+"U kunt niet meer dan één wijziging tegelijk valideren voor verkoop "
+"\"%(sale)s\"."
+
+msgctxt ""
+"model:ir.model.button,confirm:sale_amendment_validation_amendment_button"
+msgid "Are you sure you want to validate the amendments?"
+msgstr "Weet u zeker dat u de wijzigingen wilt valideren?"
+
+msgctxt ""
+"model:ir.model.button,string:sale_amendment_validation_amendment_button"
+msgid "Validate"
+msgstr "bevestigen"
+
+#, fuzzy
+msgctxt "model:ir.ui.menu,name:menu_sale_amendment"
+msgid "Amendments"
+msgstr "wijzigingen"
+
+msgctxt "model:res.group,name:group_sale_amendment"
+msgid "Sale Amendment"
+msgstr "Verkoop wijziging"
+
+msgctxt "model:sale.amendment,name:"
+msgid "Sale Amendment"
+msgstr "Verkoop wijziging"
+
+msgctxt "model:sale.amendment.line,name:"
+msgid "Sale Amendment Line"
+msgstr "Verkoop wijzigingsregel"
+
+msgctxt "selection:sale.amendment,state:"
+msgid "Draft"
+msgstr "Concept"
+
+msgctxt "selection:sale.amendment,state:"
+msgid "Validated"
+msgstr "Goedgekeurd"
+
+msgctxt "selection:sale.amendment.line,action:"
+msgid "Change Line"
+msgstr "Lijn wijzigen"
+
+msgctxt "selection:sale.amendment.line,action:"
+msgid "Change Parties and Addresses"
+msgstr "Verander relaties en adressen"
+
+msgctxt "selection:sale.amendment.line,action:"
+msgid "Change Payment Term"
+msgstr "Wijzig betalingsvoorwaarden"
+
+msgctxt "selection:sale.amendment.line,action:"
+msgid "Change Warehouse"
+msgstr "Magazijn wijzigen"
+
+msgctxt "selection:sale.amendment.line,action:"
+msgid "Recompute Taxes"
+msgstr "Belastingen opnieuw berekenen"
diff --git a/modules/sale_amendment/locale/pl.po b/modules/sale_amendment/locale/pl.po
new file mode 100644
index 0000000000..18c95a56fe
--- /dev/null
+++ b/modules/sale_amendment/locale/pl.po
@@ -0,0 +1,178 @@
+#
+msgid ""
+msgstr "Content-Type: text/plain; charset=utf-8\n"
+
+msgctxt "field:sale.amendment,date:"
+msgid "Date"
+msgstr ""
+
+msgctxt "field:sale.amendment,description:"
+msgid "Description"
+msgstr ""
+
+msgctxt "field:sale.amendment,lines:"
+msgid "Lines"
+msgstr ""
+
+msgctxt "field:sale.amendment,sale:"
+msgid "Sale"
+msgstr ""
+
+msgctxt "field:sale.amendment,state:"
+msgid "State"
+msgstr ""
+
+msgctxt "field:sale.amendment.line,action:"
+msgid "Action"
+msgstr ""
+
+msgctxt "field:sale.amendment.line,amendment:"
+msgid "Amendment"
+msgstr ""
+
+msgctxt "field:sale.amendment.line,description:"
+msgid "Description"
+msgstr ""
+
+msgctxt "field:sale.amendment.line,invoice_address:"
+msgid "Invoice Address"
+msgstr ""
+
+msgctxt "field:sale.amendment.line,line:"
+msgid "Line"
+msgstr ""
+
+msgctxt "field:sale.amendment.line,party:"
+msgid "Party"
+msgstr ""
+
+msgctxt "field:sale.amendment.line,payment_term:"
+msgid "Payment Term"
+msgstr ""
+
+msgctxt "field:sale.amendment.line,product:"
+msgid "Product"
+msgstr ""
+
+msgctxt "field:sale.amendment.line,product_uom_category:"
+msgid "Product UoM Category"
+msgstr ""
+
+msgctxt "field:sale.amendment.line,quantity:"
+msgid "Quantity"
+msgstr ""
+
+msgctxt "field:sale.amendment.line,sale:"
+msgid "Sale"
+msgstr ""
+
+msgctxt "field:sale.amendment.line,shipment_address:"
+msgid "Shipment Address"
+msgstr ""
+
+msgctxt "field:sale.amendment.line,shipment_party:"
+msgid "Shipment Party"
+msgstr ""
+
+msgctxt "field:sale.amendment.line,state:"
+msgid "State"
+msgstr ""
+
+msgctxt "field:sale.amendment.line,unit:"
+msgid "Unit"
+msgstr ""
+
+msgctxt "field:sale.amendment.line,unit_digits:"
+msgid "Unit Digits"
+msgstr ""
+
+msgctxt "field:sale.amendment.line,unit_price:"
+msgid "Unit Price"
+msgstr ""
+
+msgctxt "field:sale.amendment.line,warehouse:"
+msgid "Warehouse"
+msgstr ""
+
+msgctxt "field:sale.sale,amendments:"
+msgid "Amendments"
+msgstr ""
+
+msgctxt "model:ir.action,name:act_sale_amendment_form"
+msgid "Amendments"
+msgstr ""
+
+msgctxt ""
+"model:ir.action.act_window.domain,name:act_sale_amendment_form_domain_all"
+msgid "All"
+msgstr ""
+
+msgctxt ""
+"model:ir.action.act_window.domain,name:act_sale_amendment_form_domain_draft"
+msgid "Draft"
+msgstr ""
+
+msgctxt ""
+"model:ir.action.act_window.domain,name:act_sale_amendment_form_domain_validated"
+msgid "Validated"
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_one_sale_at_time"
+msgid ""
+"You cannot validate more than one amendment at the same time for sale "
+"\"%(sale)s\"."
+msgstr ""
+
+msgctxt ""
+"model:ir.model.button,confirm:sale_amendment_validation_amendment_button"
+msgid "Are you sure you want to validate the amendments?"
+msgstr ""
+
+msgctxt ""
+"model:ir.model.button,string:sale_amendment_validation_amendment_button"
+msgid "Validate"
+msgstr ""
+
+msgctxt "model:ir.ui.menu,name:menu_sale_amendment"
+msgid "Amendments"
+msgstr ""
+
+msgctxt "model:res.group,name:group_sale_amendment"
+msgid "Sale Amendment"
+msgstr ""
+
+msgctxt "model:sale.amendment,name:"
+msgid "Sale Amendment"
+msgstr ""
+
+msgctxt "model:sale.amendment.line,name:"
+msgid "Sale Amendment Line"
+msgstr ""
+
+msgctxt "selection:sale.amendment,state:"
+msgid "Draft"
+msgstr ""
+
+msgctxt "selection:sale.amendment,state:"
+msgid "Validated"
+msgstr ""
+
+msgctxt "selection:sale.amendment.line,action:"
+msgid "Change Line"
+msgstr ""
+
+msgctxt "selection:sale.amendment.line,action:"
+msgid "Change Parties and Addresses"
+msgstr ""
+
+msgctxt "selection:sale.amendment.line,action:"
+msgid "Change Payment Term"
+msgstr ""
+
+msgctxt "selection:sale.amendment.line,action:"
+msgid "Change Warehouse"
+msgstr ""
+
+msgctxt "selection:sale.amendment.line,action:"
+msgid "Recompute Taxes"
+msgstr ""
diff --git a/modules/sale_amendment/locale/pt.po b/modules/sale_amendment/locale/pt.po
new file mode 100644
index 0000000000..18c95a56fe
--- /dev/null
+++ b/modules/sale_amendment/locale/pt.po
@@ -0,0 +1,178 @@
+#
+msgid ""
+msgstr "Content-Type: text/plain; charset=utf-8\n"
+
+msgctxt "field:sale.amendment,date:"
+msgid "Date"
+msgstr ""
+
+msgctxt "field:sale.amendment,description:"
+msgid "Description"
+msgstr ""
+
+msgctxt "field:sale.amendment,lines:"
+msgid "Lines"
+msgstr ""
+
+msgctxt "field:sale.amendment,sale:"
+msgid "Sale"
+msgstr ""
+
+msgctxt "field:sale.amendment,state:"
+msgid "State"
+msgstr ""
+
+msgctxt "field:sale.amendment.line,action:"
+msgid "Action"
+msgstr ""
+
+msgctxt "field:sale.amendment.line,amendment:"
+msgid "Amendment"
+msgstr ""
+
+msgctxt "field:sale.amendment.line,description:"
+msgid "Description"
+msgstr ""
+
+msgctxt "field:sale.amendment.line,invoice_address:"
+msgid "Invoice Address"
+msgstr ""
+
+msgctxt "field:sale.amendment.line,line:"
+msgid "Line"
+msgstr ""
+
+msgctxt "field:sale.amendment.line,party:"
+msgid "Party"
+msgstr ""
+
+msgctxt "field:sale.amendment.line,payment_term:"
+msgid "Payment Term"
+msgstr ""
+
+msgctxt "field:sale.amendment.line,product:"
+msgid "Product"
+msgstr ""
+
+msgctxt "field:sale.amendment.line,product_uom_category:"
+msgid "Product UoM Category"
+msgstr ""
+
+msgctxt "field:sale.amendment.line,quantity:"
+msgid "Quantity"
+msgstr ""
+
+msgctxt "field:sale.amendment.line,sale:"
+msgid "Sale"
+msgstr ""
+
+msgctxt "field:sale.amendment.line,shipment_address:"
+msgid "Shipment Address"
+msgstr ""
+
+msgctxt "field:sale.amendment.line,shipment_party:"
+msgid "Shipment Party"
+msgstr ""
+
+msgctxt "field:sale.amendment.line,state:"
+msgid "State"
+msgstr ""
+
+msgctxt "field:sale.amendment.line,unit:"
+msgid "Unit"
+msgstr ""
+
+msgctxt "field:sale.amendment.line,unit_digits:"
+msgid "Unit Digits"
+msgstr ""
+
+msgctxt "field:sale.amendment.line,unit_price:"
+msgid "Unit Price"
+msgstr ""
+
+msgctxt "field:sale.amendment.line,warehouse:"
+msgid "Warehouse"
+msgstr ""
+
+msgctxt "field:sale.sale,amendments:"
+msgid "Amendments"
+msgstr ""
+
+msgctxt "model:ir.action,name:act_sale_amendment_form"
+msgid "Amendments"
+msgstr ""
+
+msgctxt ""
+"model:ir.action.act_window.domain,name:act_sale_amendment_form_domain_all"
+msgid "All"
+msgstr ""
+
+msgctxt ""
+"model:ir.action.act_window.domain,name:act_sale_amendment_form_domain_draft"
+msgid "Draft"
+msgstr ""
+
+msgctxt ""
+"model:ir.action.act_window.domain,name:act_sale_amendment_form_domain_validated"
+msgid "Validated"
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_one_sale_at_time"
+msgid ""
+"You cannot validate more than one amendment at the same time for sale "
+"\"%(sale)s\"."
+msgstr ""
+
+msgctxt ""
+"model:ir.model.button,confirm:sale_amendment_validation_amendment_button"
+msgid "Are you sure you want to validate the amendments?"
+msgstr ""
+
+msgctxt ""
+"model:ir.model.button,string:sale_amendment_validation_amendment_button"
+msgid "Validate"
+msgstr ""
+
+msgctxt "model:ir.ui.menu,name:menu_sale_amendment"
+msgid "Amendments"
+msgstr ""
+
+msgctxt "model:res.group,name:group_sale_amendment"
+msgid "Sale Amendment"
+msgstr ""
+
+msgctxt "model:sale.amendment,name:"
+msgid "Sale Amendment"
+msgstr ""
+
+msgctxt "model:sale.amendment.line,name:"
+msgid "Sale Amendment Line"
+msgstr ""
+
+msgctxt "selection:sale.amendment,state:"
+msgid "Draft"
+msgstr ""
+
+msgctxt "selection:sale.amendment,state:"
+msgid "Validated"
+msgstr ""
+
+msgctxt "selection:sale.amendment.line,action:"
+msgid "Change Line"
+msgstr ""
+
+msgctxt "selection:sale.amendment.line,action:"
+msgid "Change Parties and Addresses"
+msgstr ""
+
+msgctxt "selection:sale.amendment.line,action:"
+msgid "Change Payment Term"
+msgstr ""
+
+msgctxt "selection:sale.amendment.line,action:"
+msgid "Change Warehouse"
+msgstr ""
+
+msgctxt "selection:sale.amendment.line,action:"
+msgid "Recompute Taxes"
+msgstr ""
diff --git a/modules/sale_amendment/locale/ro.po b/modules/sale_amendment/locale/ro.po
new file mode 100644
index 0000000000..7e17cff38f
--- /dev/null
+++ b/modules/sale_amendment/locale/ro.po
@@ -0,0 +1,178 @@
+#
+msgid ""
+msgstr "Content-Type: text/plain; charset=utf-8\n"
+
+msgctxt "field:sale.amendment,date:"
+msgid "Date"
+msgstr "Data"
+
+msgctxt "field:sale.amendment,description:"
+msgid "Description"
+msgstr "Descriere"
+
+msgctxt "field:sale.amendment,lines:"
+msgid "Lines"
+msgstr ""
+
+msgctxt "field:sale.amendment,sale:"
+msgid "Sale"
+msgstr ""
+
+msgctxt "field:sale.amendment,state:"
+msgid "State"
+msgstr ""
+
+msgctxt "field:sale.amendment.line,action:"
+msgid "Action"
+msgstr "Acțiune"
+
+msgctxt "field:sale.amendment.line,amendment:"
+msgid "Amendment"
+msgstr ""
+
+msgctxt "field:sale.amendment.line,description:"
+msgid "Description"
+msgstr "Descriere"
+
+msgctxt "field:sale.amendment.line,invoice_address:"
+msgid "Invoice Address"
+msgstr ""
+
+msgctxt "field:sale.amendment.line,line:"
+msgid "Line"
+msgstr ""
+
+msgctxt "field:sale.amendment.line,party:"
+msgid "Party"
+msgstr "Parte"
+
+msgctxt "field:sale.amendment.line,payment_term:"
+msgid "Payment Term"
+msgstr "Termen de plata"
+
+msgctxt "field:sale.amendment.line,product:"
+msgid "Product"
+msgstr "Produs"
+
+msgctxt "field:sale.amendment.line,product_uom_category:"
+msgid "Product UoM Category"
+msgstr ""
+
+msgctxt "field:sale.amendment.line,quantity:"
+msgid "Quantity"
+msgstr ""
+
+msgctxt "field:sale.amendment.line,sale:"
+msgid "Sale"
+msgstr ""
+
+msgctxt "field:sale.amendment.line,shipment_address:"
+msgid "Shipment Address"
+msgstr ""
+
+msgctxt "field:sale.amendment.line,shipment_party:"
+msgid "Shipment Party"
+msgstr ""
+
+msgctxt "field:sale.amendment.line,state:"
+msgid "State"
+msgstr ""
+
+msgctxt "field:sale.amendment.line,unit:"
+msgid "Unit"
+msgstr ""
+
+msgctxt "field:sale.amendment.line,unit_digits:"
+msgid "Unit Digits"
+msgstr ""
+
+msgctxt "field:sale.amendment.line,unit_price:"
+msgid "Unit Price"
+msgstr ""
+
+msgctxt "field:sale.amendment.line,warehouse:"
+msgid "Warehouse"
+msgstr ""
+
+msgctxt "field:sale.sale,amendments:"
+msgid "Amendments"
+msgstr ""
+
+msgctxt "model:ir.action,name:act_sale_amendment_form"
+msgid "Amendments"
+msgstr ""
+
+msgctxt ""
+"model:ir.action.act_window.domain,name:act_sale_amendment_form_domain_all"
+msgid "All"
+msgstr ""
+
+msgctxt ""
+"model:ir.action.act_window.domain,name:act_sale_amendment_form_domain_draft"
+msgid "Draft"
+msgstr ""
+
+msgctxt ""
+"model:ir.action.act_window.domain,name:act_sale_amendment_form_domain_validated"
+msgid "Validated"
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_one_sale_at_time"
+msgid ""
+"You cannot validate more than one amendment at the same time for sale "
+"\"%(sale)s\"."
+msgstr ""
+
+msgctxt ""
+"model:ir.model.button,confirm:sale_amendment_validation_amendment_button"
+msgid "Are you sure you want to validate the amendments?"
+msgstr ""
+
+msgctxt ""
+"model:ir.model.button,string:sale_amendment_validation_amendment_button"
+msgid "Validate"
+msgstr ""
+
+msgctxt "model:ir.ui.menu,name:menu_sale_amendment"
+msgid "Amendments"
+msgstr ""
+
+msgctxt "model:res.group,name:group_sale_amendment"
+msgid "Sale Amendment"
+msgstr ""
+
+msgctxt "model:sale.amendment,name:"
+msgid "Sale Amendment"
+msgstr ""
+
+msgctxt "model:sale.amendment.line,name:"
+msgid "Sale Amendment Line"
+msgstr ""
+
+msgctxt "selection:sale.amendment,state:"
+msgid "Draft"
+msgstr ""
+
+msgctxt "selection:sale.amendment,state:"
+msgid "Validated"
+msgstr ""
+
+msgctxt "selection:sale.amendment.line,action:"
+msgid "Change Line"
+msgstr ""
+
+msgctxt "selection:sale.amendment.line,action:"
+msgid "Change Parties and Addresses"
+msgstr ""
+
+msgctxt "selection:sale.amendment.line,action:"
+msgid "Change Payment Term"
+msgstr ""
+
+msgctxt "selection:sale.amendment.line,action:"
+msgid "Change Warehouse"
+msgstr ""
+
+msgctxt "selection:sale.amendment.line,action:"
+msgid "Recompute Taxes"
+msgstr ""
diff --git a/modules/sale_amendment/locale/ru.po b/modules/sale_amendment/locale/ru.po
new file mode 100644
index 0000000000..18c95a56fe
--- /dev/null
+++ b/modules/sale_amendment/locale/ru.po
@@ -0,0 +1,178 @@
+#
+msgid ""
+msgstr "Content-Type: text/plain; charset=utf-8\n"
+
+msgctxt "field:sale.amendment,date:"
+msgid "Date"
+msgstr ""
+
+msgctxt "field:sale.amendment,description:"
+msgid "Description"
+msgstr ""
+
+msgctxt "field:sale.amendment,lines:"
+msgid "Lines"
+msgstr ""
+
+msgctxt "field:sale.amendment,sale:"
+msgid "Sale"
+msgstr ""
+
+msgctxt "field:sale.amendment,state:"
+msgid "State"
+msgstr ""
+
+msgctxt "field:sale.amendment.line,action:"
+msgid "Action"
+msgstr ""
+
+msgctxt "field:sale.amendment.line,amendment:"
+msgid "Amendment"
+msgstr ""
+
+msgctxt "field:sale.amendment.line,description:"
+msgid "Description"
+msgstr ""
+
+msgctxt "field:sale.amendment.line,invoice_address:"
+msgid "Invoice Address"
+msgstr ""
+
+msgctxt "field:sale.amendment.line,line:"
+msgid "Line"
+msgstr ""
+
+msgctxt "field:sale.amendment.line,party:"
+msgid "Party"
+msgstr ""
+
+msgctxt "field:sale.amendment.line,payment_term:"
+msgid "Payment Term"
+msgstr ""
+
+msgctxt "field:sale.amendment.line,product:"
+msgid "Product"
+msgstr ""
+
+msgctxt "field:sale.amendment.line,product_uom_category:"
+msgid "Product UoM Category"
+msgstr ""
+
+msgctxt "field:sale.amendment.line,quantity:"
+msgid "Quantity"
+msgstr ""
+
+msgctxt "field:sale.amendment.line,sale:"
+msgid "Sale"
+msgstr ""
+
+msgctxt "field:sale.amendment.line,shipment_address:"
+msgid "Shipment Address"
+msgstr ""
+
+msgctxt "field:sale.amendment.line,shipment_party:"
+msgid "Shipment Party"
+msgstr ""
+
+msgctxt "field:sale.amendment.line,state:"
+msgid "State"
+msgstr ""
+
+msgctxt "field:sale.amendment.line,unit:"
+msgid "Unit"
+msgstr ""
+
+msgctxt "field:sale.amendment.line,unit_digits:"
+msgid "Unit Digits"
+msgstr ""
+
+msgctxt "field:sale.amendment.line,unit_price:"
+msgid "Unit Price"
+msgstr ""
+
+msgctxt "field:sale.amendment.line,warehouse:"
+msgid "Warehouse"
+msgstr ""
+
+msgctxt "field:sale.sale,amendments:"
+msgid "Amendments"
+msgstr ""
+
+msgctxt "model:ir.action,name:act_sale_amendment_form"
+msgid "Amendments"
+msgstr ""
+
+msgctxt ""
+"model:ir.action.act_window.domain,name:act_sale_amendment_form_domain_all"
+msgid "All"
+msgstr ""
+
+msgctxt ""
+"model:ir.action.act_window.domain,name:act_sale_amendment_form_domain_draft"
+msgid "Draft"
+msgstr ""
+
+msgctxt ""
+"model:ir.action.act_window.domain,name:act_sale_amendment_form_domain_validated"
+msgid "Validated"
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_one_sale_at_time"
+msgid ""
+"You cannot validate more than one amendment at the same time for sale "
+"\"%(sale)s\"."
+msgstr ""
+
+msgctxt ""
+"model:ir.model.button,confirm:sale_amendment_validation_amendment_button"
+msgid "Are you sure you want to validate the amendments?"
+msgstr ""
+
+msgctxt ""
+"model:ir.model.button,string:sale_amendment_validation_amendment_button"
+msgid "Validate"
+msgstr ""
+
+msgctxt "model:ir.ui.menu,name:menu_sale_amendment"
+msgid "Amendments"
+msgstr ""
+
+msgctxt "model:res.group,name:group_sale_amendment"
+msgid "Sale Amendment"
+msgstr ""
+
+msgctxt "model:sale.amendment,name:"
+msgid "Sale Amendment"
+msgstr ""
+
+msgctxt "model:sale.amendment.line,name:"
+msgid "Sale Amendment Line"
+msgstr ""
+
+msgctxt "selection:sale.amendment,state:"
+msgid "Draft"
+msgstr ""
+
+msgctxt "selection:sale.amendment,state:"
+msgid "Validated"
+msgstr ""
+
+msgctxt "selection:sale.amendment.line,action:"
+msgid "Change Line"
+msgstr ""
+
+msgctxt "selection:sale.amendment.line,action:"
+msgid "Change Parties and Addresses"
+msgstr ""
+
+msgctxt "selection:sale.amendment.line,action:"
+msgid "Change Payment Term"
+msgstr ""
+
+msgctxt "selection:sale.amendment.line,action:"
+msgid "Change Warehouse"
+msgstr ""
+
+msgctxt "selection:sale.amendment.line,action:"
+msgid "Recompute Taxes"
+msgstr ""
diff --git a/modules/sale_amendment/locale/sl.po b/modules/sale_amendment/locale/sl.po
new file mode 100644
index 0000000000..18c95a56fe
--- /dev/null
+++ b/modules/sale_amendment/locale/sl.po
@@ -0,0 +1,178 @@
+#
+msgid ""
+msgstr "Content-Type: text/plain; charset=utf-8\n"
+
+msgctxt "field:sale.amendment,date:"
+msgid "Date"
+msgstr ""
+
+msgctxt "field:sale.amendment,description:"
+msgid "Description"
+msgstr ""
+
+msgctxt "field:sale.amendment,lines:"
+msgid "Lines"
+msgstr ""
+
+msgctxt "field:sale.amendment,sale:"
+msgid "Sale"
+msgstr ""
+
+msgctxt "field:sale.amendment,state:"
+msgid "State"
+msgstr ""
+
+msgctxt "field:sale.amendment.line,action:"
+msgid "Action"
+msgstr ""
+
+msgctxt "field:sale.amendment.line,amendment:"
+msgid "Amendment"
+msgstr ""
+
+msgctxt "field:sale.amendment.line,description:"
+msgid "Description"
+msgstr ""
+
+msgctxt "field:sale.amendment.line,invoice_address:"
+msgid "Invoice Address"
+msgstr ""
+
+msgctxt "field:sale.amendment.line,line:"
+msgid "Line"
+msgstr ""
+
+msgctxt "field:sale.amendment.line,party:"
+msgid "Party"
+msgstr ""
+
+msgctxt "field:sale.amendment.line,payment_term:"
+msgid "Payment Term"
+msgstr ""
+
+msgctxt "field:sale.amendment.line,product:"
+msgid "Product"
+msgstr ""
+
+msgctxt "field:sale.amendment.line,product_uom_category:"
+msgid "Product UoM Category"
+msgstr ""
+
+msgctxt "field:sale.amendment.line,quantity:"
+msgid "Quantity"
+msgstr ""
+
+msgctxt "field:sale.amendment.line,sale:"
+msgid "Sale"
+msgstr ""
+
+msgctxt "field:sale.amendment.line,shipment_address:"
+msgid "Shipment Address"
+msgstr ""
+
+msgctxt "field:sale.amendment.line,shipment_party:"
+msgid "Shipment Party"
+msgstr ""
+
+msgctxt "field:sale.amendment.line,state:"
+msgid "State"
+msgstr ""
+
+msgctxt "field:sale.amendment.line,unit:"
+msgid "Unit"
+msgstr ""
+
+msgctxt "field:sale.amendment.line,unit_digits:"
+msgid "Unit Digits"
+msgstr ""
+
+msgctxt "field:sale.amendment.line,unit_price:"
+msgid "Unit Price"
+msgstr ""
+
+msgctxt "field:sale.amendment.line,warehouse:"
+msgid "Warehouse"
+msgstr ""
+
+msgctxt "field:sale.sale,amendments:"
+msgid "Amendments"
+msgstr ""
+
+msgctxt "model:ir.action,name:act_sale_amendment_form"
+msgid "Amendments"
+msgstr ""
+
+msgctxt ""
+"model:ir.action.act_window.domain,name:act_sale_amendment_form_domain_all"
+msgid "All"
+msgstr ""
+
+msgctxt ""
+"model:ir.action.act_window.domain,name:act_sale_amendment_form_domain_draft"
+msgid "Draft"
+msgstr ""
+
+msgctxt ""
+"model:ir.action.act_window.domain,name:act_sale_amendment_form_domain_validated"
+msgid "Validated"
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_one_sale_at_time"
+msgid ""
+"You cannot validate more than one amendment at the same time for sale "
+"\"%(sale)s\"."
+msgstr ""
+
+msgctxt ""
+"model:ir.model.button,confirm:sale_amendment_validation_amendment_button"
+msgid "Are you sure you want to validate the amendments?"
+msgstr ""
+
+msgctxt ""
+"model:ir.model.button,string:sale_amendment_validation_amendment_button"
+msgid "Validate"
+msgstr ""
+
+msgctxt "model:ir.ui.menu,name:menu_sale_amendment"
+msgid "Amendments"
+msgstr ""
+
+msgctxt "model:res.group,name:group_sale_amendment"
+msgid "Sale Amendment"
+msgstr ""
+
+msgctxt "model:sale.amendment,name:"
+msgid "Sale Amendment"
+msgstr ""
+
+msgctxt "model:sale.amendment.line,name:"
+msgid "Sale Amendment Line"
+msgstr ""
+
+msgctxt "selection:sale.amendment,state:"
+msgid "Draft"
+msgstr ""
+
+msgctxt "selection:sale.amendment,state:"
+msgid "Validated"
+msgstr ""
+
+msgctxt "selection:sale.amendment.line,action:"
+msgid "Change Line"
+msgstr ""
+
+msgctxt "selection:sale.amendment.line,action:"
+msgid "Change Parties and Addresses"
+msgstr ""
+
+msgctxt "selection:sale.amendment.line,action:"
+msgid "Change Payment Term"
+msgstr ""
+
+msgctxt "selection:sale.amendment.line,action:"
+msgid "Change Warehouse"
+msgstr ""
+
+msgctxt "selection:sale.amendment.line,action:"
+msgid "Recompute Taxes"
+msgstr ""
diff --git a/modules/sale_amendment/locale/tr.po b/modules/sale_amendment/locale/tr.po
new file mode 100644
index 0000000000..18c95a56fe
--- /dev/null
+++ b/modules/sale_amendment/locale/tr.po
@@ -0,0 +1,178 @@
+#
+msgid ""
+msgstr "Content-Type: text/plain; charset=utf-8\n"
+
+msgctxt "field:sale.amendment,date:"
+msgid "Date"
+msgstr ""
+
+msgctxt "field:sale.amendment,description:"
+msgid "Description"
+msgstr ""
+
+msgctxt "field:sale.amendment,lines:"
+msgid "Lines"
+msgstr ""
+
+msgctxt "field:sale.amendment,sale:"
+msgid "Sale"
+msgstr ""
+
+msgctxt "field:sale.amendment,state:"
+msgid "State"
+msgstr ""
+
+msgctxt "field:sale.amendment.line,action:"
+msgid "Action"
+msgstr ""
+
+msgctxt "field:sale.amendment.line,amendment:"
+msgid "Amendment"
+msgstr ""
+
+msgctxt "field:sale.amendment.line,description:"
+msgid "Description"
+msgstr ""
+
+msgctxt "field:sale.amendment.line,invoice_address:"
+msgid "Invoice Address"
+msgstr ""
+
+msgctxt "field:sale.amendment.line,line:"
+msgid "Line"
+msgstr ""
+
+msgctxt "field:sale.amendment.line,party:"
+msgid "Party"
+msgstr ""
+
+msgctxt "field:sale.amendment.line,payment_term:"
+msgid "Payment Term"
+msgstr ""
+
+msgctxt "field:sale.amendment.line,product:"
+msgid "Product"
+msgstr ""
+
+msgctxt "field:sale.amendment.line,product_uom_category:"
+msgid "Product UoM Category"
+msgstr ""
+
+msgctxt "field:sale.amendment.line,quantity:"
+msgid "Quantity"
+msgstr ""
+
+msgctxt "field:sale.amendment.line,sale:"
+msgid "Sale"
+msgstr ""
+
+msgctxt "field:sale.amendment.line,shipment_address:"
+msgid "Shipment Address"
+msgstr ""
+
+msgctxt "field:sale.amendment.line,shipment_party:"
+msgid "Shipment Party"
+msgstr ""
+
+msgctxt "field:sale.amendment.line,state:"
+msgid "State"
+msgstr ""
+
+msgctxt "field:sale.amendment.line,unit:"
+msgid "Unit"
+msgstr ""
+
+msgctxt "field:sale.amendment.line,unit_digits:"
+msgid "Unit Digits"
+msgstr ""
+
+msgctxt "field:sale.amendment.line,unit_price:"
+msgid "Unit Price"
+msgstr ""
+
+msgctxt "field:sale.amendment.line,warehouse:"
+msgid "Warehouse"
+msgstr ""
+
+msgctxt "field:sale.sale,amendments:"
+msgid "Amendments"
+msgstr ""
+
+msgctxt "model:ir.action,name:act_sale_amendment_form"
+msgid "Amendments"
+msgstr ""
+
+msgctxt ""
+"model:ir.action.act_window.domain,name:act_sale_amendment_form_domain_all"
+msgid "All"
+msgstr ""
+
+msgctxt ""
+"model:ir.action.act_window.domain,name:act_sale_amendment_form_domain_draft"
+msgid "Draft"
+msgstr ""
+
+msgctxt ""
+"model:ir.action.act_window.domain,name:act_sale_amendment_form_domain_validated"
+msgid "Validated"
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_one_sale_at_time"
+msgid ""
+"You cannot validate more than one amendment at the same time for sale "
+"\"%(sale)s\"."
+msgstr ""
+
+msgctxt ""
+"model:ir.model.button,confirm:sale_amendment_validation_amendment_button"
+msgid "Are you sure you want to validate the amendments?"
+msgstr ""
+
+msgctxt ""
+"model:ir.model.button,string:sale_amendment_validation_amendment_button"
+msgid "Validate"
+msgstr ""
+
+msgctxt "model:ir.ui.menu,name:menu_sale_amendment"
+msgid "Amendments"
+msgstr ""
+
+msgctxt "model:res.group,name:group_sale_amendment"
+msgid "Sale Amendment"
+msgstr ""
+
+msgctxt "model:sale.amendment,name:"
+msgid "Sale Amendment"
+msgstr ""
+
+msgctxt "model:sale.amendment.line,name:"
+msgid "Sale Amendment Line"
+msgstr ""
+
+msgctxt "selection:sale.amendment,state:"
+msgid "Draft"
+msgstr ""
+
+msgctxt "selection:sale.amendment,state:"
+msgid "Validated"
+msgstr ""
+
+msgctxt "selection:sale.amendment.line,action:"
+msgid "Change Line"
+msgstr ""
+
+msgctxt "selection:sale.amendment.line,action:"
+msgid "Change Parties and Addresses"
+msgstr ""
+
+msgctxt "selection:sale.amendment.line,action:"
+msgid "Change Payment Term"
+msgstr ""
+
+msgctxt "selection:sale.amendment.line,action:"
+msgid "Change Warehouse"
+msgstr ""
+
+msgctxt "selection:sale.amendment.line,action:"
+msgid "Recompute Taxes"
+msgstr ""
diff --git a/modules/sale_amendment/locale/zh_CN.po b/modules/sale_amendment/locale/zh_CN.po
new file mode 100644
index 0000000000..18c95a56fe
--- /dev/null
+++ b/modules/sale_amendment/locale/zh_CN.po
@@ -0,0 +1,178 @@
+#
+msgid ""
+msgstr "Content-Type: text/plain; charset=utf-8\n"
+
+msgctxt "field:sale.amendment,date:"
+msgid "Date"
+msgstr ""
+
+msgctxt "field:sale.amendment,description:"
+msgid "Description"
+msgstr ""
+
+msgctxt "field:sale.amendment,lines:"
+msgid "Lines"
+msgstr ""
+
+msgctxt "field:sale.amendment,sale:"
+msgid "Sale"
+msgstr ""
+
+msgctxt "field:sale.amendment,state:"
+msgid "State"
+msgstr ""
+
+msgctxt "field:sale.amendment.line,action:"
+msgid "Action"
+msgstr ""
+
+msgctxt "field:sale.amendment.line,amendment:"
+msgid "Amendment"
+msgstr ""
+
+msgctxt "field:sale.amendment.line,description:"
+msgid "Description"
+msgstr ""
+
+msgctxt "field:sale.amendment.line,invoice_address:"
+msgid "Invoice Address"
+msgstr ""
+
+msgctxt "field:sale.amendment.line,line:"
+msgid "Line"
+msgstr ""
+
+msgctxt "field:sale.amendment.line,party:"
+msgid "Party"
+msgstr ""
+
+msgctxt "field:sale.amendment.line,payment_term:"
+msgid "Payment Term"
+msgstr ""
+
+msgctxt "field:sale.amendment.line,product:"
+msgid "Product"
+msgstr ""
+
+msgctxt "field:sale.amendment.line,product_uom_category:"
+msgid "Product UoM Category"
+msgstr ""
+
+msgctxt "field:sale.amendment.line,quantity:"
+msgid "Quantity"
+msgstr ""
+
+msgctxt "field:sale.amendment.line,sale:"
+msgid "Sale"
+msgstr ""
+
+msgctxt "field:sale.amendment.line,shipment_address:"
+msgid "Shipment Address"
+msgstr ""
+
+msgctxt "field:sale.amendment.line,shipment_party:"
+msgid "Shipment Party"
+msgstr ""
+
+msgctxt "field:sale.amendment.line,state:"
+msgid "State"
+msgstr ""
+
+msgctxt "field:sale.amendment.line,unit:"
+msgid "Unit"
+msgstr ""
+
+msgctxt "field:sale.amendment.line,unit_digits:"
+msgid "Unit Digits"
+msgstr ""
+
+msgctxt "field:sale.amendment.line,unit_price:"
+msgid "Unit Price"
+msgstr ""
+
+msgctxt "field:sale.amendment.line,warehouse:"
+msgid "Warehouse"
+msgstr ""
+
+msgctxt "field:sale.sale,amendments:"
+msgid "Amendments"
+msgstr ""
+
+msgctxt "model:ir.action,name:act_sale_amendment_form"
+msgid "Amendments"
+msgstr ""
+
+msgctxt ""
+"model:ir.action.act_window.domain,name:act_sale_amendment_form_domain_all"
+msgid "All"
+msgstr ""
+
+msgctxt ""
+"model:ir.action.act_window.domain,name:act_sale_amendment_form_domain_draft"
+msgid "Draft"
+msgstr ""
+
+msgctxt ""
+"model:ir.action.act_window.domain,name:act_sale_amendment_form_domain_validated"
+msgid "Validated"
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_one_sale_at_time"
+msgid ""
+"You cannot validate more than one amendment at the same time for sale "
+"\"%(sale)s\"."
+msgstr ""
+
+msgctxt ""
+"model:ir.model.button,confirm:sale_amendment_validation_amendment_button"
+msgid "Are you sure you want to validate the amendments?"
+msgstr ""
+
+msgctxt ""
+"model:ir.model.button,string:sale_amendment_validation_amendment_button"
+msgid "Validate"
+msgstr ""
+
+msgctxt "model:ir.ui.menu,name:menu_sale_amendment"
+msgid "Amendments"
+msgstr ""
+
+msgctxt "model:res.group,name:group_sale_amendment"
+msgid "Sale Amendment"
+msgstr ""
+
+msgctxt "model:sale.amendment,name:"
+msgid "Sale Amendment"
+msgstr ""
+
+msgctxt "model:sale.amendment.line,name:"
+msgid "Sale Amendment Line"
+msgstr ""
+
+msgctxt "selection:sale.amendment,state:"
+msgid "Draft"
+msgstr ""
+
+msgctxt "selection:sale.amendment,state:"
+msgid "Validated"
+msgstr ""
+
+msgctxt "selection:sale.amendment.line,action:"
+msgid "Change Line"
+msgstr ""
+
+msgctxt "selection:sale.amendment.line,action:"
+msgid "Change Parties and Addresses"
+msgstr ""
+
+msgctxt "selection:sale.amendment.line,action:"
+msgid "Change Payment Term"
+msgstr ""
+
+msgctxt "selection:sale.amendment.line,action:"
+msgid "Change Warehouse"
+msgstr ""
+
+msgctxt "selection:sale.amendment.line,action:"
+msgid "Recompute Taxes"
+msgstr ""
diff --git a/modules/sale_amendment/message.xml b/modules/sale_amendment/message.xml
new file mode 100644
index 0000000000..1e3704d31a
--- /dev/null
+++ b/modules/sale_amendment/message.xml
@@ -0,0 +1,10 @@
+
+
+
+
+
+ You cannot validate more than one amendment at the same time for sale "%(sale)s".
+
+
+
diff --git a/modules/sale_amendment/sale.py b/modules/sale_amendment/sale.py
new file mode 100644
index 0000000000..0712c66385
--- /dev/null
+++ b/modules/sale_amendment/sale.py
@@ -0,0 +1,459 @@
+# This file is part of Tryton. The COPYRIGHT file at the top level of
+# this repository contains the full copyright notices and license terms.
+
+from trytond.i18n import gettext
+from trytond.model import ModelSQL, ModelView, Workflow, fields
+from trytond.pool import Pool, PoolMeta
+from trytond.pyson import Eval, If, Bool
+
+from trytond.modules.product import price_digits
+
+from .exceptions import AmendmentValidateError
+
+
+class Sale(metaclass=PoolMeta):
+ __name__ = 'sale.sale'
+
+ amendments = fields.One2Many(
+ 'sale.amendment', 'sale', "Amendments",
+ states={
+ 'invisible': ((Eval('state') != 'processing')
+ | ~Eval('amendments')),
+ 'readonly': Eval('state') != 'processing',
+ },
+ depends=['state'])
+
+ @classmethod
+ def copy(cls, sales, default=None):
+ if default is None:
+ default = {}
+ else:
+ default = default.copy()
+ default.setdefault('amendments')
+ return super().copy(sales, default=default)
+
+
+class Amendment(Workflow, ModelSQL, ModelView):
+ "Sale Amendment"
+ __name__ = 'sale.amendment'
+
+ sale = fields.Many2One(
+ 'sale.sale', "Sale", required=True, select=True,
+ domain=[
+ ('state', 'in', ['processing', 'done']),
+ ],
+ states={
+ 'readonly': (Eval('state') != 'draft') | Eval('lines', [0]),
+ },
+ depends=['state'])
+ date = fields.Date(
+ "Date", required=True,
+ states={
+ 'readonly': Eval('state') != 'draft',
+ },
+ depends=['state'])
+ description = fields.Char(
+ "Description",
+ states={
+ 'readonly': Eval('state') != 'draft',
+ },
+ depends=['state'])
+ state = fields.Selection([
+ ('draft', "Draft"),
+ ('validated', "Validated"),
+ ], "State", readonly=True, required=True)
+ lines = fields.One2Many(
+ 'sale.amendment.line', 'amendment', "Lines",
+ states={
+ 'readonly': Eval('state') != 'draft',
+ },
+ depends=['state'])
+
+ @classmethod
+ def __setup__(cls):
+ super(Amendment, cls).__setup__()
+ cls._order = [
+ ('date', 'DESC'),
+ ('id', 'DESC'),
+ ]
+ cls._transitions |= {
+ ('draft', 'validated'),
+ }
+ cls._buttons.update({
+ 'validate_amendment': {
+ 'invisible': Eval('state') != 'draft',
+ 'depends': ['state'],
+ },
+ })
+
+ @classmethod
+ def default_date(cls):
+ return Pool().get('ir.date').today()
+
+ @classmethod
+ def default_state(cls):
+ return 'draft'
+
+ @classmethod
+ @ModelView.button
+ @Workflow.transition('validated')
+ def validate_amendment(cls, amendments):
+ pool = Pool()
+ Sale = pool.get('sale.sale')
+ sales = set()
+ for amendment in amendments:
+ sale = amendment.sale
+ if sale in sales:
+ raise AmendmentValidateError(
+ gettext('sale_amendment.msg_one_sale_at_time',
+ sale=sale.rec_name))
+ sales.add(sale)
+ sale.revision += 1
+ for line in amendment.lines:
+ line.apply(sale)
+ # Force saved lines
+ sale.lines = sale.lines
+ # Force recompute cache
+ sale.untaxed_amount_cache = None
+ sale.tax_amount_cache = None
+ sale.total_amount_cache = None
+
+ Sale.save(sales)
+ Sale.store_cache(sales)
+ cls._clear_sale(sales)
+ Sale.__queue__.process(sales)
+
+ @classmethod
+ def _clear_sale(cls, sales):
+ pool = Pool()
+ Invoice = pool.get('account.invoice')
+ InvoiceLine = pool.get('account.invoice.line')
+ Shipment = pool.get('stock.shipment.out')
+ ShipmentReturn = pool.get('stock.shipment.out.return')
+ Move = pool.get('stock.move')
+
+ invoices = set()
+ shipments = set()
+ shipment_returns = set()
+ invoice_lines = set()
+ moves = set()
+ for sale in sales:
+ for invoice in sale.invoices:
+ if invoice.state == 'draft':
+ invoices.add(invoice)
+ for shipment in sale.shipments:
+ if shipment.state in ['draft', 'waiting']:
+ shipments.add(shipment)
+ for shipment_return in sale.shipment_returns:
+ if shipment_return.state == 'draft':
+ shipment_returns.add(shipment_return)
+
+ for line in sale.lines:
+ for invoice_line in line.invoice_lines:
+ if invoice_line.invoice_state == 'draft':
+ invoice_lines.add(invoice_line)
+ moves.update(cls._stock_moves(line))
+
+ shipments_waiting = [s for s in shipments if s.state == 'waiting']
+ Shipment.draft(shipments) # Clear inventory moves
+ InvoiceLine.delete(invoice_lines)
+ Move.delete(moves)
+
+ Invoice.update_taxes([i for i in invoices if i.lines])
+ Invoice.delete([i for i in invoices if not i.lines])
+ Shipment.wait([s for s in shipments_waiting if s.outgoing_moves])
+ Shipment.delete([s for s in shipments if not s.outgoing_moves])
+ ShipmentReturn.delete(
+ [s for s in shipment_returns if not s.incoming_moves])
+
+ @classmethod
+ def _stock_moves(cls, line):
+ for move in line.moves:
+ if move.state == 'draft':
+ yield move
+
+
+class AmendmentLine(ModelSQL, ModelView):
+ "Sale Amendment Line"
+ __name__ = 'sale.amendment.line'
+
+ amendment = fields.Many2One(
+ 'sale.amendment', "Amendment", required=True, ondelete='CASCADE')
+ state = fields.Function(fields.Selection(
+ 'get_states', "State"), 'on_change_with_state')
+ action = fields.Selection([
+ ('taxes', "Recompute Taxes"),
+ ('payment_term', "Change Payment Term"),
+ ('party', "Change Parties and Addresses"),
+ ('warehouse', "Change Warehouse"),
+ ('line', "Change Line"),
+ ], "Action", required=True,
+ states={
+ 'readonly': Eval('state') != 'draft',
+ },
+ depends=['state'])
+
+ sale = fields.Function(fields.Many2One(
+ 'sale.sale', "Sale"), 'on_change_with_sale')
+ line = fields.Many2One(
+ 'sale.line', "Line",
+ domain=[
+ ('type', '=', 'line'),
+ ('sale', '=', Eval('sale', -1)),
+ ],
+ states={
+ 'readonly': Eval('state') != 'draft',
+ 'invisible': Eval('action') != 'line',
+ 'required': Eval('action') == 'line',
+ },
+ depends=['state', 'sale', 'action'])
+
+ payment_term = fields.Many2One(
+ 'account.invoice.payment_term', "Payment Term",
+ states={
+ 'invisible': Eval('action') != 'payment_term',
+ },
+ depends=['action'])
+
+ party = fields.Many2One(
+ 'party.party', "Party",
+ states={
+ 'readonly': Eval('state') != 'draft',
+ 'invisible': Eval('action') != 'party',
+ 'required': Eval('action') == 'party',
+ },
+ depends=['state', 'action'])
+ invoice_address = fields.Many2One(
+ 'party.address', "Invoice Address",
+ domain=[
+ ('party', '=', Eval('party')),
+ ],
+ states={
+ 'readonly': Eval('state') != 'draft',
+ 'invisible': Eval('action') != 'party',
+ 'required': Eval('action') == 'party',
+ },
+ depends=['state', 'action', 'party'])
+ shipment_party = fields.Many2One(
+ 'party.party', "Shipment Party",
+ states={
+ 'readonly': Eval('state') != 'draft',
+ 'invisible': Eval('action') != 'party',
+ },
+ depends=['state', 'action'])
+ shipment_address = fields.Many2One(
+ 'party.address', "Shipment Address",
+ domain=[
+ ('party', '=', If(Eval('shipment_party'),
+ Eval('shipment_party'), Eval('party'))),
+ ],
+ states={
+ 'readonly': Eval('state') != 'draft',
+ 'invisible': Eval('action') != 'party',
+ 'required': Eval('action') == 'party',
+ },
+ depends=['state', 'action', 'party', 'shipment_party'])
+
+ warehouse = fields.Many2One(
+ 'stock.location', "Warehouse",
+ domain=[
+ ('type', '=', 'warehouse'),
+ ],
+ states={
+ 'readonly': Eval('state') != 'draft',
+ 'invisible': Eval('action') != 'warehouse',
+ 'required': Eval('action') == 'warehouse',
+ },
+ depends=['state', 'action'])
+
+ product = fields.Many2One(
+ 'product.product', "Product",
+ domain=[
+ If(Eval('state') == 'draft',
+ ('salable', '=', True),
+ ()),
+ If(Eval('product_uom_category'),
+ ('default_uom_category', '=', Eval('product_uom_category')),
+ ()),
+ ],
+ states={
+ 'readonly': Eval('state') != 'draft',
+ 'invisible': Eval('action') != 'line',
+ },
+ depends=['action', 'state', 'product_uom_category'])
+ quantity = fields.Float(
+ "Quantity",
+ digits=(16, Eval('unit_digits', 2)),
+ states={
+ 'readonly': Eval('state') != 'draft',
+ 'invisible': Eval('action') != 'line',
+ 'required': Eval('action') == 'line',
+ },
+ depends=['unit_digits', 'action'])
+ unit = fields.Many2One(
+ 'product.uom', "Unit", ondelete='RESTRICT',
+ domain=[
+ If(Eval('product_uom_category'),
+ ('category', '=', Eval('product_uom_category')),
+ ()),
+ ],
+ states={
+ 'readonly': Eval('state') != 'draft',
+ 'invisible': Eval('action') != 'line',
+ 'required': Bool(Eval('product')),
+ },
+ depends=['state', 'product_uom_category', 'action', 'product'])
+ unit_price = fields.Numeric(
+ "Unit Price", digits=price_digits,
+ states={
+ 'readonly': Eval('state') != 'draft',
+ 'invisible': Eval('action') != 'line',
+ 'required': Eval('action') == 'line',
+ },
+ depends=['state', 'action'])
+ description = fields.Text(
+ "Description",
+ states={
+ 'readonly': Eval('state') != 'draft',
+ 'invisible': Eval('action') != 'line',
+ },
+ depends=['state', 'action'])
+
+ unit_digits = fields.Function(
+ fields.Integer("Unit Digits"),
+ 'on_change_with_unit_digits')
+ product_uom_category = fields.Function(
+ fields.Many2One('product.uom.category', "Product UoM Category"),
+ 'on_change_with_product_uom_category')
+
+ @classmethod
+ def __setup__(cls):
+ super().__setup__()
+ cls.__access__.add('amendment')
+
+ @fields.depends(
+ 'amendment',
+ '_parent_amendment.sale',
+ '_parent_amendment._parent_sale.payment_term',
+ '_parent_amendment._parent_sale.party',
+ '_parent_amendment._parent_sale.invoice_address',
+ '_parent_amendment._parent_sale.shipment_party',
+ '_parent_amendment._parent_sale.shipment_address',
+ '_parent_amendment._parent_sale.warehouse')
+ def on_change_amendment(self):
+ if self.amendment and self.amendment.sale:
+ self.payment_term = self.amendment.sale.payment_term
+
+ self.party = self.amendment.sale.party
+ self.invoice_address = self.amendment.sale.invoice_address
+ self.shipment_party = self.amendment.sale.shipment_party
+ self.shipment_address = self.amendment.sale.shipment_address
+
+ self.warehouse = self.amendment.sale.warehouse
+
+ @fields.depends(methods=['on_change_amendment'])
+ def on_change_state(self):
+ self.on_change_amendment()
+
+ @classmethod
+ def get_states(cls):
+ pool = Pool()
+ Amendment = pool.get('sale.amendment')
+ return Amendment.fields_get(['state'])['state']['selection']
+
+ @fields.depends(
+ 'amendment',
+ '_parent_amendment.state')
+ def on_change_with_state(self, name=None):
+ if self.amendment:
+ return self.amendment.state
+
+ @fields.depends(methods=['on_change_line', 'on_change_amendment'])
+ def on_change_action(self):
+ self.line = None
+ self.on_change_line()
+ self.on_change_amendment()
+
+ @fields.depends(
+ 'amendment',
+ '_parent_amendment.sale')
+ def on_change_with_sale(self, name=None):
+ if self.amendment and self.amendment.sale:
+ return self.amendment.sale.id
+
+ @fields.depends('line')
+ def on_change_line(self):
+ if self.line:
+ self.product = self.line.product
+ self.quantity = self.line.quantity
+ self.unit = self.line.unit
+ self.unit_price = self.line.unit_price
+ self.description = self.line.description
+ else:
+ self.product = self.quantity = self.unit = self.unit_price = None
+ self.description = None
+
+ @fields.depends('party', 'shipment_party')
+ def on_change_party(self):
+ self.invoice_address = None
+ if not self.shipment_party:
+ self.shipment_address = None
+ if self.party:
+ self.invoice_address = self.party.address_get(type='invoice')
+ if not self.shipment_party:
+ self.shipment_address = self.party.address_get(type='delivery')
+
+ @fields.depends('party', 'shipment_party')
+ def on_change_shipment_party(self):
+ if self.shipment_party:
+ self.shipment_address = self.shipment_party.address_get(
+ type='delivery')
+ elif self.party:
+ self.shipment_address = self.party.address_get(type='delivery')
+
+ @fields.depends('unit')
+ def on_change_with_unit_digits(self, name=None):
+ if self.unit:
+ return self.unit.digits
+
+ @fields.depends('line')
+ def on_change_with_product_uom_category(self, name=None):
+ if self.line:
+ if self.line.product_uom_category:
+ return self.line.product_uom_category.id
+ elif self.line.unit:
+ return self.line.unit.category.id
+
+ def apply(self, sale):
+ assert self.sale == sale
+ sale_line = None
+ if self.line:
+ for line in sale.lines:
+ if self.line == line:
+ sale_line = line
+ break
+ getattr(self, '_apply_%s' % self.action)(sale, sale_line)
+
+ def _apply_taxes(self, sale, sale_line):
+ for line in sale.lines:
+ if line.product:
+ line.taxes = line.compute_taxes(sale.party)
+
+ def _apply_payment_term(self, sale, sale_line):
+ sale.payment_term = self.payment_term
+
+ def _apply_party(self, sale, sale_line):
+ sale.party = self.party
+ sale.invoice_address = self.invoice_address
+ sale.shipment_party = self.shipment_party
+ sale.shipment_address = self.shipment_address
+
+ def _apply_warehouse(self, sale, sale_line):
+ sale.warehouse = self.warehouse
+
+ def _apply_line(self, sale, sale_line):
+ sale_line.product = self.product
+ sale_line.quantity = self.quantity
+ sale_line.unit = self.unit
+ sale_line.unit_price = self.unit_price
+ sale_line.description = self.description
diff --git a/modules/sale_amendment/sale.xml b/modules/sale_amendment/sale.xml
new file mode 100644
index 0000000000..333edfaf3e
--- /dev/null
+++ b/modules/sale_amendment/sale.xml
@@ -0,0 +1,110 @@
+
+
+
+
+
+ Sale Amendment
+
+
+
+
+
+
+
+ sale.sale
+
+ sale_form
+
+
+
+ sale.amendment
+ tree
+ sale_amendment_list
+
+
+
+ sale.amendment
+ form
+ sale_amendment_form
+
+
+
+ Amendments
+ sale.amendment
+
+
+
+
+
+
+
+
+
+
+
+
+ Draft
+
+
+
+
+
+
+ Validated
+
+
+
+
+
+ All
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ validate_amendment
+ Validate
+ Are you sure you want to validate the amendments?
+
+
+
+
+
+
+
+
+ sale.amendment.line
+ tree
+ sale_amendment_line_list
+
+
+
+ sale.amendment.line
+ form
+ sale_amendment_line_form
+
+
+
diff --git a/modules/sale_amendment/setup.py b/modules/sale_amendment/setup.py
new file mode 100755
index 0000000000..7e5557eb7c
--- /dev/null
+++ b/modules/sale_amendment/setup.py
@@ -0,0 +1,149 @@
+#!/usr/bin/env python3
+# This file is part of Tryton. The COPYRIGHT file at the top level of
+# this repository contains the full copyright notices and license terms.
+
+import io
+import os
+import re
+from configparser import ConfigParser
+from setuptools import setup, find_packages
+
+
+def read(fname):
+ return io.open(
+ os.path.join(os.path.dirname(__file__), fname),
+ 'r', encoding='utf-8').read()
+
+
+def get_require_version(name):
+ if minor_version % 2:
+ require = '%s >= %s.%s.dev0, < %s.%s'
+ else:
+ require = '%s >= %s.%s, < %s.%s'
+ require %= (name, major_version, minor_version,
+ major_version, minor_version + 1)
+ return require
+
+
+config = ConfigParser()
+config.read_file(open(os.path.join(os.path.dirname(__file__), 'tryton.cfg')))
+info = dict(config.items('tryton'))
+for key in ('depends', 'extras_depend', 'xml'):
+ if key in info:
+ info[key] = info[key].strip().splitlines()
+version = info.get('version', '0.0.1')
+major_version, minor_version, _ = version.split('.', 2)
+major_version = int(major_version)
+minor_version = int(minor_version)
+name = 'trytond_sale_amendment'
+
+download_url = 'http://downloads.tryton.org/%s.%s/' % (
+ major_version, minor_version)
+if minor_version % 2:
+ version = '%s.%s.dev0' % (major_version, minor_version)
+ download_url = (
+ 'hg+http://hg.tryton.org/modules/%s#egg=%s-%s' % (
+ name[8:], name, version))
+local_version = []
+if os.environ.get('CI_JOB_ID'):
+ local_version.append(os.environ['CI_JOB_ID'])
+else:
+ for build in ['CI_BUILD_NUMBER', 'CI_JOB_NUMBER']:
+ if os.environ.get(build):
+ local_version.append(os.environ[build])
+ else:
+ local_version = []
+ break
+if local_version:
+ version += '+' + '.'.join(local_version)
+
+requires = []
+for dep in info.get('depends', []):
+ if not re.match(r'(ir|res)(\W|$)', dep):
+ requires.append(get_require_version('trytond_%s' % dep))
+requires.append(get_require_version('trytond'))
+
+tests_require = [get_require_version('proteus')]
+dependency_links = []
+if minor_version % 2:
+ dependency_links.append(
+ 'https://trydevpi.tryton.org/?local_version='
+ + '.'.join(local_version))
+
+setup(name=name,
+ version=version,
+ description='Tryton module to amend sales',
+ long_description=read('README.rst'),
+ author='Tryton',
+ author_email='bugs@tryton.org',
+ url='http://www.tryton.org/',
+ download_url=download_url,
+ project_urls={
+ "Bug Tracker": 'https://bugs.tryton.org/',
+ "Documentation": 'https://docs.tryton.org/',
+ "Forum": 'https://www.tryton.org/forum',
+ "Source Code": 'https://hg.tryton.org/modules/sale_amendment',
+ },
+ keywords='tryton sale amendment',
+ package_dir={'trytond.modules.sale_amendment': '.'},
+ packages=(
+ ['trytond.modules.sale_amendment']
+ + ['trytond.modules.sale_amendment.%s' % p for p in find_packages()]
+ ),
+ package_data={
+ 'trytond.modules.sale_amendment': (info.get('xml', [])
+ + ['tryton.cfg', 'view/*.xml', 'locale/*.po', '*.fodt',
+ 'icons/*.svg', 'tests/*.rst']),
+ },
+ classifiers=[
+ 'Development Status :: 5 - Production/Stable',
+ 'Environment :: Plugins',
+ 'Framework :: Tryton',
+ 'Intended Audience :: Developers',
+ 'Intended Audience :: Financial and Insurance Industry',
+ 'Intended Audience :: Legal Industry',
+ 'License :: OSI Approved :: '
+ 'GNU General Public License v3 or later (GPLv3+)',
+ 'Natural Language :: Bulgarian',
+ 'Natural Language :: Catalan',
+ 'Natural Language :: Chinese (Simplified)',
+ 'Natural Language :: Czech',
+ 'Natural Language :: Dutch',
+ 'Natural Language :: English',
+ 'Natural Language :: Finnish',
+ 'Natural Language :: French',
+ 'Natural Language :: German',
+ 'Natural Language :: Hungarian',
+ 'Natural Language :: Indonesian',
+ 'Natural Language :: Italian',
+ 'Natural Language :: Persian',
+ 'Natural Language :: Polish',
+ 'Natural Language :: Portuguese (Brazilian)',
+ 'Natural Language :: Romanian',
+ 'Natural Language :: Russian',
+ 'Natural Language :: Slovenian',
+ 'Natural Language :: Spanish',
+ 'Natural Language :: Turkish',
+ 'Operating System :: OS Independent',
+ 'Programming Language :: Python :: 3',
+ 'Programming Language :: Python :: 3.6',
+ 'Programming Language :: Python :: 3.7',
+ 'Programming Language :: Python :: 3.8',
+ 'Programming Language :: Python :: 3.9',
+ 'Programming Language :: Python :: Implementation :: CPython',
+ 'Programming Language :: Python :: Implementation :: PyPy',
+ 'Topic :: Office/Business',
+ ],
+ license='GPL-3',
+ python_requires='>=3.6',
+ install_requires=requires,
+ dependency_links=dependency_links,
+ zip_safe=False,
+ entry_points="""
+ [trytond.modules]
+ sale_amendment = trytond.modules.sale_amendment
+ """,
+ test_suite='tests',
+ test_loader='trytond.test_loader:Loader',
+ tests_require=tests_require,
+ )
diff --git a/modules/sale_amendment/tests/__init__.py b/modules/sale_amendment/tests/__init__.py
new file mode 100644
index 0000000000..cc49615673
--- /dev/null
+++ b/modules/sale_amendment/tests/__init__.py
@@ -0,0 +1,9 @@
+# This file is part of Tryton. The COPYRIGHT file at the top level of
+# this repository contains the full copyright notices and license terms.
+
+try:
+ from trytond.modules.sale_amendment.tests.test_sale_amendment import suite
+except ImportError:
+ from .test_sale_amendment import suite
+
+__all__ = ['suite']
diff --git a/modules/sale_amendment/tests/scenario_sale_amendment.rst b/modules/sale_amendment/tests/scenario_sale_amendment.rst
new file mode 100644
index 0000000000..f91358962a
--- /dev/null
+++ b/modules/sale_amendment/tests/scenario_sale_amendment.rst
@@ -0,0 +1,171 @@
+=======================
+Sale Amendment Scenario
+=======================
+
+Imports::
+
+ >>> from decimal import Decimal
+ >>> from proteus import Model, Wizard
+ >>> from trytond.tests.tools import activate_modules
+ >>> from trytond.modules.company.tests.tools import create_company, \
+ ... get_company
+ >>> from trytond.modules.account.tests.tools import create_fiscalyear, \
+ ... create_chart, get_accounts
+ >>> from trytond.modules.account_invoice.tests.tools import \
+ ... set_fiscalyear_invoice_sequences
+
+Activate modules::
+
+ >>> config = activate_modules('sale_amendment')
+
+Create company::
+
+ >>> _ = create_company()
+ >>> company = get_company()
+
+Create fiscal year::
+
+ >>> fiscalyear = set_fiscalyear_invoice_sequences(
+ ... create_fiscalyear(company))
+ >>> fiscalyear.click('create_period')
+
+Create chart of accounts::
+
+ >>> _ = create_chart(company)
+ >>> accounts = get_accounts(company)
+ >>> revenue = accounts['revenue']
+ >>> expense = accounts['expense']
+
+Create parties::
+
+ >>> Party = Model.get('party.party')
+ >>> customer1 = Party(name="Customer 1")
+ >>> customer1.save()
+ >>> customer2 = Party(name="Customer 2")
+ >>> customer2.save()
+
+Create account categories::
+
+ >>> ProductCategory = Model.get('product.category')
+ >>> account_category = ProductCategory(name="Account Category")
+ >>> account_category.accounting = True
+ >>> account_category.account_expense = expense
+ >>> account_category.account_revenue = revenue
+ >>> account_category.save()
+
+Create products::
+
+ >>> ProductUom = Model.get('product.uom')
+ >>> unit, = ProductUom.find([('name', '=', 'Unit')])
+ >>> ProductTemplate = Model.get('product.template')
+
+ >>> template = ProductTemplate()
+ >>> template.name = 'product'
+ >>> template.default_uom = unit
+ >>> template.type = 'goods'
+ >>> template.salable = True
+ >>> template.list_price = Decimal('10')
+ >>> template.account_category = account_category
+ >>> _ = template.products.new()
+ >>> template.save()
+ >>> product1, product2 = template.products
+
+Sale first product::
+
+ >>> Sale = Model.get('sale.sale')
+ >>> sale = Sale()
+ >>> sale.party = customer1
+ >>> sale_line = sale.lines.new()
+ >>> sale_line.product = product1
+ >>> sale_line.quantity = 5.0
+ >>> sale_line = sale.lines.new()
+ >>> sale_line.quantity = 1
+ >>> sale_line.unit_price = Decimal('5.0000')
+ >>> sale.click('quote')
+ >>> sale.click('confirm')
+ >>> sale.state
+ 'processing'
+ >>> sale.revision
+ 0
+ >>> sale.total_amount
+ Decimal('55.00')
+ >>> len(sale.shipments), len(sale.invoices)
+ (1, 1)
+
+Add an amendment::
+
+ >>> amendment = sale.amendments.new()
+ >>> line = amendment.lines.new()
+ >>> line.action = 'taxes'
+ >>> line = amendment.lines.new()
+ >>> line.action = 'payment_term'
+ >>> line = amendment.lines.new()
+ >>> line.action = 'party'
+ >>> line.party == customer1
+ True
+ >>> line.party = customer2
+ >>> line = amendment.lines.new()
+ >>> line.action = 'warehouse'
+ >>> bool(line.warehouse)
+ True
+ >>> line = amendment.lines.new()
+ >>> line.action = 'line'
+ >>> line.line = sale.lines[0]
+ >>> line.product == product1
+ True
+ >>> line.product = product2
+ >>> line.quantity
+ 5.0
+ >>> line.quantity = 4.0
+ >>> line.unit_price
+ Decimal('10.0000')
+ >>> line.unit_price = Decimal('9.0000')
+ >>> line = amendment.lines.new()
+ >>> line.action = 'line'
+ >>> line.line = sale.lines[1]
+ >>> line.product
+ >>> line.quantity = 2
+ >>> amendment.save()
+
+Validate amendment::
+
+ >>> amendment.click('validate_amendment')
+ >>> sale.reload()
+ >>> sale.revision
+ 1
+ >>> sale.party == customer2
+ True
+ >>> line = sale.lines[0]
+ >>> line.product == product2
+ True
+ >>> line.quantity
+ 4.0
+ >>> line.unit_price
+ Decimal('9.0000')
+ >>> line = sale.lines[1]
+ >>> line.quantity
+ 2.0
+ >>> sale.total_amount
+ Decimal('46.00')
+
+ >>> shipment, = sale.shipments
+ >>> move, = shipment.outgoing_moves
+ >>> move.product == product2
+ True
+ >>> move.quantity
+ 4.0
+
+ >>> invoice, = sale.invoices
+ >>> line = invoice.lines[0]
+ >>> line.product == product2
+ True
+ >>> line.quantity
+ 4.0
+ >>> line.unit_price
+ Decimal('9.0000')
+ >>> line = invoice.lines[1]
+ >>> line.product
+ >>> line.quantity
+ 2.0
+ >>> line.unit_price
+ Decimal('5.0000')
diff --git a/modules/sale_amendment/tests/test_sale_amendment.py b/modules/sale_amendment/tests/test_sale_amendment.py
new file mode 100644
index 0000000000..1d00c7aa76
--- /dev/null
+++ b/modules/sale_amendment/tests/test_sale_amendment.py
@@ -0,0 +1,28 @@
+# This file is part of Tryton. The COPYRIGHT file at the top level of
+# this repository contains the full copyright notices and license terms.
+
+import unittest
+
+import doctest
+
+from trytond.tests.test_tryton import ModuleTestCase
+from trytond.tests.test_tryton import suite as test_suite
+from trytond.tests.test_tryton import doctest_teardown
+from trytond.tests.test_tryton import doctest_checker
+
+
+class SaleAmendmentTestCase(ModuleTestCase):
+ 'Test Sale Amendment module'
+ module = 'sale_amendment'
+
+
+def suite():
+ suite = test_suite()
+ suite.addTests(unittest.TestLoader().loadTestsFromTestCase(
+ SaleAmendmentTestCase))
+ suite.addTests(doctest.DocFileSuite(
+ 'scenario_sale_amendment.rst',
+ tearDown=doctest_teardown, encoding='utf-8',
+ checker=doctest_checker,
+ optionflags=doctest.REPORT_ONLY_FIRST_FAILURE))
+ return suite
diff --git a/modules/sale_amendment/tox.ini b/modules/sale_amendment/tox.ini
new file mode 100644
index 0000000000..197496c0cb
--- /dev/null
+++ b/modules/sale_amendment/tox.ini
@@ -0,0 +1,15 @@
+[tox]
+envlist = {py36,py37,py38,py39}-{sqlite,postgresql},pypy3-{sqlite,postgresql}
+
+[testenv]
+commands = {envpython} setup.py test
+deps =
+ {py36,py37,py38,py39}-postgresql: psycopg2 >= 2.5
+ pypy3-postgresql: psycopg2cffi >= 2.5
+ py36-sqlite: sqlitebck
+setenv =
+ sqlite: TRYTOND_DATABASE_URI={env:SQLITE_URI:sqlite://}
+ postgresql: TRYTOND_DATABASE_URI={env:POSTGRESQL_URI:postgresql://}
+ sqlite: DB_NAME={env:SQLITE_NAME::memory:}
+ postgresql: DB_NAME={env:POSTGRESQL_NAME:test}
+install_command = pip install --pre --find-links https://trydevpi.tryton.org/?local_version={env:CI_JOB_ID:{env:CI_BUILD_NUMBER}.{env:CI_JOB_NUMBER}} {opts} {packages}
diff --git a/modules/sale_amendment/tryton.cfg b/modules/sale_amendment/tryton.cfg
new file mode 100644
index 0000000000..9b8b2995e7
--- /dev/null
+++ b/modules/sale_amendment/tryton.cfg
@@ -0,0 +1,11 @@
+[tryton]
+version=6.0.2
+depends:
+ account_invoice
+ ir
+ sale
+ sale_history
+ stock
+xml:
+ sale.xml
+ message.xml
diff --git a/modules/sale_amendment/view/sale_amendment_form.xml b/modules/sale_amendment/view/sale_amendment_form.xml
new file mode 100644
index 0000000000..2693731360
--- /dev/null
+++ b/modules/sale_amendment/view/sale_amendment_form.xml
@@ -0,0 +1,20 @@
+
+
+
diff --git a/modules/sale_amendment/view/sale_amendment_line_form.xml b/modules/sale_amendment/view/sale_amendment_line_form.xml
new file mode 100644
index 0000000000..7aa938b889
--- /dev/null
+++ b/modules/sale_amendment/view/sale_amendment_line_form.xml
@@ -0,0 +1,38 @@
+
+
+
diff --git a/modules/sale_amendment/view/sale_amendment_line_list.xml b/modules/sale_amendment/view/sale_amendment_line_list.xml
new file mode 100644
index 0000000000..997e900ed9
--- /dev/null
+++ b/modules/sale_amendment/view/sale_amendment_line_list.xml
@@ -0,0 +1,8 @@
+
+
+
+
+
+
+
diff --git a/modules/sale_amendment/view/sale_amendment_list.xml b/modules/sale_amendment/view/sale_amendment_list.xml
new file mode 100644
index 0000000000..99c7b87d04
--- /dev/null
+++ b/modules/sale_amendment/view/sale_amendment_list.xml
@@ -0,0 +1,10 @@
+
+
+
+
+
+
+
+
+
diff --git a/modules/sale_amendment/view/sale_form.xml b/modules/sale_amendment/view/sale_form.xml
new file mode 100644
index 0000000000..0eed820e85
--- /dev/null
+++ b/modules/sale_amendment/view/sale_form.xml
@@ -0,0 +1,10 @@
+
+
+
+
+
+
+
+
+
diff --git a/modules/sale_complaint/.drone.yml b/modules/sale_complaint/.drone.yml
new file mode 100644
index 0000000000..2049d30a49
--- /dev/null
+++ b/modules/sale_complaint/.drone.yml
@@ -0,0 +1,68 @@
+clone:
+ hg:
+ image: plugins/hg
+ environment:
+ - HG_SHARE_POOL=/root/.cache/hg
+ volumes:
+ - cache:/root/.cache
+
+pipeline:
+ tox:
+ image: ${IMAGE}
+ environment:
+ - CFLAGS=-O0
+ - DB_CACHE=/cache
+ - TOX_TESTENV_PASSENV=CFLAGS DB_CACHE CI_BUILD_NUMBER CI_JOB_NUMBER CI_JOB_ID
+ - POSTGRESQL_URI=postgresql://postgres@postgresql:5432/
+ commands:
+ - echo "[extensions]" >> /root/.hgrc
+ - echo "hgext.share =" >> /root/.hgrc
+ - echo "[share]" >> /root/.hgrc
+ - echo "pool = /root/.cache/hg" >> /root/.hgrc
+ - pip install tox
+ - tox -e "${TOXENV}-${DATABASE}"
+ volumes:
+ - cache:/root/.cache
+ check_dist:
+ image: ${IMAGE}
+ commands:
+ - pip install twine
+ - python setup.py sdist
+ - twine check dist/*
+
+services:
+ postgresql:
+ image: postgres
+ environment:
+ - POSTGRES_HOST_AUTH_METHOD=trust
+ command: "-c fsync=off -c synchronous_commit=off -c full_page_writes=off"
+ when:
+ matrix:
+ DATABASE: postgresql
+
+matrix:
+ include:
+ - IMAGE: python:3.6
+ TOXENV: py36
+ DATABASE: sqlite
+ - IMAGE: python:3.6
+ TOXENV: py36
+ DATABASE: postgresql
+ - IMAGE: python:3.7
+ TOXENV: py37
+ DATABASE: sqlite
+ - IMAGE: python:3.7
+ TOXENV: py37
+ DATABASE: postgresql
+ - IMAGE: python:3.8
+ TOXENV: py38
+ DATABASE: sqlite
+ - IMAGE: python:3.8
+ TOXENV: py38
+ DATABASE: postgresql
+ - IMAGE: python:3.9
+ TOXENV: py39
+ DATABASE: sqlite
+ - IMAGE: python:3.9
+ TOXENV: py39
+ DATABASE: postgresql
diff --git a/modules/sale_complaint/.flake8 b/modules/sale_complaint/.flake8
new file mode 100644
index 0000000000..fa6b4f66d1
--- /dev/null
+++ b/modules/sale_complaint/.flake8
@@ -0,0 +1,2 @@
+[flake8]
+ignore=E123,E124,E126,E128,E741,W503
diff --git a/modules/sale_complaint/CHANGELOG b/modules/sale_complaint/CHANGELOG
new file mode 100644
index 0000000000..6699e82986
--- /dev/null
+++ b/modules/sale_complaint/CHANGELOG
@@ -0,0 +1,52 @@
+Version 6.0.2 - 2022-10-17
+* Bug fixes (see mercurial logs for details)
+
+Version 6.0.1 - 2022-06-15
+* Bug fixes (see mercurial logs for details)
+
+Version 6.0.0 - 2021-05-03
+* Bug fixes (see mercurial logs for details)
+* Make an invoice correction for credit note action
+* Compute amount of complaint action
+* Add active field to complaint type
+
+Version 5.8.0 - 2020-11-02
+* Bug fixes (see mercurial logs for details)
+* Remove support for Python 3.5
+
+Version 5.6.0 - 2020-05-04
+* Bug fixes (see mercurial logs for details)
+* Allow partial return sale and credit invoice
+* Allow entering origin before customer
+
+Version 5.4.0 - 2019-11-04
+* Bug fixes (see mercurial logs for details)
+* Use processing delay to process approved complaint
+* Allow reset to draft approved and rejected complaint
+
+Version 5.2.0 - 2019-05-06
+* Bug fixes (see mercurial logs for details)
+
+Version 5.0.0 - 2018-10-01
+* Bug fixes (see mercurial logs for details)
+* Remove support for Python 2.7
+
+Version 4.8.0 - 2018-04-23
+* Bug fixes (see mercurial logs for details)
+
+Version 4.6.0 - 2017-10-30
+* Bug fixes (see mercurial logs for details)
+
+Version 4.4.0 - 2017-05-01
+* Bug fixes (see mercurial logs for details)
+
+Version 4.2.0 - 2016-11-28
+* Bug fixes (see mercurial logs for details)
+
+Version 4.0.0 - 2016-05-02
+* Bug fixes (see mercurial logs for details)
+* Rename Complaint reference into number and add reference
+* Add Python3 support
+
+Version 3.8.0 - 2015-11-02
+* Initial release
diff --git a/modules/sale_complaint/COPYRIGHT b/modules/sale_complaint/COPYRIGHT
new file mode 100644
index 0000000000..b97a61c3dd
--- /dev/null
+++ b/modules/sale_complaint/COPYRIGHT
@@ -0,0 +1,15 @@
+Copyright (C) 2015-2022 Cédric Krier.
+Copyright (C) 2015-2022 B2CK SPRL.
+
+This program is free software: you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation, either version 3 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program. If not, see .
diff --git a/modules/sale_complaint/LICENSE b/modules/sale_complaint/LICENSE
new file mode 100644
index 0000000000..94a9ed024d
--- /dev/null
+++ b/modules/sale_complaint/LICENSE
@@ -0,0 +1,674 @@
+ GNU GENERAL PUBLIC LICENSE
+ Version 3, 29 June 2007
+
+ Copyright (C) 2007 Free Software Foundation, Inc.
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+ Preamble
+
+ The GNU General Public License is a free, copyleft license for
+software and other kinds of works.
+
+ The licenses for most software and other practical works are designed
+to take away your freedom to share and change the works. By contrast,
+the GNU General Public License is intended to guarantee your freedom to
+share and change all versions of a program--to make sure it remains free
+software for all its users. We, the Free Software Foundation, use the
+GNU General Public License for most of our software; it applies also to
+any other work released this way by its authors. You can apply it to
+your programs, too.
+
+ When we speak of free software, we are referring to freedom, not
+price. Our General Public Licenses are designed to make sure that you
+have the freedom to distribute copies of free software (and charge for
+them if you wish), that you receive source code or can get it if you
+want it, that you can change the software or use pieces of it in new
+free programs, and that you know you can do these things.
+
+ To protect your rights, we need to prevent others from denying you
+these rights or asking you to surrender the rights. Therefore, you have
+certain responsibilities if you distribute copies of the software, or if
+you modify it: responsibilities to respect the freedom of others.
+
+ For example, if you distribute copies of such a program, whether
+gratis or for a fee, you must pass on to the recipients the same
+freedoms that you received. You must make sure that they, too, receive
+or can get the source code. And you must show them these terms so they
+know their rights.
+
+ Developers that use the GNU GPL protect your rights with two steps:
+(1) assert copyright on the software, and (2) offer you this License
+giving you legal permission to copy, distribute and/or modify it.
+
+ For the developers' and authors' protection, the GPL clearly explains
+that there is no warranty for this free software. For both users' and
+authors' sake, the GPL requires that modified versions be marked as
+changed, so that their problems will not be attributed erroneously to
+authors of previous versions.
+
+ Some devices are designed to deny users access to install or run
+modified versions of the software inside them, although the manufacturer
+can do so. This is fundamentally incompatible with the aim of
+protecting users' freedom to change the software. The systematic
+pattern of such abuse occurs in the area of products for individuals to
+use, which is precisely where it is most unacceptable. Therefore, we
+have designed this version of the GPL to prohibit the practice for those
+products. If such problems arise substantially in other domains, we
+stand ready to extend this provision to those domains in future versions
+of the GPL, as needed to protect the freedom of users.
+
+ Finally, every program is threatened constantly by software patents.
+States should not allow patents to restrict development and use of
+software on general-purpose computers, but in those that do, we wish to
+avoid the special danger that patents applied to a free program could
+make it effectively proprietary. To prevent this, the GPL assures that
+patents cannot be used to render the program non-free.
+
+ The precise terms and conditions for copying, distribution and
+modification follow.
+
+ TERMS AND CONDITIONS
+
+ 0. Definitions.
+
+ "This License" refers to version 3 of the GNU General Public License.
+
+ "Copyright" also means copyright-like laws that apply to other kinds of
+works, such as semiconductor masks.
+
+ "The Program" refers to any copyrightable work licensed under this
+License. Each licensee is addressed as "you". "Licensees" and
+"recipients" may be individuals or organizations.
+
+ To "modify" a work means to copy from or adapt all or part of the work
+in a fashion requiring copyright permission, other than the making of an
+exact copy. The resulting work is called a "modified version" of the
+earlier work or a work "based on" the earlier work.
+
+ A "covered work" means either the unmodified Program or a work based
+on the Program.
+
+ To "propagate" a work means to do anything with it that, without
+permission, would make you directly or secondarily liable for
+infringement under applicable copyright law, except executing it on a
+computer or modifying a private copy. Propagation includes copying,
+distribution (with or without modification), making available to the
+public, and in some countries other activities as well.
+
+ To "convey" a work means any kind of propagation that enables other
+parties to make or receive copies. Mere interaction with a user through
+a computer network, with no transfer of a copy, is not conveying.
+
+ An interactive user interface displays "Appropriate Legal Notices"
+to the extent that it includes a convenient and prominently visible
+feature that (1) displays an appropriate copyright notice, and (2)
+tells the user that there is no warranty for the work (except to the
+extent that warranties are provided), that licensees may convey the
+work under this License, and how to view a copy of this License. If
+the interface presents a list of user commands or options, such as a
+menu, a prominent item in the list meets this criterion.
+
+ 1. Source Code.
+
+ The "source code" for a work means the preferred form of the work
+for making modifications to it. "Object code" means any non-source
+form of a work.
+
+ A "Standard Interface" means an interface that either is an official
+standard defined by a recognized standards body, or, in the case of
+interfaces specified for a particular programming language, one that
+is widely used among developers working in that language.
+
+ The "System Libraries" of an executable work include anything, other
+than the work as a whole, that (a) is included in the normal form of
+packaging a Major Component, but which is not part of that Major
+Component, and (b) serves only to enable use of the work with that
+Major Component, or to implement a Standard Interface for which an
+implementation is available to the public in source code form. A
+"Major Component", in this context, means a major essential component
+(kernel, window system, and so on) of the specific operating system
+(if any) on which the executable work runs, or a compiler used to
+produce the work, or an object code interpreter used to run it.
+
+ The "Corresponding Source" for a work in object code form means all
+the source code needed to generate, install, and (for an executable
+work) run the object code and to modify the work, including scripts to
+control those activities. However, it does not include the work's
+System Libraries, or general-purpose tools or generally available free
+programs which are used unmodified in performing those activities but
+which are not part of the work. For example, Corresponding Source
+includes interface definition files associated with source files for
+the work, and the source code for shared libraries and dynamically
+linked subprograms that the work is specifically designed to require,
+such as by intimate data communication or control flow between those
+subprograms and other parts of the work.
+
+ The Corresponding Source need not include anything that users
+can regenerate automatically from other parts of the Corresponding
+Source.
+
+ The Corresponding Source for a work in source code form is that
+same work.
+
+ 2. Basic Permissions.
+
+ All rights granted under this License are granted for the term of
+copyright on the Program, and are irrevocable provided the stated
+conditions are met. This License explicitly affirms your unlimited
+permission to run the unmodified Program. The output from running a
+covered work is covered by this License only if the output, given its
+content, constitutes a covered work. This License acknowledges your
+rights of fair use or other equivalent, as provided by copyright law.
+
+ You may make, run and propagate covered works that you do not
+convey, without conditions so long as your license otherwise remains
+in force. You may convey covered works to others for the sole purpose
+of having them make modifications exclusively for you, or provide you
+with facilities for running those works, provided that you comply with
+the terms of this License in conveying all material for which you do
+not control copyright. Those thus making or running the covered works
+for you must do so exclusively on your behalf, under your direction
+and control, on terms that prohibit them from making any copies of
+your copyrighted material outside their relationship with you.
+
+ Conveying under any other circumstances is permitted solely under
+the conditions stated below. Sublicensing is not allowed; section 10
+makes it unnecessary.
+
+ 3. Protecting Users' Legal Rights From Anti-Circumvention Law.
+
+ No covered work shall be deemed part of an effective technological
+measure under any applicable law fulfilling obligations under article
+11 of the WIPO copyright treaty adopted on 20 December 1996, or
+similar laws prohibiting or restricting circumvention of such
+measures.
+
+ When you convey a covered work, you waive any legal power to forbid
+circumvention of technological measures to the extent such circumvention
+is effected by exercising rights under this License with respect to
+the covered work, and you disclaim any intention to limit operation or
+modification of the work as a means of enforcing, against the work's
+users, your or third parties' legal rights to forbid circumvention of
+technological measures.
+
+ 4. Conveying Verbatim Copies.
+
+ You may convey verbatim copies of the Program's source code as you
+receive it, in any medium, provided that you conspicuously and
+appropriately publish on each copy an appropriate copyright notice;
+keep intact all notices stating that this License and any
+non-permissive terms added in accord with section 7 apply to the code;
+keep intact all notices of the absence of any warranty; and give all
+recipients a copy of this License along with the Program.
+
+ You may charge any price or no price for each copy that you convey,
+and you may offer support or warranty protection for a fee.
+
+ 5. Conveying Modified Source Versions.
+
+ You may convey a work based on the Program, or the modifications to
+produce it from the Program, in the form of source code under the
+terms of section 4, provided that you also meet all of these conditions:
+
+ a) The work must carry prominent notices stating that you modified
+ it, and giving a relevant date.
+
+ b) The work must carry prominent notices stating that it is
+ released under this License and any conditions added under section
+ 7. This requirement modifies the requirement in section 4 to
+ "keep intact all notices".
+
+ c) You must license the entire work, as a whole, under this
+ License to anyone who comes into possession of a copy. This
+ License will therefore apply, along with any applicable section 7
+ additional terms, to the whole of the work, and all its parts,
+ regardless of how they are packaged. This License gives no
+ permission to license the work in any other way, but it does not
+ invalidate such permission if you have separately received it.
+
+ d) If the work has interactive user interfaces, each must display
+ Appropriate Legal Notices; however, if the Program has interactive
+ interfaces that do not display Appropriate Legal Notices, your
+ work need not make them do so.
+
+ A compilation of a covered work with other separate and independent
+works, which are not by their nature extensions of the covered work,
+and which are not combined with it such as to form a larger program,
+in or on a volume of a storage or distribution medium, is called an
+"aggregate" if the compilation and its resulting copyright are not
+used to limit the access or legal rights of the compilation's users
+beyond what the individual works permit. Inclusion of a covered work
+in an aggregate does not cause this License to apply to the other
+parts of the aggregate.
+
+ 6. Conveying Non-Source Forms.
+
+ You may convey a covered work in object code form under the terms
+of sections 4 and 5, provided that you also convey the
+machine-readable Corresponding Source under the terms of this License,
+in one of these ways:
+
+ a) Convey the object code in, or embodied in, a physical product
+ (including a physical distribution medium), accompanied by the
+ Corresponding Source fixed on a durable physical medium
+ customarily used for software interchange.
+
+ b) Convey the object code in, or embodied in, a physical product
+ (including a physical distribution medium), accompanied by a
+ written offer, valid for at least three years and valid for as
+ long as you offer spare parts or customer support for that product
+ model, to give anyone who possesses the object code either (1) a
+ copy of the Corresponding Source for all the software in the
+ product that is covered by this License, on a durable physical
+ medium customarily used for software interchange, for a price no
+ more than your reasonable cost of physically performing this
+ conveying of source, or (2) access to copy the
+ Corresponding Source from a network server at no charge.
+
+ c) Convey individual copies of the object code with a copy of the
+ written offer to provide the Corresponding Source. This
+ alternative is allowed only occasionally and noncommercially, and
+ only if you received the object code with such an offer, in accord
+ with subsection 6b.
+
+ d) Convey the object code by offering access from a designated
+ place (gratis or for a charge), and offer equivalent access to the
+ Corresponding Source in the same way through the same place at no
+ further charge. You need not require recipients to copy the
+ Corresponding Source along with the object code. If the place to
+ copy the object code is a network server, the Corresponding Source
+ may be on a different server (operated by you or a third party)
+ that supports equivalent copying facilities, provided you maintain
+ clear directions next to the object code saying where to find the
+ Corresponding Source. Regardless of what server hosts the
+ Corresponding Source, you remain obligated to ensure that it is
+ available for as long as needed to satisfy these requirements.
+
+ e) Convey the object code using peer-to-peer transmission, provided
+ you inform other peers where the object code and Corresponding
+ Source of the work are being offered to the general public at no
+ charge under subsection 6d.
+
+ A separable portion of the object code, whose source code is excluded
+from the Corresponding Source as a System Library, need not be
+included in conveying the object code work.
+
+ A "User Product" is either (1) a "consumer product", which means any
+tangible personal property which is normally used for personal, family,
+or household purposes, or (2) anything designed or sold for incorporation
+into a dwelling. In determining whether a product is a consumer product,
+doubtful cases shall be resolved in favor of coverage. For a particular
+product received by a particular user, "normally used" refers to a
+typical or common use of that class of product, regardless of the status
+of the particular user or of the way in which the particular user
+actually uses, or expects or is expected to use, the product. A product
+is a consumer product regardless of whether the product has substantial
+commercial, industrial or non-consumer uses, unless such uses represent
+the only significant mode of use of the product.
+
+ "Installation Information" for a User Product means any methods,
+procedures, authorization keys, or other information required to install
+and execute modified versions of a covered work in that User Product from
+a modified version of its Corresponding Source. The information must
+suffice to ensure that the continued functioning of the modified object
+code is in no case prevented or interfered with solely because
+modification has been made.
+
+ If you convey an object code work under this section in, or with, or
+specifically for use in, a User Product, and the conveying occurs as
+part of a transaction in which the right of possession and use of the
+User Product is transferred to the recipient in perpetuity or for a
+fixed term (regardless of how the transaction is characterized), the
+Corresponding Source conveyed under this section must be accompanied
+by the Installation Information. But this requirement does not apply
+if neither you nor any third party retains the ability to install
+modified object code on the User Product (for example, the work has
+been installed in ROM).
+
+ The requirement to provide Installation Information does not include a
+requirement to continue to provide support service, warranty, or updates
+for a work that has been modified or installed by the recipient, or for
+the User Product in which it has been modified or installed. Access to a
+network may be denied when the modification itself materially and
+adversely affects the operation of the network or violates the rules and
+protocols for communication across the network.
+
+ Corresponding Source conveyed, and Installation Information provided,
+in accord with this section must be in a format that is publicly
+documented (and with an implementation available to the public in
+source code form), and must require no special password or key for
+unpacking, reading or copying.
+
+ 7. Additional Terms.
+
+ "Additional permissions" are terms that supplement the terms of this
+License by making exceptions from one or more of its conditions.
+Additional permissions that are applicable to the entire Program shall
+be treated as though they were included in this License, to the extent
+that they are valid under applicable law. If additional permissions
+apply only to part of the Program, that part may be used separately
+under those permissions, but the entire Program remains governed by
+this License without regard to the additional permissions.
+
+ When you convey a copy of a covered work, you may at your option
+remove any additional permissions from that copy, or from any part of
+it. (Additional permissions may be written to require their own
+removal in certain cases when you modify the work.) You may place
+additional permissions on material, added by you to a covered work,
+for which you have or can give appropriate copyright permission.
+
+ Notwithstanding any other provision of this License, for material you
+add to a covered work, you may (if authorized by the copyright holders of
+that material) supplement the terms of this License with terms:
+
+ a) Disclaiming warranty or limiting liability differently from the
+ terms of sections 15 and 16 of this License; or
+
+ b) Requiring preservation of specified reasonable legal notices or
+ author attributions in that material or in the Appropriate Legal
+ Notices displayed by works containing it; or
+
+ c) Prohibiting misrepresentation of the origin of that material, or
+ requiring that modified versions of such material be marked in
+ reasonable ways as different from the original version; or
+
+ d) Limiting the use for publicity purposes of names of licensors or
+ authors of the material; or
+
+ e) Declining to grant rights under trademark law for use of some
+ trade names, trademarks, or service marks; or
+
+ f) Requiring indemnification of licensors and authors of that
+ material by anyone who conveys the material (or modified versions of
+ it) with contractual assumptions of liability to the recipient, for
+ any liability that these contractual assumptions directly impose on
+ those licensors and authors.
+
+ All other non-permissive additional terms are considered "further
+restrictions" within the meaning of section 10. If the Program as you
+received it, or any part of it, contains a notice stating that it is
+governed by this License along with a term that is a further
+restriction, you may remove that term. If a license document contains
+a further restriction but permits relicensing or conveying under this
+License, you may add to a covered work material governed by the terms
+of that license document, provided that the further restriction does
+not survive such relicensing or conveying.
+
+ If you add terms to a covered work in accord with this section, you
+must place, in the relevant source files, a statement of the
+additional terms that apply to those files, or a notice indicating
+where to find the applicable terms.
+
+ Additional terms, permissive or non-permissive, may be stated in the
+form of a separately written license, or stated as exceptions;
+the above requirements apply either way.
+
+ 8. Termination.
+
+ You may not propagate or modify a covered work except as expressly
+provided under this License. Any attempt otherwise to propagate or
+modify it is void, and will automatically terminate your rights under
+this License (including any patent licenses granted under the third
+paragraph of section 11).
+
+ However, if you cease all violation of this License, then your
+license from a particular copyright holder is reinstated (a)
+provisionally, unless and until the copyright holder explicitly and
+finally terminates your license, and (b) permanently, if the copyright
+holder fails to notify you of the violation by some reasonable means
+prior to 60 days after the cessation.
+
+ Moreover, your license from a particular copyright holder is
+reinstated permanently if the copyright holder notifies you of the
+violation by some reasonable means, this is the first time you have
+received notice of violation of this License (for any work) from that
+copyright holder, and you cure the violation prior to 30 days after
+your receipt of the notice.
+
+ Termination of your rights under this section does not terminate the
+licenses of parties who have received copies or rights from you under
+this License. If your rights have been terminated and not permanently
+reinstated, you do not qualify to receive new licenses for the same
+material under section 10.
+
+ 9. Acceptance Not Required for Having Copies.
+
+ You are not required to accept this License in order to receive or
+run a copy of the Program. Ancillary propagation of a covered work
+occurring solely as a consequence of using peer-to-peer transmission
+to receive a copy likewise does not require acceptance. However,
+nothing other than this License grants you permission to propagate or
+modify any covered work. These actions infringe copyright if you do
+not accept this License. Therefore, by modifying or propagating a
+covered work, you indicate your acceptance of this License to do so.
+
+ 10. Automatic Licensing of Downstream Recipients.
+
+ Each time you convey a covered work, the recipient automatically
+receives a license from the original licensors, to run, modify and
+propagate that work, subject to this License. You are not responsible
+for enforcing compliance by third parties with this License.
+
+ An "entity transaction" is a transaction transferring control of an
+organization, or substantially all assets of one, or subdividing an
+organization, or merging organizations. If propagation of a covered
+work results from an entity transaction, each party to that
+transaction who receives a copy of the work also receives whatever
+licenses to the work the party's predecessor in interest had or could
+give under the previous paragraph, plus a right to possession of the
+Corresponding Source of the work from the predecessor in interest, if
+the predecessor has it or can get it with reasonable efforts.
+
+ You may not impose any further restrictions on the exercise of the
+rights granted or affirmed under this License. For example, you may
+not impose a license fee, royalty, or other charge for exercise of
+rights granted under this License, and you may not initiate litigation
+(including a cross-claim or counterclaim in a lawsuit) alleging that
+any patent claim is infringed by making, using, selling, offering for
+sale, or importing the Program or any portion of it.
+
+ 11. Patents.
+
+ A "contributor" is a copyright holder who authorizes use under this
+License of the Program or a work on which the Program is based. The
+work thus licensed is called the contributor's "contributor version".
+
+ A contributor's "essential patent claims" are all patent claims
+owned or controlled by the contributor, whether already acquired or
+hereafter acquired, that would be infringed by some manner, permitted
+by this License, of making, using, or selling its contributor version,
+but do not include claims that would be infringed only as a
+consequence of further modification of the contributor version. For
+purposes of this definition, "control" includes the right to grant
+patent sublicenses in a manner consistent with the requirements of
+this License.
+
+ Each contributor grants you a non-exclusive, worldwide, royalty-free
+patent license under the contributor's essential patent claims, to
+make, use, sell, offer for sale, import and otherwise run, modify and
+propagate the contents of its contributor version.
+
+ In the following three paragraphs, a "patent license" is any express
+agreement or commitment, however denominated, not to enforce a patent
+(such as an express permission to practice a patent or covenant not to
+sue for patent infringement). To "grant" such a patent license to a
+party means to make such an agreement or commitment not to enforce a
+patent against the party.
+
+ If you convey a covered work, knowingly relying on a patent license,
+and the Corresponding Source of the work is not available for anyone
+to copy, free of charge and under the terms of this License, through a
+publicly available network server or other readily accessible means,
+then you must either (1) cause the Corresponding Source to be so
+available, or (2) arrange to deprive yourself of the benefit of the
+patent license for this particular work, or (3) arrange, in a manner
+consistent with the requirements of this License, to extend the patent
+license to downstream recipients. "Knowingly relying" means you have
+actual knowledge that, but for the patent license, your conveying the
+covered work in a country, or your recipient's use of the covered work
+in a country, would infringe one or more identifiable patents in that
+country that you have reason to believe are valid.
+
+ If, pursuant to or in connection with a single transaction or
+arrangement, you convey, or propagate by procuring conveyance of, a
+covered work, and grant a patent license to some of the parties
+receiving the covered work authorizing them to use, propagate, modify
+or convey a specific copy of the covered work, then the patent license
+you grant is automatically extended to all recipients of the covered
+work and works based on it.
+
+ A patent license is "discriminatory" if it does not include within
+the scope of its coverage, prohibits the exercise of, or is
+conditioned on the non-exercise of one or more of the rights that are
+specifically granted under this License. You may not convey a covered
+work if you are a party to an arrangement with a third party that is
+in the business of distributing software, under which you make payment
+to the third party based on the extent of your activity of conveying
+the work, and under which the third party grants, to any of the
+parties who would receive the covered work from you, a discriminatory
+patent license (a) in connection with copies of the covered work
+conveyed by you (or copies made from those copies), or (b) primarily
+for and in connection with specific products or compilations that
+contain the covered work, unless you entered into that arrangement,
+or that patent license was granted, prior to 28 March 2007.
+
+ Nothing in this License shall be construed as excluding or limiting
+any implied license or other defenses to infringement that may
+otherwise be available to you under applicable patent law.
+
+ 12. No Surrender of Others' Freedom.
+
+ If conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License. If you cannot convey a
+covered work so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you may
+not convey it at all. For example, if you agree to terms that obligate you
+to collect a royalty for further conveying from those to whom you convey
+the Program, the only way you could satisfy both those terms and this
+License would be to refrain entirely from conveying the Program.
+
+ 13. Use with the GNU Affero General Public License.
+
+ Notwithstanding any other provision of this License, you have
+permission to link or combine any covered work with a work licensed
+under version 3 of the GNU Affero General Public License into a single
+combined work, and to convey the resulting work. The terms of this
+License will continue to apply to the part which is the covered work,
+but the special requirements of the GNU Affero General Public License,
+section 13, concerning interaction through a network will apply to the
+combination as such.
+
+ 14. Revised Versions of this License.
+
+ The Free Software Foundation may publish revised and/or new versions of
+the GNU General Public License from time to time. Such new versions will
+be similar in spirit to the present version, but may differ in detail to
+address new problems or concerns.
+
+ Each version is given a distinguishing version number. If the
+Program specifies that a certain numbered version of the GNU General
+Public License "or any later version" applies to it, you have the
+option of following the terms and conditions either of that numbered
+version or of any later version published by the Free Software
+Foundation. If the Program does not specify a version number of the
+GNU General Public License, you may choose any version ever published
+by the Free Software Foundation.
+
+ If the Program specifies that a proxy can decide which future
+versions of the GNU General Public License can be used, that proxy's
+public statement of acceptance of a version permanently authorizes you
+to choose that version for the Program.
+
+ Later license versions may give you additional or different
+permissions. However, no additional obligations are imposed on any
+author or copyright holder as a result of your choosing to follow a
+later version.
+
+ 15. Disclaimer of Warranty.
+
+ THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY
+APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT
+HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY
+OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO,
+THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM
+IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF
+ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
+
+ 16. Limitation of Liability.
+
+ IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS
+THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY
+GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE
+USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF
+DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD
+PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS),
+EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF
+SUCH DAMAGES.
+
+ 17. Interpretation of Sections 15 and 16.
+
+ If the disclaimer of warranty and limitation of liability provided
+above cannot be given local legal effect according to their terms,
+reviewing courts shall apply local law that most closely approximates
+an absolute waiver of all civil liability in connection with the
+Program, unless a warranty or assumption of liability accompanies a
+copy of the Program in return for a fee.
+
+ END OF TERMS AND CONDITIONS
+
+ How to Apply These Terms to Your New Programs
+
+ If you develop a new program, and you want it to be of the greatest
+possible use to the public, the best way to achieve this is to make it
+free software which everyone can redistribute and change under these terms.
+
+ To do so, attach the following notices to the program. It is safest
+to attach them to the start of each source file to most effectively
+state the exclusion of warranty; and each file should have at least
+the "copyright" line and a pointer to where the full notice is found.
+
+
+ Copyright (C)
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see .
+
+Also add information on how to contact you by electronic and paper mail.
+
+ If the program does terminal interaction, make it output a short
+notice like this when it starts in an interactive mode:
+
+ Copyright (C)
+ This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
+ This is free software, and you are welcome to redistribute it
+ under certain conditions; type `show c' for details.
+
+The hypothetical commands `show w' and `show c' should show the appropriate
+parts of the General Public License. Of course, your program's commands
+might be different; for a GUI interface, you would use an "about box".
+
+ You should also get your employer (if you work as a programmer) or school,
+if any, to sign a "copyright disclaimer" for the program, if necessary.
+For more information on this, and how to apply and follow the GNU GPL, see
+.
+
+ The GNU General Public License does not permit incorporating your program
+into proprietary programs. If your program is a subroutine library, you
+may consider it more useful to permit linking proprietary applications with
+the library. If this is what you want to do, use the GNU Lesser General
+Public License instead of this License. But first, please read
+.
diff --git a/modules/sale_complaint/MANIFEST.in b/modules/sale_complaint/MANIFEST.in
new file mode 100644
index 0000000000..94499680c6
--- /dev/null
+++ b/modules/sale_complaint/MANIFEST.in
@@ -0,0 +1,6 @@
+include CHANGELOG
+include COPYRIGHT
+include LICENSE
+include README.rst
+include doc/*
+include icons/LICENSE
diff --git a/modules/sale_complaint/README.rst b/modules/sale_complaint/README.rst
new file mode 120000
index 0000000000..176d9c2695
--- /dev/null
+++ b/modules/sale_complaint/README.rst
@@ -0,0 +1 @@
+doc/index.rst
\ No newline at end of file
diff --git a/modules/sale_complaint/__init__.py b/modules/sale_complaint/__init__.py
new file mode 100644
index 0000000000..3b86c8acf9
--- /dev/null
+++ b/modules/sale_complaint/__init__.py
@@ -0,0 +1,21 @@
+# This file is part of Tryton. The COPYRIGHT file at the top level of
+# this repository contains the full copyright notices and license terms.
+
+from trytond.pool import Pool
+from . import complaint
+from . import sale
+from . import account
+
+
+def register():
+ Pool.register(
+ complaint.Type,
+ complaint.Complaint,
+ complaint.Action,
+ complaint.Action_SaleLine,
+ complaint.Action_InvoiceLine,
+ sale.Configuration,
+ sale.ConfigurationSequence,
+ sale.Sale,
+ account.InvoiceLine,
+ module='sale_complaint', type_='model')
diff --git a/modules/sale_complaint/account.py b/modules/sale_complaint/account.py
new file mode 100644
index 0000000000..3050d59406
--- /dev/null
+++ b/modules/sale_complaint/account.py
@@ -0,0 +1,12 @@
+# This file is part of Tryton. The COPYRIGHT file at the top level of
+# this repository contains the full copyright notices and license terms.
+
+from trytond.pool import PoolMeta
+
+
+class InvoiceLine(metaclass=PoolMeta):
+ __name__ = 'account.invoice.line'
+
+ @classmethod
+ def _get_origin(cls):
+ return super(InvoiceLine, cls)._get_origin() + ['sale.complaint']
diff --git a/modules/sale_complaint/complaint.py b/modules/sale_complaint/complaint.py
new file mode 100644
index 0000000000..9c637aae4f
--- /dev/null
+++ b/modules/sale_complaint/complaint.py
@@ -0,0 +1,812 @@
+# This file is part of Tryton. The COPYRIGHT file at the top level of
+# this repository contains the full copyright notices and license terms.
+
+from collections import defaultdict
+from decimal import Decimal
+
+from trytond.i18n import gettext
+from trytond.model import ModelSQL, ModelView, Workflow, fields
+from trytond.model import DeactivableMixin
+from trytond.model.exceptions import AccessError
+from trytond.pyson import Eval, If, Bool
+from trytond.pool import Pool
+from trytond.transaction import Transaction
+
+from trytond.modules.product import price_digits
+
+
+class Type(DeactivableMixin, ModelSQL, ModelView):
+ 'Customer Complaint Type'
+ __name__ = 'sale.complaint.type'
+
+ name = fields.Char('Name', required=True)
+ origin = fields.Many2One('ir.model', 'Origin', required=True,
+ domain=[('model', 'in', ['sale.sale', 'sale.line',
+ 'account.invoice', 'account.invoice.line'])])
+
+
+class Complaint(Workflow, ModelSQL, ModelView):
+ 'Customer Complaint'
+ __name__ = 'sale.complaint'
+ _rec_name = 'number'
+
+ _states = {
+ 'readonly': Eval('state') != 'draft',
+ }
+ _depends = ['state']
+
+ number = fields.Char('Number', readonly=True, select=True)
+ reference = fields.Char('Reference', select=True)
+ date = fields.Date('Date', states=_states, depends=_depends)
+ customer = fields.Many2One(
+ 'party.party', "Customer", required=True, states=_states,
+ context={
+ 'company': Eval('company', -1),
+ },
+ depends=_depends + ['company'])
+ address = fields.Many2One('party.address', 'Address',
+ domain=[('party', '=', Eval('customer'))],
+ states=_states, depends=_depends + ['customer'])
+ company = fields.Many2One('company.company', 'Company', required=True,
+ states={
+ 'readonly': _states['readonly'] | Eval('origin'),
+ },
+ depends=_depends + ['origin'])
+ employee = fields.Many2One('company.employee', 'Employee',
+ states=_states, depends=_depends)
+ type = fields.Many2One('sale.complaint.type', 'Type', required=True,
+ states=_states, depends=_depends)
+ origin = fields.Reference('Origin', selection='get_origin',
+ states={
+ 'readonly': ((Eval('state') != 'draft')
+ | Bool(Eval('actions', [0]))),
+ 'required': Bool(Eval('origin_model')),
+ },
+ depends=['state', 'customer', 'origin_model', 'company'])
+ origin_id = fields.Function(fields.Integer('Origin ID'),
+ 'on_change_with_origin_id')
+ origin_model = fields.Function(fields.Char('Origin Model'),
+ 'on_change_with_origin_model')
+ description = fields.Text('Description', states=_states, depends=_depends)
+ actions = fields.One2Many('sale.complaint.action', 'complaint', 'Actions',
+ states={
+ 'readonly': ((Eval('state') != 'draft')
+ | (If(~Eval('origin_id', 0), 0, Eval('origin_id', 0)) <= 0)),
+ },
+ depends=['state', 'origin_model', 'origin_id'])
+ state = fields.Selection([
+ ('draft', 'Draft'),
+ ('waiting', 'Waiting'),
+ ('approved', 'Approved'),
+ ('rejected', 'Rejected'),
+ ('done', 'Done'),
+ ('cancelled', 'Cancelled'),
+ ], 'State', readonly=True, required=True)
+
+ @classmethod
+ def __setup__(cls):
+ super(Complaint, cls).__setup__()
+ cls._order.insert(0, ('date', 'DESC'))
+ cls._transitions |= set((
+ ('draft', 'waiting'),
+ ('waiting', 'draft'),
+ ('waiting', 'approved'),
+ ('waiting', 'rejected'),
+ ('approved', 'done'),
+ ('approved', 'draft'),
+ ('draft', 'cancelled'),
+ ('waiting', 'cancelled'),
+ ('done', 'draft'),
+ ('rejected', 'draft'),
+ ('cancelled', 'draft'),
+ ))
+ cls._buttons.update({
+ 'cancel': {
+ 'invisible': ~Eval('state').in_(['draft', 'waiting']),
+ 'depends': ['state'],
+ },
+ 'draft': {
+ 'invisible': ~Eval('state').in_(
+ ['waiting', 'done', 'cancelled']),
+ 'icon': If(Eval('state').in_(['done', 'cancelled']),
+ 'tryton-undo', 'tryton-back'),
+ 'depends': ['state'],
+ },
+ 'wait': {
+ 'invisible': ~Eval('state').in_(['draft']),
+ 'depends': ['state'],
+ },
+ 'approve': {
+ 'invisible': ~Eval('state').in_(['waiting']),
+ 'depends': ['state'],
+ },
+ 'reject': {
+ 'invisible': ~Eval('state').in_(['waiting']),
+ 'depends': ['state'],
+ },
+ 'process': {
+ 'invisible': ~Eval('state').in_(['approved']),
+ 'depends': ['state'],
+ },
+ })
+
+ origin_domain = []
+ for model, domain in cls._origin_domains().items():
+ origin_domain = If(Eval('origin_model') == model,
+ domain, origin_domain)
+ cls.origin.domain = [origin_domain]
+
+ actions_domains = cls._actions_domains()
+ actions_domain = [('action', 'in', actions_domains.pop(None))]
+ for model, actions in actions_domains.items():
+ actions_domain = If(Eval('origin_model') == model,
+ [('action', 'in', actions)], actions_domain)
+ cls.actions.domain = [actions_domain]
+
+ @classmethod
+ def __register__(cls, module_name):
+ table_h = cls.__table_handler__(module_name)
+
+ # Migration from 3.8: rename reference into number
+ if (table_h.column_exist('reference')
+ and not table_h.column_exist('number')):
+ table_h.column_rename('reference', 'number')
+
+ super(Complaint, cls).__register__(module_name)
+
+ @classmethod
+ def _origin_domains(cls):
+ return {
+ 'sale.sale': [
+ If(Eval('customer'),
+ ('party', '=', Eval('customer')),
+ ()),
+ ('company', '=', Eval('company')),
+ ('state', 'in', ['confirmed', 'processing', 'done']),
+ ],
+ 'sale.line': [
+ ('type', '=', 'line'),
+ If(Eval('customer'),
+ ('sale.party', '=', Eval('customer')),
+ ()),
+ ('sale.company', '=', Eval('company')),
+ ('sale.state', 'in', ['confirmed', 'processing', 'done']),
+ ],
+ 'account.invoice': [
+ If(Eval('customer'),
+ ('party', '=', Eval('customer')),
+ ()),
+ ('company', '=', Eval('company')),
+ ('type', '=', 'out'),
+ ('state', 'in', ['posted', 'paid']),
+ ],
+ 'account.invoice.line': [
+ ('type', '=', 'line'),
+ If(Eval('customer'),
+ ('invoice.party', '=', Eval('customer')),
+ ()),
+ ('invoice.company', '=', Eval('company')),
+ ('invoice.type', '=', 'out'),
+ ('invoice.state', 'in', ['posted', 'paid']),
+ ],
+ }
+
+ @classmethod
+ def _actions_domains(cls):
+ return {
+ None: [],
+ 'sale.sale': ['sale_return'],
+ 'sale.line': ['sale_return'],
+ 'account.invoice': ['credit_note'],
+ 'account.invoice.line': ['credit_note'],
+ }
+
+ @staticmethod
+ def default_date():
+ pool = Pool()
+ Date = pool.get('ir.date')
+ return Date.today()
+
+ @staticmethod
+ def default_company():
+ return Transaction().context.get('company')
+
+ @staticmethod
+ def default_state():
+ return 'draft'
+
+ @fields.depends('type')
+ def get_origin(self):
+ if self.type:
+ origin = self.type.origin
+ return [('', ''), (origin.model, origin.name)]
+ else:
+ return []
+
+ @fields.depends('origin', 'customer')
+ def on_change_origin(self):
+ pool = Pool()
+ Sale = pool.get('sale.sale')
+ SaleLine = pool.get('sale.line')
+ Invoice = pool.get('account.invoice')
+ InvoiceLine = pool.get('account.invoice.line')
+ if not self.customer and self.origin and self.origin.id >= 0:
+ if isinstance(self.origin, Sale):
+ self.customer = self.origin.party
+ elif isinstance(self.origin, SaleLine):
+ self.customer = self.origin.sale.party
+ elif isinstance(self.origin, Invoice):
+ self.customer = self.origin.party
+ elif isinstance(self.origin, InvoiceLine) and self.origin.invoice:
+ self.customer = self.origin.invoice.party
+
+ @fields.depends('origin')
+ def on_change_with_origin_id(self, name=None):
+ if self.origin:
+ return self.origin.id
+
+ @fields.depends('origin')
+ def on_change_with_origin_model(self, name=None):
+ if self.origin:
+ return self.origin.__class__.__name__
+
+ @classmethod
+ def view_attributes(cls):
+ return super().view_attributes() + [
+ ('/tree', 'visual', If(Eval('state') == 'cancelled', 'muted', '')),
+ ]
+
+ @classmethod
+ def create(cls, vlist):
+ pool = Pool()
+ Configuration = pool.get('sale.configuration')
+
+ config = Configuration(1)
+ vlist = [v.copy() for v in vlist]
+ default_company = cls.default_company()
+ for values in vlist:
+ if values.get('number') is None:
+ values['number'] = config.get_multivalue(
+ 'complaint_sequence',
+ company=values.get('company', default_company)).get()
+ return super(Complaint, cls).create(vlist)
+
+ @classmethod
+ def copy(cls, complaints, default=None):
+ if default is None:
+ default = {}
+ else:
+ default = default.copy()
+ default.setdefault('number', None)
+ return super(Complaint, cls).copy(complaints, default=default)
+
+ @classmethod
+ def delete(cls, complaints):
+ for complaint in complaints:
+ if complaint.state != 'draft':
+ raise AccessError(
+ gettext('sale_complaint.msg_complaint_delete_draft',
+ complaint=complaint.rec_name))
+ super(Complaint, cls).delete(complaints)
+
+ @classmethod
+ @ModelView.button
+ @Workflow.transition('cancelled')
+ def cancel(cls, complaints):
+ pass
+
+ @classmethod
+ @ModelView.button
+ @Workflow.transition('draft')
+ def draft(cls, complaints):
+ pass
+
+ @classmethod
+ @ModelView.button
+ @Workflow.transition('waiting')
+ def wait(cls, complaints):
+ pass
+
+ @classmethod
+ @ModelView.button
+ @Workflow.transition('approved')
+ def approve(cls, complaints):
+ pool = Pool()
+ Configuration = pool.get('sale.configuration')
+ config = Configuration(1)
+ with Transaction().set_context(
+ queue_name='sale',
+ queue_scheduled_at=config.sale_process_after):
+ cls.__queue__.process(complaints)
+
+ @classmethod
+ @ModelView.button
+ @Workflow.transition('rejected')
+ def reject(cls, complaints):
+ pass
+
+ @classmethod
+ @ModelView.button
+ @Workflow.transition('done')
+ def process(cls, complaints):
+ pool = Pool()
+ Action = pool.get('sale.complaint.action')
+ results = defaultdict(list)
+ actions = defaultdict(list)
+ for complaint in complaints:
+ for action in complaint.actions:
+ if action.result:
+ continue
+ result = action.do()
+ results[result.__class__].append(result)
+ actions[result.__class__].append(action)
+ for kls, records in results.items():
+ kls.save(records)
+ for action, record in zip(actions[kls], records):
+ action.result = record
+ Action.save(sum(list(actions.values()), []))
+
+
+class Action(ModelSQL, ModelView):
+ 'Customer Complaint Action'
+ __name__ = 'sale.complaint.action'
+
+ _states = {
+ 'readonly': ((Eval('complaint_state') != 'draft')
+ | Bool(Eval('result'))),
+ }
+ _depends = ['complaint_state', 'result']
+ _line_states = {
+ 'invisible': ~Eval('_parent_complaint', {}
+ ).get('origin_model', 'sale.line').in_(
+ ['sale.line', 'account.invoice.line']),
+ 'readonly': _states['readonly'],
+ }
+ _line_depends = _depends
+
+ complaint = fields.Many2One(
+ 'sale.complaint', 'Complaint', required=True, ondelete='CASCADE',
+ states=_states, depends=_depends)
+ action = fields.Selection([
+ ('sale_return', 'Create Sale Return'),
+ ('credit_note', 'Create Credit Note'),
+ ], 'Action', states=_states)
+
+ sale_lines = fields.One2Many(
+ 'sale.complaint.action-sale.line', 'action', "Sale Lines",
+ states={
+ 'invisible': Eval('_parent_complaint', {}
+ ).get('origin_model', 'sale.sale') != 'sale.sale',
+ 'readonly': _states['readonly'],
+ },
+ depends=_depends,
+ help='Leave empty for all lines.')
+
+ invoice_lines = fields.One2Many(
+ 'sale.complaint.action-account.invoice.line', 'action',
+ "Invoice Lines",
+ states={
+ 'invisible': Eval('_parent_complaint', {}
+ ).get('origin_model', 'account.invoice.line'
+ ) != 'account.invoice',
+ 'readonly': _states['readonly'],
+ },
+ depends=_depends,
+ help='Leave empty for all lines.')
+
+ quantity = fields.Float('Quantity',
+ digits=(16, Eval('unit_digits', 2)),
+ states=_line_states, depends=_line_depends + ['unit_digits'],
+ help='Leave empty for the same quantity.')
+ unit = fields.Function(fields.Many2One('product.uom', 'Unit',
+ states=_line_states, depends=_line_depends),
+ 'on_change_with_unit')
+ unit_digits = fields.Function(
+ fields.Integer('Unit Digits'), 'on_change_with_unit_digits')
+ unit_price = fields.Numeric('Unit Price', digits=price_digits,
+ states=_line_states, depends=_line_depends,
+ help='Leave empty for the same price.')
+
+ amount = fields.Function(fields.Numeric(
+ "Amount", digits=(16, Eval('currency_digits', 2)),
+ depends=['currency_digits']),
+ 'on_change_with_amount')
+ currency = fields.Function(fields.Many2One(
+ 'currency.currency', "Currency"),
+ 'on_change_with_currency')
+ currency_digits = fields.Function(fields.Integer("Currency Digits"),
+ 'on_change_with_currency_digits')
+
+ result = fields.Reference('Result', selection='get_result', readonly=True)
+
+ complaint_state = fields.Function(
+ fields.Selection('get_complaint_states', "Complaint State"),
+ 'on_change_with_complaint_state')
+
+ @classmethod
+ def __setup__(cls):
+ super().__setup__()
+ cls.__access__.add('complaint')
+
+ @fields.depends('complaint',
+ '_parent_complaint.origin_model', '_parent_complaint.origin')
+ def on_change_with_unit(self, name=None):
+ if (self.complaint
+ and self.complaint.origin_model in {
+ 'sale.line', 'account.invoice.line'}):
+ return self.complaint.origin.unit.id
+
+ @fields.depends('complaint',
+ '_parent_complaint.origin_model', '_parent_complaint.origin')
+ def on_change_with_unit_digits(self, name=None):
+ if (self.complaint
+ and self.complaint.origin_model in {
+ 'sale.line', 'account.invoice.line'}):
+ return self.complaint.origin.unit.digits
+
+ @fields.depends(
+ 'quantity', 'unit_price', 'currency', 'sale_lines', 'invoice_lines',
+ 'complaint', '_parent_complaint.origin_model',
+ '_parent_complaint.origin')
+ def on_change_with_amount(self, name=None):
+ if self.complaint:
+ if self.complaint.origin_model in {
+ 'sale.line', 'account.invoice.line'}:
+ if self.quantity is not None:
+ quantity = self.quantity
+ else:
+ quantity = self.complaint.origin.quantity
+ if self.unit_price is not None:
+ unit_price = self.unit_price
+ else:
+ unit_price = self.complaint.origin.unit_price
+ amount = Decimal(str(quantity)) * unit_price
+ if self.currency:
+ amount = self.currency.round(amount)
+ return amount
+ elif self.complaint.origin_model == 'sale.sale':
+ if not self.sale_lines:
+ if self.complaint and self.complaint.origin:
+ return self.complaint.origin.untaxed_amount
+ else:
+ return sum(
+ getattr(l, 'amount', None) or Decimal(0)
+ for l in self.sale_lines)
+ elif self.complaint.origin_model == 'account.invoice':
+ if not self.invoice_lines:
+ if self.complaint and self.complaint.origin:
+ return self.complaint.origin.untaxed_amount
+ else:
+ return sum(
+ getattr(l, 'amount', None) or Decimal(0)
+ for l in self.invoice_lines)
+
+ @fields.depends(
+ 'complaint',
+ '_parent_complaint.origin_model', '_parent_complaint.origin')
+ def on_change_with_currency(self, name=None):
+ if (self.complaint
+ and self.complaint.origin_model in {
+ 'sale.sale', 'sale.line',
+ 'account.invoice', 'account.invoice.line'}):
+ return self.complaint.origin.currency.id
+
+ @fields.depends(
+ 'complaint',
+ '_parent_complaint.origin_model', '_parent_complaint.origin')
+ def on_change_with_currency_digits(self, name=None):
+ if (self.complaint
+ and self.complaint.origin_model in {
+ 'sale.sale', 'sale.line',
+ 'account.invoice', 'account.invoice.line'}):
+ return self.complaint.origin.currency.digits
+
+ @classmethod
+ def get_complaint_states(cls):
+ pool = Pool()
+ Complaint = pool.get('sale.complaint')
+ return Complaint.fields_get(['state'])['state']['selection']
+
+ @fields.depends('complaint', '_parent_complaint.state')
+ def on_change_with_complaint_state(self, name=None):
+ if self.complaint:
+ return self.complaint.state
+
+ @classmethod
+ def _get_result(cls):
+ 'Return list of Model names for result Reference'
+ return ['sale.sale', 'account.invoice']
+
+ @classmethod
+ def get_result(cls):
+ pool = Pool()
+ Model = pool.get('ir.model')
+ get_name = Model.get_name
+ models = cls._get_result()
+ return [(None, '')] + [(m, get_name(m)) for m in models]
+
+ @classmethod
+ def copy(cls, actions, default=None):
+ if default is None:
+ default = {}
+ else:
+ default = default.copy()
+ default.setdefault('result', None)
+ return super().copy(actions, default=default)
+
+ def do(self):
+ return getattr(self, 'do_%s' % self.action)()
+
+ def do_sale_return(self):
+ pool = Pool()
+ Sale = pool.get('sale.sale')
+ Line = pool.get('sale.line')
+
+ if isinstance(self.complaint.origin, (Sale, Line)):
+ default = {}
+ if isinstance(self.complaint.origin, Sale):
+ sale = self.complaint.origin
+ if self.sale_lines:
+ sale_lines = [l.line for l in self.sale_lines]
+ line2qty = {
+ l.line.id: l.get_quantity() for l in self.sale_lines}
+ line2price = {
+ l.line.id: l.get_unit_price() for l in self.sale_lines}
+ default['quantity'] = lambda o: line2qty.get(o['id'])
+ default['unit_price'] = lambda o: line2price.get(o['id'])
+ else:
+ sale_lines = [l for l in sale.lines if l.type == 'line']
+ elif isinstance(self.complaint.origin, Line):
+ sale_line = self.complaint.origin
+ sale = sale_line.sale
+ sale_lines = [sale_line]
+ if self.quantity is not None:
+ default['quantity'] = self.quantity
+ if self.unit_price is not None:
+ default['unit_price'] = self.unit_price
+ return_sale, = Sale.copy([sale], default={'lines': None})
+ default['sale'] = return_sale.id
+ Line.copy(sale_lines, default=default)
+ else:
+ return
+ return_sale.origin = self.complaint
+ for line in return_sale.lines:
+ if line.type == 'line':
+ line.quantity *= -1
+ return_sale.lines = return_sale.lines # Force saving
+ return return_sale
+
+ def do_credit_note(self):
+ pool = Pool()
+ Invoice = pool.get('account.invoice')
+ Line = pool.get('account.invoice.line')
+
+ if isinstance(self.complaint.origin, (Invoice, Line)):
+ line2qty = line2price = {}
+ if isinstance(self.complaint.origin, Invoice):
+ invoice = self.complaint.origin
+ if self.invoice_lines:
+ invoice_lines = [l.line for l in self.invoice_lines]
+ line2qty = {l.line: l.quantity
+ for l in self.invoice_lines
+ if l.quantity is not None}
+ line2price = {l.line: l.unit_price
+ for l in self.invoice_lines
+ if l.unit_price is not None}
+ else:
+ invoice_lines = [
+ l for l in invoice.lines if l.type == 'line']
+ elif isinstance(self.complaint.origin, Line):
+ invoice_line = self.complaint.origin
+ invoice = invoice_line.invoice
+ invoice_lines = [invoice_line]
+ if self.quantity is not None:
+ line2qty = {invoice_line: self.quantity}
+ if self.unit_price is not None:
+ line2price = {invoice_line: self.unit_price}
+ with Transaction().set_context(_account_invoice_correction=True):
+ credit_note, = Invoice.copy([invoice], default={
+ 'lines': [],
+ })
+ # Copy each line one by one to get negative and positive lines
+ # following each other
+ for invoice_line in invoice_lines:
+ qty = line2qty.get(invoice_line, invoice_line.quantity)
+ unit_price = invoice_line.unit_price - line2price.get(
+ invoice_line, invoice_line.unit_price)
+ Line.copy([invoice_line], default={
+ 'invoice': credit_note.id,
+ 'quantity': -qty,
+ 'origin': str(self.complaint),
+ })
+ credit_line, = Line.copy([invoice_line], default={
+ 'invoice': credit_note.id,
+ 'quantity': qty,
+ 'unit_price': unit_price,
+ 'origin': str(self.complaint),
+ })
+ credit_note.update_taxes()
+ else:
+ return
+ return credit_note
+
+ @classmethod
+ def delete(cls, actions):
+ for action in actions:
+ if action.result:
+ raise AccessError(
+ gettext('sale_complaint.msg_action_delete_result',
+ action=action.rec_name))
+ super(Action, cls).delete(actions)
+
+
+class _Action_Line:
+
+ _states = {
+ 'readonly': (
+ (Eval('complaint_state') != 'draft')
+ | Bool(Eval('_parent_action.result', True))),
+ }
+ _depends = ['complaint_state']
+
+ action = fields.Many2One('sale.complaint.action', 'Action',
+ ondelete='CASCADE', select=True, required=True)
+ quantity = fields.Float(
+ "Quantity",
+ digits=(16, Eval('unit_digits', 2)),
+ states=_states,
+ depends=_depends + ['unit_digits'])
+ unit = fields.Function(
+ fields.Many2One('product.uom', "Unit"), 'on_change_with_unit')
+ unit_digits = fields.Function(
+ fields.Integer("Unit Digits"), 'on_change_with_unit_digits')
+ unit_price = fields.Numeric(
+ "Unit Price", digits=price_digits, states=_states, depends=_depends,
+ help='Leave empty for the same price.')
+
+ amount = fields.Function(fields.Numeric(
+ "Amount", digits=(16, Eval('currency_digits', 2)),
+ depends=['currency_digits']),
+ 'on_change_with_amount')
+ currency = fields.Function(fields.Many2One(
+ 'currency.currency', "Currency"),
+ 'on_change_with_currency')
+ currency_digits = fields.Function(fields.Integer("Currency Digits"),
+ 'on_change_with_currency_digits')
+
+ complaint_state = fields.Function(
+ fields.Selection('get_complaint_states', "Complaint State"),
+ 'on_change_with_complaint_state')
+ complaint_origin_id = fields.Function(
+ fields.Integer("Complaint Origin ID"),
+ 'on_change_with_complaint_origin_id')
+
+ @classmethod
+ def __setup__(cls):
+ super().__setup__()
+ cls.__access__.add('action')
+
+ def on_change_with_unit(self, name=None):
+ raise NotImplementedError
+
+ def on_change_with_unit_digits(self, name=None):
+ raise NotImplementedError
+
+ @fields.depends('currency', methods=['get_quantity', 'get_unit_price'])
+ def on_change_with_amount(self, name=None):
+ quantity = self.get_quantity() or 0
+ unit_price = self.get_unit_price() or Decimal(0)
+ amount = Decimal(str(quantity)) * unit_price
+ if self.currency:
+ amount = self.currency.round(amount)
+ return amount
+
+ def get_quantity(self):
+ raise NotImplementedError
+
+ def get_unit_price(self):
+ raise NotImplementedError
+
+ @fields.depends('action', '_parent_action.currency')
+ def on_change_with_currency(self, name=None):
+ if self.action and self.action.currency:
+ return self.action.currency.id
+
+ @fields.depends('action', '_parent_action.currency')
+ def on_change_with_currency_digits(self, name=None):
+ if self.action and self.action.currency:
+ return self.action.currency.digits
+
+ @classmethod
+ def get_complaint_states(cls):
+ pool = Pool()
+ Complaint = pool.get('sale.complaint')
+ return Complaint.fields_get(['state'])['state']['selection']
+
+ @fields.depends('action', '_parent_action.complaint',
+ '_parent_action._parent_complaint.state')
+ def on_change_with_complaint_state(self, name=None):
+ if self.action and self.action.complaint:
+ return self.action.complaint.state
+
+ @fields.depends('action', '_parent_action.complaint',
+ '_parent_action._parent_complaint.origin_id')
+ def on_change_with_complaint_origin_id(self, name=None):
+ if self.action and self.action.complaint:
+ return self.action.complaint.origin_id
+
+
+class Action_SaleLine(_Action_Line, ModelView, ModelSQL):
+ 'Customer Complaint Action - Sale Line'
+ __name__ = 'sale.complaint.action-sale.line'
+
+ line = fields.Many2One(
+ 'sale.line', "Sale Line",
+ ondelete='RESTRICT', required=True,
+ domain=[
+ ('type', '=', 'line'),
+ ('sale', '=', Eval('complaint_origin_id', -1)),
+ ],
+ depends=['complaint_origin_id'])
+
+ @fields.depends('line')
+ def on_change_with_unit(self, name=None):
+ if self.line and self.line.unit:
+ return self.line.unit.id
+
+ @fields.depends('line')
+ def on_change_with_unit_digits(self, name=None):
+ if self.line:
+ return self.line.unit.digits
+
+ @fields.depends('quantity', 'line')
+ def get_quantity(self):
+ if self.quantity is not None:
+ return self.quantity
+ elif self.line:
+ return self.line.quantity
+
+ @fields.depends('unit_price', 'line')
+ def get_unit_price(self):
+ if self.unit_price is not None:
+ return self.unit_price
+ elif self.line:
+ return self.line.unit_price
+
+
+class Action_InvoiceLine(_Action_Line, ModelView, ModelSQL):
+ 'Customer Complaint Action - Invoice Line'
+ __name__ = 'sale.complaint.action-account.invoice.line'
+
+ line = fields.Many2One(
+ 'account.invoice.line', 'Invoice Line',
+ ondelete='RESTRICT', required=True,
+ domain=[
+ ('type', '=', 'line'),
+ ('invoice', '=', Eval('complaint_origin_id', -1)),
+ ],
+ depends=['complaint_origin_id'])
+
+ @fields.depends('line')
+ def on_change_with_unit(self, name=None):
+ if self.line and self.line.unit:
+ return self.line.unit.id
+
+ @fields.depends('line')
+ def on_change_with_unit_digits(self, name=None):
+ if self.line:
+ return self.line.unit.digits
+
+ @fields.depends('quantity', 'line')
+ def get_quantity(self):
+ if self.quantity is not None:
+ return self.quantity
+ elif self.line:
+ return self.line.quantity
+
+ @fields.depends('unit_price', 'line')
+ def get_unit_price(self):
+ if self.unit_price is not None:
+ return self.unit_price
+ elif self.line:
+ return self.line.unit_price
diff --git a/modules/sale_complaint/complaint.xml b/modules/sale_complaint/complaint.xml
new file mode 100644
index 0000000000..12358da273
--- /dev/null
+++ b/modules/sale_complaint/complaint.xml
@@ -0,0 +1,303 @@
+
+
+
+
+
+
+
+ sale.complaint.type
+ form
+ type_form
+
+
+ sale.complaint.type
+ tree
+ type_list
+
+
+
+ Types
+ sale.complaint.type
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ sale.complaint
+ form
+ complaint_form
+
+
+ sale.complaint
+ tree
+ complaint_list
+
+
+
+ Complaints
+ sale.complaint
+
+
+
+
+
+
+
+
+
+
+
+
+ Draft
+
+
+
+
+
+
+ Waiting
+
+
+
+
+
+
+ Approved
+
+
+
+
+
+
+ All
+
+
+
+
+
+
+
+ Customer Complaints
+ sale.complaint
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ form_relate
+ party.party,-1
+
+
+
+
+ Complaints
+ sale.complaint
+
+
+
+
+
+
+
+
+
+
+
+
+
+ form_relate
+ sale.sale,-1
+
+
+
+
+ User in companies
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ cancel
+ Cancel
+
+
+
+
+
+
+
+
+ draft
+ Draft
+
+
+
+
+
+
+
+
+ wait
+ Wait
+
+
+
+
+
+
+
+
+ approve
+ Approve
+
+
+
+
+
+
+
+
+ reject
+ Reject
+
+
+
+
+
+
+
+
+ process
+ Process
+
+
+
+
+
+
+
+
+ sale.complaint.action
+ form
+ action_form
+
+
+ sale.complaint.action
+ tree
+ action_list
+
+
+
+ sale.complaint.action-sale.line
+ form
+ action_line_form
+
+
+ sale.complaint.action-sale.line
+ tree
+ action_line_list
+
+
+
+ sale.complaint.action-account.invoice.line
+ form
+ action_line_form
+
+
+ sale.complaint.action-account.invoice.line
+ tree
+ action_line_list
+
+
+
diff --git a/modules/sale_complaint/doc/index.rst b/modules/sale_complaint/doc/index.rst
new file mode 100644
index 0000000000..a3f57de0c8
--- /dev/null
+++ b/modules/sale_complaint/doc/index.rst
@@ -0,0 +1,47 @@
+Sale Complaint Module
+#####################
+
+The sale_complaint module defines Complaint model.
+
+Complaint
+*********
+
+The complaint is mainly defined by a customer which complains about a sale or
+an invoice. Actions can be taken to solve the complaint. Here is the extensive
+list of the fields, most of them are optional:
+
+- Customer: The customer.
+- Address: The main address of the customer.
+- Date: The date the complaint is filled.
+- Number: The internal reference of the complaint (will be generated
+ automatically on creation).
+- Reference: The optional external reference of the complaint.
+- Employee: The employee responsible of the complaint.
+- Type: The type of complaint
+- Origin: The original document for which the complaint if filled.
+- Company: The company against which the complaint is filled.
+- Description: The description of the complaint.
+- Actions: The actions to take to solve it.
+- State:
+
+ - Draft
+ - Waiting: The complaint is waiting for approval.
+ - Approved: The complaint has been approved by a sale admin.
+ - Rejected: The complaint has been rejected by a sale admin.
+ - Done: The complaint's actions have been executed.
+ - Cancelled
+
+Action
+******
+
+A complaint action defines an action to execute to solve the complaint.
+There are two types of action: *Create Sale Return* and *Create Credit Note*.
+When the origin of the complaint is a line, only this line will proceeded and
+it will be possible to define the quantity and the unit price otherwise it is
+the all document.
+
+Type
+****
+
+It defines the type of complaint per document: *Sale*, *Sale Line*, *Customer
+Invoice* and *Customer Invoice Line*.
diff --git a/modules/sale_complaint/icons/LICENSE b/modules/sale_complaint/icons/LICENSE
new file mode 100644
index 0000000000..7a4a3ea242
--- /dev/null
+++ b/modules/sale_complaint/icons/LICENSE
@@ -0,0 +1,202 @@
+
+ Apache License
+ Version 2.0, January 2004
+ http://www.apache.org/licenses/
+
+ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+ 1. Definitions.
+
+ "License" shall mean the terms and conditions for use, reproduction,
+ and distribution as defined by Sections 1 through 9 of this document.
+
+ "Licensor" shall mean the copyright owner or entity authorized by
+ the copyright owner that is granting the License.
+
+ "Legal Entity" shall mean the union of the acting entity and all
+ other entities that control, are controlled by, or are under common
+ control with that entity. For the purposes of this definition,
+ "control" means (i) the power, direct or indirect, to cause the
+ direction or management of such entity, whether by contract or
+ otherwise, or (ii) ownership of fifty percent (50%) or more of the
+ outstanding shares, or (iii) beneficial ownership of such entity.
+
+ "You" (or "Your") shall mean an individual or Legal Entity
+ exercising permissions granted by this License.
+
+ "Source" form shall mean the preferred form for making modifications,
+ including but not limited to software source code, documentation
+ source, and configuration files.
+
+ "Object" form shall mean any form resulting from mechanical
+ transformation or translation of a Source form, including but
+ not limited to compiled object code, generated documentation,
+ and conversions to other media types.
+
+ "Work" shall mean the work of authorship, whether in Source or
+ Object form, made available under the License, as indicated by a
+ copyright notice that is included in or attached to the work
+ (an example is provided in the Appendix below).
+
+ "Derivative Works" shall mean any work, whether in Source or Object
+ form, that is based on (or derived from) the Work and for which the
+ editorial revisions, annotations, elaborations, or other modifications
+ represent, as a whole, an original work of authorship. For the purposes
+ of this License, Derivative Works shall not include works that remain
+ separable from, or merely link (or bind by name) to the interfaces of,
+ the Work and Derivative Works thereof.
+
+ "Contribution" shall mean any work of authorship, including
+ the original version of the Work and any modifications or additions
+ to that Work or Derivative Works thereof, that is intentionally
+ submitted to Licensor for inclusion in the Work by the copyright owner
+ or by an individual or Legal Entity authorized to submit on behalf of
+ the copyright owner. For the purposes of this definition, "submitted"
+ means any form of electronic, verbal, or written communication sent
+ to the Licensor or its representatives, including but not limited to
+ communication on electronic mailing lists, source code control systems,
+ and issue tracking systems that are managed by, or on behalf of, the
+ Licensor for the purpose of discussing and improving the Work, but
+ excluding communication that is conspicuously marked or otherwise
+ designated in writing by the copyright owner as "Not a Contribution."
+
+ "Contributor" shall mean Licensor and any individual or Legal Entity
+ on behalf of whom a Contribution has been received by Licensor and
+ subsequently incorporated within the Work.
+
+ 2. Grant of Copyright License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ copyright license to reproduce, prepare Derivative Works of,
+ publicly display, publicly perform, sublicense, and distribute the
+ Work and such Derivative Works in Source or Object form.
+
+ 3. Grant of Patent License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ (except as stated in this section) patent license to make, have made,
+ use, offer to sell, sell, import, and otherwise transfer the Work,
+ where such license applies only to those patent claims licensable
+ by such Contributor that are necessarily infringed by their
+ Contribution(s) alone or by combination of their Contribution(s)
+ with the Work to which such Contribution(s) was submitted. If You
+ institute patent litigation against any entity (including a
+ cross-claim or counterclaim in a lawsuit) alleging that the Work
+ or a Contribution incorporated within the Work constitutes direct
+ or contributory patent infringement, then any patent licenses
+ granted to You under this License for that Work shall terminate
+ as of the date such litigation is filed.
+
+ 4. Redistribution. You may reproduce and distribute copies of the
+ Work or Derivative Works thereof in any medium, with or without
+ modifications, and in Source or Object form, provided that You
+ meet the following conditions:
+
+ (a) You must give any other recipients of the Work or
+ Derivative Works a copy of this License; and
+
+ (b) You must cause any modified files to carry prominent notices
+ stating that You changed the files; and
+
+ (c) You must retain, in the Source form of any Derivative Works
+ that You distribute, all copyright, patent, trademark, and
+ attribution notices from the Source form of the Work,
+ excluding those notices that do not pertain to any part of
+ the Derivative Works; and
+
+ (d) If the Work includes a "NOTICE" text file as part of its
+ distribution, then any Derivative Works that You distribute must
+ include a readable copy of the attribution notices contained
+ within such NOTICE file, excluding those notices that do not
+ pertain to any part of the Derivative Works, in at least one
+ of the following places: within a NOTICE text file distributed
+ as part of the Derivative Works; within the Source form or
+ documentation, if provided along with the Derivative Works; or,
+ within a display generated by the Derivative Works, if and
+ wherever such third-party notices normally appear. The contents
+ of the NOTICE file are for informational purposes only and
+ do not modify the License. You may add Your own attribution
+ notices within Derivative Works that You distribute, alongside
+ or as an addendum to the NOTICE text from the Work, provided
+ that such additional attribution notices cannot be construed
+ as modifying the License.
+
+ You may add Your own copyright statement to Your modifications and
+ may provide additional or different license terms and conditions
+ for use, reproduction, or distribution of Your modifications, or
+ for any such Derivative Works as a whole, provided Your use,
+ reproduction, and distribution of the Work otherwise complies with
+ the conditions stated in this License.
+
+ 5. Submission of Contributions. Unless You explicitly state otherwise,
+ any Contribution intentionally submitted for inclusion in the Work
+ by You to the Licensor shall be under the terms and conditions of
+ this License, without any additional terms or conditions.
+ Notwithstanding the above, nothing herein shall supersede or modify
+ the terms of any separate license agreement you may have executed
+ with Licensor regarding such Contributions.
+
+ 6. Trademarks. This License does not grant permission to use the trade
+ names, trademarks, service marks, or product names of the Licensor,
+ except as required for reasonable and customary use in describing the
+ origin of the Work and reproducing the content of the NOTICE file.
+
+ 7. Disclaimer of Warranty. Unless required by applicable law or
+ agreed to in writing, Licensor provides the Work (and each
+ Contributor provides its Contributions) on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ implied, including, without limitation, any warranties or conditions
+ of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+ PARTICULAR PURPOSE. You are solely responsible for determining the
+ appropriateness of using or redistributing the Work and assume any
+ risks associated with Your exercise of permissions under this License.
+
+ 8. Limitation of Liability. In no event and under no legal theory,
+ whether in tort (including negligence), contract, or otherwise,
+ unless required by applicable law (such as deliberate and grossly
+ negligent acts) or agreed to in writing, shall any Contributor be
+ liable to You for damages, including any direct, indirect, special,
+ incidental, or consequential damages of any character arising as a
+ result of this License or out of the use or inability to use the
+ Work (including but not limited to damages for loss of goodwill,
+ work stoppage, computer failure or malfunction, or any and all
+ other commercial damages or losses), even if such Contributor
+ has been advised of the possibility of such damages.
+
+ 9. Accepting Warranty or Additional Liability. While redistributing
+ the Work or Derivative Works thereof, You may choose to offer,
+ and charge a fee for, acceptance of support, warranty, indemnity,
+ or other liability obligations and/or rights consistent with this
+ License. However, in accepting such obligations, You may act only
+ on Your own behalf and on Your sole responsibility, not on behalf
+ of any other Contributor, and only if You agree to indemnify,
+ defend, and hold each Contributor harmless for any liability
+ incurred by, or claims asserted against, such Contributor by reason
+ of your accepting any such warranty or additional liability.
+
+ END OF TERMS AND CONDITIONS
+
+ APPENDIX: How to apply the Apache License to your work.
+
+ To apply the Apache License to your work, attach the following
+ boilerplate notice, with the fields enclosed by brackets "[]"
+ replaced with your own identifying information. (Don't include
+ the brackets!) The text should be enclosed in the appropriate
+ comment syntax for the file format. We also recommend that a
+ file or class name and description of purpose be included on the
+ same "printed page" as the copyright notice for easier
+ identification within third-party archives.
+
+ Copyright [yyyy] [name of copyright owner]
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
\ No newline at end of file
diff --git a/modules/sale_complaint/icons/tryton-sale-complaint.svg b/modules/sale_complaint/icons/tryton-sale-complaint.svg
new file mode 100644
index 0000000000..a9bc26dc25
--- /dev/null
+++ b/modules/sale_complaint/icons/tryton-sale-complaint.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/modules/sale_complaint/locale/bg.po b/modules/sale_complaint/locale/bg.po
new file mode 100644
index 0000000000..a8e01ddd31
--- /dev/null
+++ b/modules/sale_complaint/locale/bg.po
@@ -0,0 +1,454 @@
+#
+msgid ""
+msgstr "Content-Type: text/plain; charset=utf-8\n"
+
+#, fuzzy
+msgctxt "field:sale.complaint,actions:"
+msgid "Actions"
+msgstr "Действия"
+
+#, fuzzy
+msgctxt "field:sale.complaint,address:"
+msgid "Address"
+msgstr "Адрес"
+
+#, fuzzy
+msgctxt "field:sale.complaint,company:"
+msgid "Company"
+msgstr "Фирма"
+
+#, fuzzy
+msgctxt "field:sale.complaint,customer:"
+msgid "Customer"
+msgstr "Клиент"
+
+#, fuzzy
+msgctxt "field:sale.complaint,date:"
+msgid "Date"
+msgstr "Дата"
+
+#, fuzzy
+msgctxt "field:sale.complaint,description:"
+msgid "Description"
+msgstr "Описание"
+
+#, fuzzy
+msgctxt "field:sale.complaint,employee:"
+msgid "Employee"
+msgstr "Служител"
+
+#, fuzzy
+msgctxt "field:sale.complaint,number:"
+msgid "Number"
+msgstr "Номер"
+
+#, fuzzy
+msgctxt "field:sale.complaint,origin:"
+msgid "Origin"
+msgstr "Източник"
+
+msgctxt "field:sale.complaint,origin_id:"
+msgid "Origin ID"
+msgstr ""
+
+msgctxt "field:sale.complaint,origin_model:"
+msgid "Origin Model"
+msgstr ""
+
+#, fuzzy
+msgctxt "field:sale.complaint,reference:"
+msgid "Reference"
+msgstr "Препратка"
+
+#, fuzzy
+msgctxt "field:sale.complaint,state:"
+msgid "State"
+msgstr "Щат"
+
+#, fuzzy
+msgctxt "field:sale.complaint,type:"
+msgid "Type"
+msgstr "Вид"
+
+#, fuzzy
+msgctxt "field:sale.complaint.action,action:"
+msgid "Action"
+msgstr "Действие"
+
+msgctxt "field:sale.complaint.action,amount:"
+msgid "Amount"
+msgstr ""
+
+#, fuzzy
+msgctxt "field:sale.complaint.action,complaint:"
+msgid "Complaint"
+msgstr "Complaints"
+
+#, fuzzy
+msgctxt "field:sale.complaint.action,complaint_state:"
+msgid "Complaint State"
+msgstr "Complaints"
+
+msgctxt "field:sale.complaint.action,currency:"
+msgid "Currency"
+msgstr ""
+
+#, fuzzy
+msgctxt "field:sale.complaint.action,currency_digits:"
+msgid "Currency Digits"
+msgstr "Десетични единици"
+
+#, fuzzy
+msgctxt "field:sale.complaint.action,invoice_lines:"
+msgid "Invoice Lines"
+msgstr "Редове от фактура"
+
+#, fuzzy
+msgctxt "field:sale.complaint.action,quantity:"
+msgid "Quantity"
+msgstr "Количество"
+
+msgctxt "field:sale.complaint.action,result:"
+msgid "Result"
+msgstr ""
+
+#, fuzzy
+msgctxt "field:sale.complaint.action,sale_lines:"
+msgid "Sale Lines"
+msgstr "Ред от продажба"
+
+#, fuzzy
+msgctxt "field:sale.complaint.action,unit:"
+msgid "Unit"
+msgstr "Единица"
+
+#, fuzzy
+msgctxt "field:sale.complaint.action,unit_digits:"
+msgid "Unit Digits"
+msgstr "Десетични единици"
+
+#, fuzzy
+msgctxt "field:sale.complaint.action,unit_price:"
+msgid "Unit Price"
+msgstr "Единична цена"
+
+#, fuzzy
+msgctxt "field:sale.complaint.action-account.invoice.line,action:"
+msgid "Action"
+msgstr "Действие"
+
+msgctxt "field:sale.complaint.action-account.invoice.line,amount:"
+msgid "Amount"
+msgstr ""
+
+#, fuzzy
+msgctxt ""
+"field:sale.complaint.action-account.invoice.line,complaint_origin_id:"
+msgid "Complaint Origin ID"
+msgstr "Complaints"
+
+#, fuzzy
+msgctxt "field:sale.complaint.action-account.invoice.line,complaint_state:"
+msgid "Complaint State"
+msgstr "Complaints"
+
+msgctxt "field:sale.complaint.action-account.invoice.line,currency:"
+msgid "Currency"
+msgstr ""
+
+#, fuzzy
+msgctxt "field:sale.complaint.action-account.invoice.line,currency_digits:"
+msgid "Currency Digits"
+msgstr "Десетични единици"
+
+#, fuzzy
+msgctxt "field:sale.complaint.action-account.invoice.line,line:"
+msgid "Invoice Line"
+msgstr "Ред от фактура"
+
+#, fuzzy
+msgctxt "field:sale.complaint.action-account.invoice.line,quantity:"
+msgid "Quantity"
+msgstr "Количество"
+
+#, fuzzy
+msgctxt "field:sale.complaint.action-account.invoice.line,unit:"
+msgid "Unit"
+msgstr "Единица"
+
+#, fuzzy
+msgctxt "field:sale.complaint.action-account.invoice.line,unit_digits:"
+msgid "Unit Digits"
+msgstr "Десетични единици"
+
+#, fuzzy
+msgctxt "field:sale.complaint.action-account.invoice.line,unit_price:"
+msgid "Unit Price"
+msgstr "Единична цена"
+
+#, fuzzy
+msgctxt "field:sale.complaint.action-sale.line,action:"
+msgid "Action"
+msgstr "Действие"
+
+msgctxt "field:sale.complaint.action-sale.line,amount:"
+msgid "Amount"
+msgstr ""
+
+#, fuzzy
+msgctxt "field:sale.complaint.action-sale.line,complaint_origin_id:"
+msgid "Complaint Origin ID"
+msgstr "Complaints"
+
+#, fuzzy
+msgctxt "field:sale.complaint.action-sale.line,complaint_state:"
+msgid "Complaint State"
+msgstr "Complaints"
+
+msgctxt "field:sale.complaint.action-sale.line,currency:"
+msgid "Currency"
+msgstr ""
+
+#, fuzzy
+msgctxt "field:sale.complaint.action-sale.line,currency_digits:"
+msgid "Currency Digits"
+msgstr "Десетични единици"
+
+#, fuzzy
+msgctxt "field:sale.complaint.action-sale.line,line:"
+msgid "Sale Line"
+msgstr "Ред от продажба"
+
+#, fuzzy
+msgctxt "field:sale.complaint.action-sale.line,quantity:"
+msgid "Quantity"
+msgstr "Количество"
+
+#, fuzzy
+msgctxt "field:sale.complaint.action-sale.line,unit:"
+msgid "Unit"
+msgstr "Единица"
+
+#, fuzzy
+msgctxt "field:sale.complaint.action-sale.line,unit_digits:"
+msgid "Unit Digits"
+msgstr "Десетични единици"
+
+#, fuzzy
+msgctxt "field:sale.complaint.action-sale.line,unit_price:"
+msgid "Unit Price"
+msgstr "Единична цена"
+
+#, fuzzy
+msgctxt "field:sale.complaint.type,name:"
+msgid "Name"
+msgstr "Условие за плащане"
+
+#, fuzzy
+msgctxt "field:sale.complaint.type,origin:"
+msgid "Origin"
+msgstr "Източник"
+
+msgctxt "field:sale.configuration,complaint_sequence:"
+msgid "Complaint Sequence"
+msgstr ""
+
+msgctxt "field:sale.configuration.sequence,complaint_sequence:"
+msgid "Complaint Sequence"
+msgstr ""
+
+msgctxt "help:sale.complaint.action,invoice_lines:"
+msgid "Leave empty for all lines."
+msgstr ""
+
+msgctxt "help:sale.complaint.action,quantity:"
+msgid "Leave empty for the same quantity."
+msgstr ""
+
+msgctxt "help:sale.complaint.action,sale_lines:"
+msgid "Leave empty for all lines."
+msgstr ""
+
+msgctxt "help:sale.complaint.action,unit_price:"
+msgid "Leave empty for the same price."
+msgstr ""
+
+msgctxt "help:sale.complaint.action-account.invoice.line,unit_price:"
+msgid "Leave empty for the same price."
+msgstr ""
+
+msgctxt "help:sale.complaint.action-sale.line,unit_price:"
+msgid "Leave empty for the same price."
+msgstr ""
+
+msgctxt "model:ir.action,name:act_complaint_form"
+msgid "Complaints"
+msgstr "Complaints"
+
+msgctxt "model:ir.action,name:act_complaint_relate_party"
+msgid "Customer Complaints"
+msgstr "Customer Complaints"
+
+msgctxt "model:ir.action,name:act_complaint_relate_sale"
+msgid "Complaints"
+msgstr "Complaints"
+
+#, fuzzy
+msgctxt "model:ir.action,name:act_type_form"
+msgid "Types"
+msgstr "Вид"
+
+msgctxt "model:ir.action.act_window.domain,name:act_complaint_form_domain_all"
+msgid "All"
+msgstr "All"
+
+#, fuzzy
+msgctxt ""
+"model:ir.action.act_window.domain,name:act_complaint_form_domain_approved"
+msgid "Approved"
+msgstr "Approved"
+
+#, fuzzy
+msgctxt ""
+"model:ir.action.act_window.domain,name:act_complaint_form_domain_draft"
+msgid "Draft"
+msgstr "Проект"
+
+#, fuzzy
+msgctxt ""
+"model:ir.action.act_window.domain,name:act_complaint_form_domain_waiting"
+msgid "Waiting"
+msgstr "Очакване"
+
+msgctxt "model:ir.message,text:msg_action_delete_result"
+msgid "You cannot delete action \"%(action)s\" because it has a result."
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_complaint_delete_draft"
+msgid "To delete complaint \"%(complaint)s\" you must reset it to draft state."
+msgstr ""
+
+msgctxt "model:ir.model.button,string:complaint_approve_button"
+msgid "Approve"
+msgstr "Approve"
+
+msgctxt "model:ir.model.button,string:complaint_cancel_button"
+msgid "Cancel"
+msgstr "Cancel"
+
+msgctxt "model:ir.model.button,string:complaint_do_button"
+msgid "Process"
+msgstr "Process"
+
+msgctxt "model:ir.model.button,string:complaint_draft_button"
+msgid "Draft"
+msgstr "Draft"
+
+msgctxt "model:ir.model.button,string:complaint_reject_button"
+msgid "Reject"
+msgstr "Reject"
+
+msgctxt "model:ir.model.button,string:complaint_wait_button"
+msgid "Wait"
+msgstr "Wait"
+
+#, fuzzy
+msgctxt "model:ir.rule.group,name:rule_group_complaint_companies"
+msgid "User in companies"
+msgstr "Customer Complaint"
+
+msgctxt "model:ir.sequence,name:sequence_complaint"
+msgid "Customer Complaint"
+msgstr "Customer Complaint"
+
+msgctxt "model:ir.sequence.type,name:sequence_type_complaint"
+msgid "Customer Complaint"
+msgstr "Customer Complaint"
+
+msgctxt "model:ir.ui.menu,name:menu_complaint"
+msgid "Complaints"
+msgstr "Complaints"
+
+msgctxt "model:ir.ui.menu,name:menu_configuration"
+msgid "Customer Complaint"
+msgstr "Customer Complaint"
+
+#, fuzzy
+msgctxt "model:ir.ui.menu,name:menu_type"
+msgid "Types"
+msgstr "Вид"
+
+#, fuzzy
+msgctxt "model:sale.complaint,name:"
+msgid "Customer Complaint"
+msgstr "Customer Complaint"
+
+#, fuzzy
+msgctxt "model:sale.complaint.action,name:"
+msgid "Customer Complaint Action"
+msgstr "Customer Complaint"
+
+msgctxt "model:sale.complaint.action-account.invoice.line,name:"
+msgid "Customer Complaint Action - Invoice Line"
+msgstr ""
+
+msgctxt "model:sale.complaint.action-sale.line,name:"
+msgid "Customer Complaint Action - Sale Line"
+msgstr ""
+
+#, fuzzy
+msgctxt "model:sale.complaint.type,name:"
+msgid "Customer Complaint Type"
+msgstr "Customer Complaint"
+
+#, fuzzy
+msgctxt "selection:sale.complaint,state:"
+msgid "Approved"
+msgstr "Approve"
+
+#, fuzzy
+msgctxt "selection:sale.complaint,state:"
+msgid "Cancelled"
+msgstr "Отказан"
+
+#, fuzzy
+msgctxt "selection:sale.complaint,state:"
+msgid "Done"
+msgstr "Приключено"
+
+#, fuzzy
+msgctxt "selection:sale.complaint,state:"
+msgid "Draft"
+msgstr "Проект"
+
+#, fuzzy
+msgctxt "selection:sale.complaint,state:"
+msgid "Rejected"
+msgstr "Reject"
+
+#, fuzzy
+msgctxt "selection:sale.complaint,state:"
+msgid "Waiting"
+msgstr "Очакване"
+
+msgctxt "selection:sale.complaint.action,action:"
+msgid "Create Credit Note"
+msgstr ""
+
+msgctxt "selection:sale.complaint.action,action:"
+msgid "Create Sale Return"
+msgstr ""
+
+msgctxt "view:sale.complaint.action:"
+msgid "Amount"
+msgstr ""
+
+#, fuzzy
+msgctxt "view:sale.complaint:"
+msgid "Complaint"
+msgstr "Complaints"
+
+#, fuzzy
+msgctxt "view:sale.complaint:"
+msgid "Process"
+msgstr "Обработване"
diff --git a/modules/sale_complaint/locale/ca.po b/modules/sale_complaint/locale/ca.po
new file mode 100644
index 0000000000..5150a6e793
--- /dev/null
+++ b/modules/sale_complaint/locale/ca.po
@@ -0,0 +1,397 @@
+#
+msgid ""
+msgstr "Content-Type: text/plain; charset=utf-8\n"
+
+msgctxt "field:sale.complaint,actions:"
+msgid "Actions"
+msgstr "Accions"
+
+msgctxt "field:sale.complaint,address:"
+msgid "Address"
+msgstr "Adreça"
+
+msgctxt "field:sale.complaint,company:"
+msgid "Company"
+msgstr "Empresa"
+
+msgctxt "field:sale.complaint,customer:"
+msgid "Customer"
+msgstr "Client"
+
+msgctxt "field:sale.complaint,date:"
+msgid "Date"
+msgstr "Data"
+
+msgctxt "field:sale.complaint,description:"
+msgid "Description"
+msgstr "Descripció"
+
+msgctxt "field:sale.complaint,employee:"
+msgid "Employee"
+msgstr "Empleat"
+
+msgctxt "field:sale.complaint,number:"
+msgid "Number"
+msgstr "Número"
+
+msgctxt "field:sale.complaint,origin:"
+msgid "Origin"
+msgstr "Origen"
+
+msgctxt "field:sale.complaint,origin_id:"
+msgid "Origin ID"
+msgstr "Identificador de l'origen"
+
+msgctxt "field:sale.complaint,origin_model:"
+msgid "Origin Model"
+msgstr "Model de l'origen"
+
+msgctxt "field:sale.complaint,reference:"
+msgid "Reference"
+msgstr "Referència"
+
+msgctxt "field:sale.complaint,state:"
+msgid "State"
+msgstr "Estat"
+
+msgctxt "field:sale.complaint,type:"
+msgid "Type"
+msgstr "Tipus"
+
+msgctxt "field:sale.complaint.action,action:"
+msgid "Action"
+msgstr "Acció"
+
+msgctxt "field:sale.complaint.action,amount:"
+msgid "Amount"
+msgstr "Import"
+
+msgctxt "field:sale.complaint.action,complaint:"
+msgid "Complaint"
+msgstr "Reclamació"
+
+msgctxt "field:sale.complaint.action,complaint_state:"
+msgid "Complaint State"
+msgstr "Estat reclamació"
+
+msgctxt "field:sale.complaint.action,currency:"
+msgid "Currency"
+msgstr "Moneda"
+
+msgctxt "field:sale.complaint.action,currency_digits:"
+msgid "Currency Digits"
+msgstr "Decimals de la moneda"
+
+msgctxt "field:sale.complaint.action,invoice_lines:"
+msgid "Invoice Lines"
+msgstr "Línies de factura"
+
+msgctxt "field:sale.complaint.action,quantity:"
+msgid "Quantity"
+msgstr "Quantitat"
+
+msgctxt "field:sale.complaint.action,result:"
+msgid "Result"
+msgstr "Resultat"
+
+msgctxt "field:sale.complaint.action,sale_lines:"
+msgid "Sale Lines"
+msgstr "Línies de venda"
+
+msgctxt "field:sale.complaint.action,unit:"
+msgid "Unit"
+msgstr "Unitat"
+
+msgctxt "field:sale.complaint.action,unit_digits:"
+msgid "Unit Digits"
+msgstr "Dígits de la unitat"
+
+msgctxt "field:sale.complaint.action,unit_price:"
+msgid "Unit Price"
+msgstr "Preu unitari"
+
+msgctxt "field:sale.complaint.action-account.invoice.line,action:"
+msgid "Action"
+msgstr "Acció"
+
+msgctxt "field:sale.complaint.action-account.invoice.line,amount:"
+msgid "Amount"
+msgstr "Import"
+
+msgctxt ""
+"field:sale.complaint.action-account.invoice.line,complaint_origin_id:"
+msgid "Complaint Origin ID"
+msgstr "Identificador de l'origen de la reclamació"
+
+msgctxt "field:sale.complaint.action-account.invoice.line,complaint_state:"
+msgid "Complaint State"
+msgstr "Estat reclamació"
+
+msgctxt "field:sale.complaint.action-account.invoice.line,currency:"
+msgid "Currency"
+msgstr "Moneda"
+
+msgctxt "field:sale.complaint.action-account.invoice.line,currency_digits:"
+msgid "Currency Digits"
+msgstr "Decimals de la moneda"
+
+msgctxt "field:sale.complaint.action-account.invoice.line,line:"
+msgid "Invoice Line"
+msgstr "Línia de factura"
+
+msgctxt "field:sale.complaint.action-account.invoice.line,quantity:"
+msgid "Quantity"
+msgstr "Quantitat"
+
+msgctxt "field:sale.complaint.action-account.invoice.line,unit:"
+msgid "Unit"
+msgstr "Unitat"
+
+msgctxt "field:sale.complaint.action-account.invoice.line,unit_digits:"
+msgid "Unit Digits"
+msgstr "Dígits de la unitat"
+
+msgctxt "field:sale.complaint.action-account.invoice.line,unit_price:"
+msgid "Unit Price"
+msgstr "Preu unitari"
+
+msgctxt "field:sale.complaint.action-sale.line,action:"
+msgid "Action"
+msgstr "Acció"
+
+msgctxt "field:sale.complaint.action-sale.line,amount:"
+msgid "Amount"
+msgstr "Import"
+
+msgctxt "field:sale.complaint.action-sale.line,complaint_origin_id:"
+msgid "Complaint Origin ID"
+msgstr "Identificador de l'origen de la reclamació"
+
+msgctxt "field:sale.complaint.action-sale.line,complaint_state:"
+msgid "Complaint State"
+msgstr "Estat reclamació"
+
+msgctxt "field:sale.complaint.action-sale.line,currency:"
+msgid "Currency"
+msgstr "Moneda"
+
+msgctxt "field:sale.complaint.action-sale.line,currency_digits:"
+msgid "Currency Digits"
+msgstr "Decimals de la moneda"
+
+msgctxt "field:sale.complaint.action-sale.line,line:"
+msgid "Sale Line"
+msgstr "Línia de venda"
+
+msgctxt "field:sale.complaint.action-sale.line,quantity:"
+msgid "Quantity"
+msgstr "Quantitat"
+
+msgctxt "field:sale.complaint.action-sale.line,unit:"
+msgid "Unit"
+msgstr "Unitat"
+
+msgctxt "field:sale.complaint.action-sale.line,unit_digits:"
+msgid "Unit Digits"
+msgstr "Dígits de la unitat"
+
+msgctxt "field:sale.complaint.action-sale.line,unit_price:"
+msgid "Unit Price"
+msgstr "Preu unitari"
+
+msgctxt "field:sale.complaint.type,name:"
+msgid "Name"
+msgstr "Nom"
+
+msgctxt "field:sale.complaint.type,origin:"
+msgid "Origin"
+msgstr "Origen"
+
+msgctxt "field:sale.configuration,complaint_sequence:"
+msgid "Complaint Sequence"
+msgstr "Seqüència de reclamació"
+
+msgctxt "field:sale.configuration.sequence,complaint_sequence:"
+msgid "Complaint Sequence"
+msgstr "Seqüència de reclamació"
+
+msgctxt "help:sale.complaint.action,invoice_lines:"
+msgid "Leave empty for all lines."
+msgstr "Deixeu-lo buit per totes les línies."
+
+msgctxt "help:sale.complaint.action,quantity:"
+msgid "Leave empty for the same quantity."
+msgstr "Deixeu-lo buit per la mateixa quantitat."
+
+msgctxt "help:sale.complaint.action,sale_lines:"
+msgid "Leave empty for all lines."
+msgstr "Deixeu-lo buit per totes les línies."
+
+msgctxt "help:sale.complaint.action,unit_price:"
+msgid "Leave empty for the same price."
+msgstr "Deixeu-lo buit pel mateix preu."
+
+msgctxt "help:sale.complaint.action-account.invoice.line,unit_price:"
+msgid "Leave empty for the same price."
+msgstr "Deixeu-lo buit pel mateix preu."
+
+msgctxt "help:sale.complaint.action-sale.line,unit_price:"
+msgid "Leave empty for the same price."
+msgstr "Deixeu-lo buit pel mateix preu."
+
+msgctxt "model:ir.action,name:act_complaint_form"
+msgid "Complaints"
+msgstr "Reclamacions"
+
+msgctxt "model:ir.action,name:act_complaint_relate_party"
+msgid "Customer Complaints"
+msgstr "Reclamacions de client"
+
+msgctxt "model:ir.action,name:act_complaint_relate_sale"
+msgid "Complaints"
+msgstr "Reclamacions"
+
+msgctxt "model:ir.action,name:act_type_form"
+msgid "Types"
+msgstr "Tipus"
+
+msgctxt "model:ir.action.act_window.domain,name:act_complaint_form_domain_all"
+msgid "All"
+msgstr "Tot"
+
+msgctxt ""
+"model:ir.action.act_window.domain,name:act_complaint_form_domain_approved"
+msgid "Approved"
+msgstr "Aprovada"
+
+msgctxt ""
+"model:ir.action.act_window.domain,name:act_complaint_form_domain_draft"
+msgid "Draft"
+msgstr "Esborrany"
+
+msgctxt ""
+"model:ir.action.act_window.domain,name:act_complaint_form_domain_waiting"
+msgid "Waiting"
+msgstr "En espera"
+
+msgctxt "model:ir.message,text:msg_action_delete_result"
+msgid "You cannot delete action \"%(action)s\" because it has a result."
+msgstr "No podeu eliminar l'acció \"%(action)s\" perquè té un resultat."
+
+msgctxt "model:ir.message,text:msg_complaint_delete_draft"
+msgid "To delete complaint \"%(complaint)s\" you must reset it to draft state."
+msgstr ""
+"Per eliminar la reclamació \"%(complaint)s\" he de restablir-n'he l'estat a "
+"borrador."
+
+msgctxt "model:ir.model.button,string:complaint_approve_button"
+msgid "Approve"
+msgstr "Aprova"
+
+msgctxt "model:ir.model.button,string:complaint_cancel_button"
+msgid "Cancel"
+msgstr "Cancel·la"
+
+msgctxt "model:ir.model.button,string:complaint_do_button"
+msgid "Process"
+msgstr "Processa"
+
+msgctxt "model:ir.model.button,string:complaint_draft_button"
+msgid "Draft"
+msgstr "Esborrany"
+
+msgctxt "model:ir.model.button,string:complaint_reject_button"
+msgid "Reject"
+msgstr "Rebutja"
+
+msgctxt "model:ir.model.button,string:complaint_wait_button"
+msgid "Wait"
+msgstr "En espera"
+
+msgctxt "model:ir.rule.group,name:rule_group_complaint_companies"
+msgid "User in companies"
+msgstr "Usuari a les empreses"
+
+msgctxt "model:ir.sequence,name:sequence_complaint"
+msgid "Customer Complaint"
+msgstr "Reclamació de client"
+
+msgctxt "model:ir.sequence.type,name:sequence_type_complaint"
+msgid "Customer Complaint"
+msgstr "Reclamació de client"
+
+msgctxt "model:ir.ui.menu,name:menu_complaint"
+msgid "Complaints"
+msgstr "Reclamacions"
+
+msgctxt "model:ir.ui.menu,name:menu_configuration"
+msgid "Customer Complaint"
+msgstr "Reclamació de client"
+
+msgctxt "model:ir.ui.menu,name:menu_type"
+msgid "Types"
+msgstr "Tipus"
+
+msgctxt "model:sale.complaint,name:"
+msgid "Customer Complaint"
+msgstr "Reclamació de client"
+
+msgctxt "model:sale.complaint.action,name:"
+msgid "Customer Complaint Action"
+msgstr "Acció de reclamació de client"
+
+msgctxt "model:sale.complaint.action-account.invoice.line,name:"
+msgid "Customer Complaint Action - Invoice Line"
+msgstr "Acció de reclamació de client - Línia de factura"
+
+msgctxt "model:sale.complaint.action-sale.line,name:"
+msgid "Customer Complaint Action - Sale Line"
+msgstr "Acció de reclamació de client - Línia de venda"
+
+msgctxt "model:sale.complaint.type,name:"
+msgid "Customer Complaint Type"
+msgstr "Tipus de reclamació de client"
+
+msgctxt "selection:sale.complaint,state:"
+msgid "Approved"
+msgstr "Aprovada"
+
+msgctxt "selection:sale.complaint,state:"
+msgid "Cancelled"
+msgstr "Cancel·lada"
+
+msgctxt "selection:sale.complaint,state:"
+msgid "Done"
+msgstr "Finalitzada"
+
+msgctxt "selection:sale.complaint,state:"
+msgid "Draft"
+msgstr "Esborrany"
+
+msgctxt "selection:sale.complaint,state:"
+msgid "Rejected"
+msgstr "Refusada"
+
+msgctxt "selection:sale.complaint,state:"
+msgid "Waiting"
+msgstr "En espera"
+
+msgctxt "selection:sale.complaint.action,action:"
+msgid "Create Credit Note"
+msgstr "Crea factura d'abonament"
+
+msgctxt "selection:sale.complaint.action,action:"
+msgid "Create Sale Return"
+msgstr "Crea venda de devolució"
+
+msgctxt "view:sale.complaint.action:"
+msgid "Amount"
+msgstr "Import"
+
+msgctxt "view:sale.complaint:"
+msgid "Complaint"
+msgstr "Reclamació"
+
+msgctxt "view:sale.complaint:"
+msgid "Process"
+msgstr "Processa"
diff --git a/modules/sale_complaint/locale/cs.po b/modules/sale_complaint/locale/cs.po
new file mode 100644
index 0000000000..01188bdd08
--- /dev/null
+++ b/modules/sale_complaint/locale/cs.po
@@ -0,0 +1,414 @@
+#
+msgid ""
+msgstr "Content-Type: text/plain; charset=utf-8\n"
+
+msgctxt "field:sale.complaint,actions:"
+msgid "Actions"
+msgstr ""
+
+msgctxt "field:sale.complaint,address:"
+msgid "Address"
+msgstr ""
+
+msgctxt "field:sale.complaint,company:"
+msgid "Company"
+msgstr ""
+
+msgctxt "field:sale.complaint,customer:"
+msgid "Customer"
+msgstr ""
+
+msgctxt "field:sale.complaint,date:"
+msgid "Date"
+msgstr ""
+
+msgctxt "field:sale.complaint,description:"
+msgid "Description"
+msgstr ""
+
+msgctxt "field:sale.complaint,employee:"
+msgid "Employee"
+msgstr ""
+
+msgctxt "field:sale.complaint,number:"
+msgid "Number"
+msgstr ""
+
+msgctxt "field:sale.complaint,origin:"
+msgid "Origin"
+msgstr ""
+
+msgctxt "field:sale.complaint,origin_id:"
+msgid "Origin ID"
+msgstr ""
+
+msgctxt "field:sale.complaint,origin_model:"
+msgid "Origin Model"
+msgstr ""
+
+msgctxt "field:sale.complaint,reference:"
+msgid "Reference"
+msgstr ""
+
+msgctxt "field:sale.complaint,state:"
+msgid "State"
+msgstr ""
+
+#, fuzzy
+msgctxt "field:sale.complaint,type:"
+msgid "Type"
+msgstr "Types"
+
+msgctxt "field:sale.complaint.action,action:"
+msgid "Action"
+msgstr ""
+
+msgctxt "field:sale.complaint.action,amount:"
+msgid "Amount"
+msgstr ""
+
+#, fuzzy
+msgctxt "field:sale.complaint.action,complaint:"
+msgid "Complaint"
+msgstr "Complaints"
+
+#, fuzzy
+msgctxt "field:sale.complaint.action,complaint_state:"
+msgid "Complaint State"
+msgstr "Complaints"
+
+msgctxt "field:sale.complaint.action,currency:"
+msgid "Currency"
+msgstr ""
+
+msgctxt "field:sale.complaint.action,currency_digits:"
+msgid "Currency Digits"
+msgstr ""
+
+msgctxt "field:sale.complaint.action,invoice_lines:"
+msgid "Invoice Lines"
+msgstr ""
+
+msgctxt "field:sale.complaint.action,quantity:"
+msgid "Quantity"
+msgstr ""
+
+msgctxt "field:sale.complaint.action,result:"
+msgid "Result"
+msgstr ""
+
+msgctxt "field:sale.complaint.action,sale_lines:"
+msgid "Sale Lines"
+msgstr ""
+
+msgctxt "field:sale.complaint.action,unit:"
+msgid "Unit"
+msgstr ""
+
+msgctxt "field:sale.complaint.action,unit_digits:"
+msgid "Unit Digits"
+msgstr ""
+
+msgctxt "field:sale.complaint.action,unit_price:"
+msgid "Unit Price"
+msgstr ""
+
+msgctxt "field:sale.complaint.action-account.invoice.line,action:"
+msgid "Action"
+msgstr ""
+
+msgctxt "field:sale.complaint.action-account.invoice.line,amount:"
+msgid "Amount"
+msgstr ""
+
+#, fuzzy
+msgctxt ""
+"field:sale.complaint.action-account.invoice.line,complaint_origin_id:"
+msgid "Complaint Origin ID"
+msgstr "Complaints"
+
+#, fuzzy
+msgctxt "field:sale.complaint.action-account.invoice.line,complaint_state:"
+msgid "Complaint State"
+msgstr "Complaints"
+
+msgctxt "field:sale.complaint.action-account.invoice.line,currency:"
+msgid "Currency"
+msgstr ""
+
+msgctxt "field:sale.complaint.action-account.invoice.line,currency_digits:"
+msgid "Currency Digits"
+msgstr ""
+
+msgctxt "field:sale.complaint.action-account.invoice.line,line:"
+msgid "Invoice Line"
+msgstr ""
+
+msgctxt "field:sale.complaint.action-account.invoice.line,quantity:"
+msgid "Quantity"
+msgstr ""
+
+msgctxt "field:sale.complaint.action-account.invoice.line,unit:"
+msgid "Unit"
+msgstr ""
+
+msgctxt "field:sale.complaint.action-account.invoice.line,unit_digits:"
+msgid "Unit Digits"
+msgstr ""
+
+msgctxt "field:sale.complaint.action-account.invoice.line,unit_price:"
+msgid "Unit Price"
+msgstr ""
+
+msgctxt "field:sale.complaint.action-sale.line,action:"
+msgid "Action"
+msgstr ""
+
+msgctxt "field:sale.complaint.action-sale.line,amount:"
+msgid "Amount"
+msgstr ""
+
+#, fuzzy
+msgctxt "field:sale.complaint.action-sale.line,complaint_origin_id:"
+msgid "Complaint Origin ID"
+msgstr "Complaints"
+
+#, fuzzy
+msgctxt "field:sale.complaint.action-sale.line,complaint_state:"
+msgid "Complaint State"
+msgstr "Complaints"
+
+msgctxt "field:sale.complaint.action-sale.line,currency:"
+msgid "Currency"
+msgstr ""
+
+msgctxt "field:sale.complaint.action-sale.line,currency_digits:"
+msgid "Currency Digits"
+msgstr ""
+
+msgctxt "field:sale.complaint.action-sale.line,line:"
+msgid "Sale Line"
+msgstr ""
+
+msgctxt "field:sale.complaint.action-sale.line,quantity:"
+msgid "Quantity"
+msgstr ""
+
+msgctxt "field:sale.complaint.action-sale.line,unit:"
+msgid "Unit"
+msgstr ""
+
+msgctxt "field:sale.complaint.action-sale.line,unit_digits:"
+msgid "Unit Digits"
+msgstr ""
+
+msgctxt "field:sale.complaint.action-sale.line,unit_price:"
+msgid "Unit Price"
+msgstr ""
+
+#, fuzzy
+msgctxt "field:sale.complaint.type,name:"
+msgid "Name"
+msgstr "Namu"
+
+msgctxt "field:sale.complaint.type,origin:"
+msgid "Origin"
+msgstr ""
+
+msgctxt "field:sale.configuration,complaint_sequence:"
+msgid "Complaint Sequence"
+msgstr ""
+
+msgctxt "field:sale.configuration.sequence,complaint_sequence:"
+msgid "Complaint Sequence"
+msgstr ""
+
+msgctxt "help:sale.complaint.action,invoice_lines:"
+msgid "Leave empty for all lines."
+msgstr ""
+
+msgctxt "help:sale.complaint.action,quantity:"
+msgid "Leave empty for the same quantity."
+msgstr ""
+
+msgctxt "help:sale.complaint.action,sale_lines:"
+msgid "Leave empty for all lines."
+msgstr ""
+
+msgctxt "help:sale.complaint.action,unit_price:"
+msgid "Leave empty for the same price."
+msgstr ""
+
+msgctxt "help:sale.complaint.action-account.invoice.line,unit_price:"
+msgid "Leave empty for the same price."
+msgstr ""
+
+msgctxt "help:sale.complaint.action-sale.line,unit_price:"
+msgid "Leave empty for the same price."
+msgstr ""
+
+msgctxt "model:ir.action,name:act_complaint_form"
+msgid "Complaints"
+msgstr "Complaints"
+
+msgctxt "model:ir.action,name:act_complaint_relate_party"
+msgid "Customer Complaints"
+msgstr "Customer Complaints"
+
+msgctxt "model:ir.action,name:act_complaint_relate_sale"
+msgid "Complaints"
+msgstr "Complaints"
+
+msgctxt "model:ir.action,name:act_type_form"
+msgid "Types"
+msgstr "Types"
+
+msgctxt "model:ir.action.act_window.domain,name:act_complaint_form_domain_all"
+msgid "All"
+msgstr "All"
+
+#, fuzzy
+msgctxt ""
+"model:ir.action.act_window.domain,name:act_complaint_form_domain_approved"
+msgid "Approved"
+msgstr "Approved"
+
+msgctxt ""
+"model:ir.action.act_window.domain,name:act_complaint_form_domain_draft"
+msgid "Draft"
+msgstr "Draft"
+
+msgctxt ""
+"model:ir.action.act_window.domain,name:act_complaint_form_domain_waiting"
+msgid "Waiting"
+msgstr "Waiting"
+
+msgctxt "model:ir.message,text:msg_action_delete_result"
+msgid "You cannot delete action \"%(action)s\" because it has a result."
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_complaint_delete_draft"
+msgid "To delete complaint \"%(complaint)s\" you must reset it to draft state."
+msgstr ""
+
+msgctxt "model:ir.model.button,string:complaint_approve_button"
+msgid "Approve"
+msgstr "Approve"
+
+msgctxt "model:ir.model.button,string:complaint_cancel_button"
+msgid "Cancel"
+msgstr "Cancel"
+
+msgctxt "model:ir.model.button,string:complaint_do_button"
+msgid "Process"
+msgstr "Process"
+
+msgctxt "model:ir.model.button,string:complaint_draft_button"
+msgid "Draft"
+msgstr "Draft"
+
+msgctxt "model:ir.model.button,string:complaint_reject_button"
+msgid "Reject"
+msgstr "Reject"
+
+msgctxt "model:ir.model.button,string:complaint_wait_button"
+msgid "Wait"
+msgstr "Wait"
+
+#, fuzzy
+msgctxt "model:ir.rule.group,name:rule_group_complaint_companies"
+msgid "User in companies"
+msgstr "Customer Complaint"
+
+msgctxt "model:ir.sequence,name:sequence_complaint"
+msgid "Customer Complaint"
+msgstr "Customer Complaint"
+
+msgctxt "model:ir.sequence.type,name:sequence_type_complaint"
+msgid "Customer Complaint"
+msgstr "Customer Complaint"
+
+msgctxt "model:ir.ui.menu,name:menu_complaint"
+msgid "Complaints"
+msgstr "Complaints"
+
+msgctxt "model:ir.ui.menu,name:menu_configuration"
+msgid "Customer Complaint"
+msgstr "Customer Complaint"
+
+msgctxt "model:ir.ui.menu,name:menu_type"
+msgid "Types"
+msgstr "Types"
+
+#, fuzzy
+msgctxt "model:sale.complaint,name:"
+msgid "Customer Complaint"
+msgstr "Customer Complaint"
+
+#, fuzzy
+msgctxt "model:sale.complaint.action,name:"
+msgid "Customer Complaint Action"
+msgstr "Customer Complaint"
+
+msgctxt "model:sale.complaint.action-account.invoice.line,name:"
+msgid "Customer Complaint Action - Invoice Line"
+msgstr ""
+
+msgctxt "model:sale.complaint.action-sale.line,name:"
+msgid "Customer Complaint Action - Sale Line"
+msgstr ""
+
+#, fuzzy
+msgctxt "model:sale.complaint.type,name:"
+msgid "Customer Complaint Type"
+msgstr "Customer Complaint"
+
+#, fuzzy
+msgctxt "selection:sale.complaint,state:"
+msgid "Approved"
+msgstr "Approve"
+
+msgctxt "selection:sale.complaint,state:"
+msgid "Cancelled"
+msgstr ""
+
+msgctxt "selection:sale.complaint,state:"
+msgid "Done"
+msgstr ""
+
+#, fuzzy
+msgctxt "selection:sale.complaint,state:"
+msgid "Draft"
+msgstr "Draft"
+
+#, fuzzy
+msgctxt "selection:sale.complaint,state:"
+msgid "Rejected"
+msgstr "Reject"
+
+#, fuzzy
+msgctxt "selection:sale.complaint,state:"
+msgid "Waiting"
+msgstr "Waiting"
+
+msgctxt "selection:sale.complaint.action,action:"
+msgid "Create Credit Note"
+msgstr ""
+
+msgctxt "selection:sale.complaint.action,action:"
+msgid "Create Sale Return"
+msgstr ""
+
+msgctxt "view:sale.complaint.action:"
+msgid "Amount"
+msgstr ""
+
+#, fuzzy
+msgctxt "view:sale.complaint:"
+msgid "Complaint"
+msgstr "Complaints"
+
+#, fuzzy
+msgctxt "view:sale.complaint:"
+msgid "Process"
+msgstr "Process"
diff --git a/modules/sale_complaint/locale/de.po b/modules/sale_complaint/locale/de.po
new file mode 100644
index 0000000000..2d362a254d
--- /dev/null
+++ b/modules/sale_complaint/locale/de.po
@@ -0,0 +1,399 @@
+#
+msgid ""
+msgstr "Content-Type: text/plain; charset=utf-8\n"
+
+msgctxt "field:sale.complaint,actions:"
+msgid "Actions"
+msgstr "Aktionen"
+
+msgctxt "field:sale.complaint,address:"
+msgid "Address"
+msgstr "Adresse"
+
+msgctxt "field:sale.complaint,company:"
+msgid "Company"
+msgstr "Unternehmen"
+
+msgctxt "field:sale.complaint,customer:"
+msgid "Customer"
+msgstr "Kunde"
+
+msgctxt "field:sale.complaint,date:"
+msgid "Date"
+msgstr "Datum"
+
+msgctxt "field:sale.complaint,description:"
+msgid "Description"
+msgstr "Beschreibung"
+
+msgctxt "field:sale.complaint,employee:"
+msgid "Employee"
+msgstr "Mitarbeiter"
+
+msgctxt "field:sale.complaint,number:"
+msgid "Number"
+msgstr "Nummer"
+
+msgctxt "field:sale.complaint,origin:"
+msgid "Origin"
+msgstr "Herkunft"
+
+msgctxt "field:sale.complaint,origin_id:"
+msgid "Origin ID"
+msgstr "HerkunftsID"
+
+msgctxt "field:sale.complaint,origin_model:"
+msgid "Origin Model"
+msgstr "Herkunftsmodell"
+
+msgctxt "field:sale.complaint,reference:"
+msgid "Reference"
+msgstr "Belegnummer"
+
+msgctxt "field:sale.complaint,state:"
+msgid "State"
+msgstr "Status"
+
+msgctxt "field:sale.complaint,type:"
+msgid "Type"
+msgstr "Typ"
+
+msgctxt "field:sale.complaint.action,action:"
+msgid "Action"
+msgstr "Aktion"
+
+msgctxt "field:sale.complaint.action,amount:"
+msgid "Amount"
+msgstr "Betrag"
+
+msgctxt "field:sale.complaint.action,complaint:"
+msgid "Complaint"
+msgstr "Reklamation"
+
+msgctxt "field:sale.complaint.action,complaint_state:"
+msgid "Complaint State"
+msgstr "Reklamationsstatus"
+
+msgctxt "field:sale.complaint.action,currency:"
+msgid "Currency"
+msgstr "Währung"
+
+msgctxt "field:sale.complaint.action,currency_digits:"
+msgid "Currency Digits"
+msgstr "Nachkommastellen Währung"
+
+msgctxt "field:sale.complaint.action,invoice_lines:"
+msgid "Invoice Lines"
+msgstr "Rechnungspositionen"
+
+msgctxt "field:sale.complaint.action,quantity:"
+msgid "Quantity"
+msgstr "Menge"
+
+msgctxt "field:sale.complaint.action,result:"
+msgid "Result"
+msgstr "Ergebnis"
+
+msgctxt "field:sale.complaint.action,sale_lines:"
+msgid "Sale Lines"
+msgstr "Verkaufspositionen"
+
+msgctxt "field:sale.complaint.action,unit:"
+msgid "Unit"
+msgstr "Einheit"
+
+msgctxt "field:sale.complaint.action,unit_digits:"
+msgid "Unit Digits"
+msgstr "Nachkommastellen"
+
+msgctxt "field:sale.complaint.action,unit_price:"
+msgid "Unit Price"
+msgstr "Einzelpreis"
+
+msgctxt "field:sale.complaint.action-account.invoice.line,action:"
+msgid "Action"
+msgstr "Aktion"
+
+msgctxt "field:sale.complaint.action-account.invoice.line,amount:"
+msgid "Amount"
+msgstr "Betrag"
+
+msgctxt ""
+"field:sale.complaint.action-account.invoice.line,complaint_origin_id:"
+msgid "Complaint Origin ID"
+msgstr "Reklamation Herkunfts-ID"
+
+msgctxt "field:sale.complaint.action-account.invoice.line,complaint_state:"
+msgid "Complaint State"
+msgstr "Reklamationsstatus"
+
+msgctxt "field:sale.complaint.action-account.invoice.line,currency:"
+msgid "Currency"
+msgstr "Währung"
+
+msgctxt "field:sale.complaint.action-account.invoice.line,currency_digits:"
+msgid "Currency Digits"
+msgstr "Nachkommastellen Währung"
+
+msgctxt "field:sale.complaint.action-account.invoice.line,line:"
+msgid "Invoice Line"
+msgstr "Rechnungsposition"
+
+msgctxt "field:sale.complaint.action-account.invoice.line,quantity:"
+msgid "Quantity"
+msgstr "Menge"
+
+msgctxt "field:sale.complaint.action-account.invoice.line,unit:"
+msgid "Unit"
+msgstr "Einheit"
+
+msgctxt "field:sale.complaint.action-account.invoice.line,unit_digits:"
+msgid "Unit Digits"
+msgstr "Nachkommastellen"
+
+msgctxt "field:sale.complaint.action-account.invoice.line,unit_price:"
+msgid "Unit Price"
+msgstr "Einzelpreis"
+
+msgctxt "field:sale.complaint.action-sale.line,action:"
+msgid "Action"
+msgstr "Aktion"
+
+msgctxt "field:sale.complaint.action-sale.line,amount:"
+msgid "Amount"
+msgstr "Betrag"
+
+msgctxt "field:sale.complaint.action-sale.line,complaint_origin_id:"
+msgid "Complaint Origin ID"
+msgstr "Reklamation Herkunfts-ID"
+
+msgctxt "field:sale.complaint.action-sale.line,complaint_state:"
+msgid "Complaint State"
+msgstr "Reklamationsstatus"
+
+msgctxt "field:sale.complaint.action-sale.line,currency:"
+msgid "Currency"
+msgstr "Währung"
+
+msgctxt "field:sale.complaint.action-sale.line,currency_digits:"
+msgid "Currency Digits"
+msgstr "Nachkommastellen Währung"
+
+msgctxt "field:sale.complaint.action-sale.line,line:"
+msgid "Sale Line"
+msgstr "Verkaufsposition"
+
+msgctxt "field:sale.complaint.action-sale.line,quantity:"
+msgid "Quantity"
+msgstr "Menge"
+
+msgctxt "field:sale.complaint.action-sale.line,unit:"
+msgid "Unit"
+msgstr "Einheit"
+
+msgctxt "field:sale.complaint.action-sale.line,unit_digits:"
+msgid "Unit Digits"
+msgstr "Nachkommastellen"
+
+msgctxt "field:sale.complaint.action-sale.line,unit_price:"
+msgid "Unit Price"
+msgstr "Einzelpreis"
+
+msgctxt "field:sale.complaint.type,name:"
+msgid "Name"
+msgstr "Name"
+
+msgctxt "field:sale.complaint.type,origin:"
+msgid "Origin"
+msgstr "Herkunft"
+
+msgctxt "field:sale.configuration,complaint_sequence:"
+msgid "Complaint Sequence"
+msgstr "Nummernkreis Reklamation"
+
+msgctxt "field:sale.configuration.sequence,complaint_sequence:"
+msgid "Complaint Sequence"
+msgstr "Nummernkreis Reklamation"
+
+msgctxt "help:sale.complaint.action,invoice_lines:"
+msgid "Leave empty for all lines."
+msgstr "Leer lassen für alle Positionen."
+
+msgctxt "help:sale.complaint.action,quantity:"
+msgid "Leave empty for the same quantity."
+msgstr "Leer lassen für gleiche Menge."
+
+msgctxt "help:sale.complaint.action,sale_lines:"
+msgid "Leave empty for all lines."
+msgstr "Leer lassen für alle Positionen."
+
+msgctxt "help:sale.complaint.action,unit_price:"
+msgid "Leave empty for the same price."
+msgstr "Leer lassen für gleichen Preis."
+
+msgctxt "help:sale.complaint.action-account.invoice.line,unit_price:"
+msgid "Leave empty for the same price."
+msgstr "Leer lassen für gleichen Preis."
+
+msgctxt "help:sale.complaint.action-sale.line,unit_price:"
+msgid "Leave empty for the same price."
+msgstr "Leer lassen für gleichen Preis."
+
+msgctxt "model:ir.action,name:act_complaint_form"
+msgid "Complaints"
+msgstr "Reklamationen"
+
+msgctxt "model:ir.action,name:act_complaint_relate_party"
+msgid "Customer Complaints"
+msgstr "Kundenreklamationen"
+
+msgctxt "model:ir.action,name:act_complaint_relate_sale"
+msgid "Complaints"
+msgstr "Reklamationen"
+
+msgctxt "model:ir.action,name:act_type_form"
+msgid "Types"
+msgstr "Typen"
+
+msgctxt "model:ir.action.act_window.domain,name:act_complaint_form_domain_all"
+msgid "All"
+msgstr "Alle"
+
+msgctxt ""
+"model:ir.action.act_window.domain,name:act_complaint_form_domain_approved"
+msgid "Approved"
+msgstr "Genehmigt"
+
+msgctxt ""
+"model:ir.action.act_window.domain,name:act_complaint_form_domain_draft"
+msgid "Draft"
+msgstr "Entwurf"
+
+msgctxt ""
+"model:ir.action.act_window.domain,name:act_complaint_form_domain_waiting"
+msgid "Waiting"
+msgstr "Wartend"
+
+msgctxt "model:ir.message,text:msg_action_delete_result"
+msgid "You cannot delete action \"%(action)s\" because it has a result."
+msgstr ""
+"Aktion \"%(action)s\" kann nicht gelöscht werden, da bereits ein Ergebnis "
+"vorliegt."
+
+msgctxt "model:ir.message,text:msg_complaint_delete_draft"
+msgid "To delete complaint \"%(complaint)s\" you must reset it to draft state."
+msgstr ""
+"Damit die Reklamation \"%(complaint)s\" gelöscht werden kann, muss sie "
+"zuerst in den Entwurfsstatus zurückgesetzt werden."
+
+msgctxt "model:ir.model.button,string:complaint_approve_button"
+msgid "Approve"
+msgstr "Genehmigen"
+
+msgctxt "model:ir.model.button,string:complaint_cancel_button"
+msgid "Cancel"
+msgstr "Annullieren"
+
+msgctxt "model:ir.model.button,string:complaint_do_button"
+msgid "Process"
+msgstr "Ausführen"
+
+msgctxt "model:ir.model.button,string:complaint_draft_button"
+msgid "Draft"
+msgstr "Entwurf"
+
+msgctxt "model:ir.model.button,string:complaint_reject_button"
+msgid "Reject"
+msgstr "Ablehnen"
+
+msgctxt "model:ir.model.button,string:complaint_wait_button"
+msgid "Wait"
+msgstr "Warten"
+
+msgctxt "model:ir.rule.group,name:rule_group_complaint_companies"
+msgid "User in companies"
+msgstr "Benutzer im Unternehmen"
+
+msgctxt "model:ir.sequence,name:sequence_complaint"
+msgid "Customer Complaint"
+msgstr "Kundenreklamation"
+
+msgctxt "model:ir.sequence.type,name:sequence_type_complaint"
+msgid "Customer Complaint"
+msgstr "Kundenreklamation"
+
+msgctxt "model:ir.ui.menu,name:menu_complaint"
+msgid "Complaints"
+msgstr "Reklamationen"
+
+msgctxt "model:ir.ui.menu,name:menu_configuration"
+msgid "Customer Complaint"
+msgstr "Kundenreklamation"
+
+msgctxt "model:ir.ui.menu,name:menu_type"
+msgid "Types"
+msgstr "Typen"
+
+msgctxt "model:sale.complaint,name:"
+msgid "Customer Complaint"
+msgstr "Reklamation"
+
+msgctxt "model:sale.complaint.action,name:"
+msgid "Customer Complaint Action"
+msgstr "Reklamationsaktion"
+
+msgctxt "model:sale.complaint.action-account.invoice.line,name:"
+msgid "Customer Complaint Action - Invoice Line"
+msgstr "Reklamationsaktion - Rechnungsposition"
+
+msgctxt "model:sale.complaint.action-sale.line,name:"
+msgid "Customer Complaint Action - Sale Line"
+msgstr "Reklamationsaktion - Verkaufsposition"
+
+msgctxt "model:sale.complaint.type,name:"
+msgid "Customer Complaint Type"
+msgstr "Reklamationstyp"
+
+msgctxt "selection:sale.complaint,state:"
+msgid "Approved"
+msgstr "Genehmigt"
+
+msgctxt "selection:sale.complaint,state:"
+msgid "Cancelled"
+msgstr "Annulliert"
+
+msgctxt "selection:sale.complaint,state:"
+msgid "Done"
+msgstr "Erledigt"
+
+msgctxt "selection:sale.complaint,state:"
+msgid "Draft"
+msgstr "Entwurf"
+
+msgctxt "selection:sale.complaint,state:"
+msgid "Rejected"
+msgstr "Abgelehnt"
+
+msgctxt "selection:sale.complaint,state:"
+msgid "Waiting"
+msgstr "Wartend"
+
+msgctxt "selection:sale.complaint.action,action:"
+msgid "Create Credit Note"
+msgstr "Stornorechnung erstellen"
+
+msgctxt "selection:sale.complaint.action,action:"
+msgid "Create Sale Return"
+msgstr "Rücknahme erstellen"
+
+msgctxt "view:sale.complaint.action:"
+msgid "Amount"
+msgstr "Betrag"
+
+msgctxt "view:sale.complaint:"
+msgid "Complaint"
+msgstr "Reklamation"
+
+msgctxt "view:sale.complaint:"
+msgid "Process"
+msgstr "Ausführen"
diff --git a/modules/sale_complaint/locale/es.po b/modules/sale_complaint/locale/es.po
new file mode 100644
index 0000000000..959a30aa51
--- /dev/null
+++ b/modules/sale_complaint/locale/es.po
@@ -0,0 +1,396 @@
+#
+msgid ""
+msgstr "Content-Type: text/plain; charset=utf-8\n"
+
+msgctxt "field:sale.complaint,actions:"
+msgid "Actions"
+msgstr "Acciones"
+
+msgctxt "field:sale.complaint,address:"
+msgid "Address"
+msgstr "Dirección"
+
+msgctxt "field:sale.complaint,company:"
+msgid "Company"
+msgstr "Empresa"
+
+msgctxt "field:sale.complaint,customer:"
+msgid "Customer"
+msgstr "Cliente"
+
+msgctxt "field:sale.complaint,date:"
+msgid "Date"
+msgstr "Fecha"
+
+msgctxt "field:sale.complaint,description:"
+msgid "Description"
+msgstr "Descripción"
+
+msgctxt "field:sale.complaint,employee:"
+msgid "Employee"
+msgstr "Empleado"
+
+msgctxt "field:sale.complaint,number:"
+msgid "Number"
+msgstr "Número"
+
+msgctxt "field:sale.complaint,origin:"
+msgid "Origin"
+msgstr "Origen"
+
+msgctxt "field:sale.complaint,origin_id:"
+msgid "Origin ID"
+msgstr "ID del origen"
+
+msgctxt "field:sale.complaint,origin_model:"
+msgid "Origin Model"
+msgstr "Modelo del origen"
+
+msgctxt "field:sale.complaint,reference:"
+msgid "Reference"
+msgstr "Referencia"
+
+msgctxt "field:sale.complaint,state:"
+msgid "State"
+msgstr "Estado"
+
+msgctxt "field:sale.complaint,type:"
+msgid "Type"
+msgstr "Tipo"
+
+msgctxt "field:sale.complaint.action,action:"
+msgid "Action"
+msgstr "Acción"
+
+msgctxt "field:sale.complaint.action,amount:"
+msgid "Amount"
+msgstr "Importe"
+
+msgctxt "field:sale.complaint.action,complaint:"
+msgid "Complaint"
+msgstr "Reclamación"
+
+msgctxt "field:sale.complaint.action,complaint_state:"
+msgid "Complaint State"
+msgstr "Estado reclamación"
+
+msgctxt "field:sale.complaint.action,currency:"
+msgid "Currency"
+msgstr "Moneda"
+
+msgctxt "field:sale.complaint.action,currency_digits:"
+msgid "Currency Digits"
+msgstr "Decimales de la moneda"
+
+msgctxt "field:sale.complaint.action,invoice_lines:"
+msgid "Invoice Lines"
+msgstr "Líneas de factura"
+
+msgctxt "field:sale.complaint.action,quantity:"
+msgid "Quantity"
+msgstr "Cantidad"
+
+msgctxt "field:sale.complaint.action,result:"
+msgid "Result"
+msgstr "Resultado"
+
+msgctxt "field:sale.complaint.action,sale_lines:"
+msgid "Sale Lines"
+msgstr "Líneas de venta"
+
+msgctxt "field:sale.complaint.action,unit:"
+msgid "Unit"
+msgstr "Unidad"
+
+msgctxt "field:sale.complaint.action,unit_digits:"
+msgid "Unit Digits"
+msgstr "Dígitos de la unidad"
+
+msgctxt "field:sale.complaint.action,unit_price:"
+msgid "Unit Price"
+msgstr "Precio unitario"
+
+msgctxt "field:sale.complaint.action-account.invoice.line,action:"
+msgid "Action"
+msgstr "Acción"
+
+msgctxt "field:sale.complaint.action-account.invoice.line,amount:"
+msgid "Amount"
+msgstr "Importe"
+
+msgctxt ""
+"field:sale.complaint.action-account.invoice.line,complaint_origin_id:"
+msgid "Complaint Origin ID"
+msgstr "ID del origen de la reclamación"
+
+msgctxt "field:sale.complaint.action-account.invoice.line,complaint_state:"
+msgid "Complaint State"
+msgstr "Estado reclamación"
+
+msgctxt "field:sale.complaint.action-account.invoice.line,currency:"
+msgid "Currency"
+msgstr "Moneda"
+
+msgctxt "field:sale.complaint.action-account.invoice.line,currency_digits:"
+msgid "Currency Digits"
+msgstr "Decimales de la moneda"
+
+msgctxt "field:sale.complaint.action-account.invoice.line,line:"
+msgid "Invoice Line"
+msgstr "Línea de factura"
+
+msgctxt "field:sale.complaint.action-account.invoice.line,quantity:"
+msgid "Quantity"
+msgstr "Cantidad"
+
+msgctxt "field:sale.complaint.action-account.invoice.line,unit:"
+msgid "Unit"
+msgstr "Unidad"
+
+msgctxt "field:sale.complaint.action-account.invoice.line,unit_digits:"
+msgid "Unit Digits"
+msgstr "Dígitos de la unidad"
+
+msgctxt "field:sale.complaint.action-account.invoice.line,unit_price:"
+msgid "Unit Price"
+msgstr "Precio unitario"
+
+msgctxt "field:sale.complaint.action-sale.line,action:"
+msgid "Action"
+msgstr "Acción"
+
+msgctxt "field:sale.complaint.action-sale.line,amount:"
+msgid "Amount"
+msgstr "Importe"
+
+msgctxt "field:sale.complaint.action-sale.line,complaint_origin_id:"
+msgid "Complaint Origin ID"
+msgstr "ID del origen de la reclamación"
+
+msgctxt "field:sale.complaint.action-sale.line,complaint_state:"
+msgid "Complaint State"
+msgstr "Estado reclamación"
+
+msgctxt "field:sale.complaint.action-sale.line,currency:"
+msgid "Currency"
+msgstr "Moneda"
+
+msgctxt "field:sale.complaint.action-sale.line,currency_digits:"
+msgid "Currency Digits"
+msgstr "Decimales de la moneda"
+
+msgctxt "field:sale.complaint.action-sale.line,line:"
+msgid "Sale Line"
+msgstr "Línea de venta"
+
+msgctxt "field:sale.complaint.action-sale.line,quantity:"
+msgid "Quantity"
+msgstr "Cantidad"
+
+msgctxt "field:sale.complaint.action-sale.line,unit:"
+msgid "Unit"
+msgstr "Unidad"
+
+msgctxt "field:sale.complaint.action-sale.line,unit_digits:"
+msgid "Unit Digits"
+msgstr "Dígitos de la unidad"
+
+msgctxt "field:sale.complaint.action-sale.line,unit_price:"
+msgid "Unit Price"
+msgstr "Precio unitario"
+
+msgctxt "field:sale.complaint.type,name:"
+msgid "Name"
+msgstr "Nombre"
+
+msgctxt "field:sale.complaint.type,origin:"
+msgid "Origin"
+msgstr "Origen"
+
+msgctxt "field:sale.configuration,complaint_sequence:"
+msgid "Complaint Sequence"
+msgstr "Secuencia de reclamación"
+
+msgctxt "field:sale.configuration.sequence,complaint_sequence:"
+msgid "Complaint Sequence"
+msgstr "Secuencia de reclamación"
+
+msgctxt "help:sale.complaint.action,invoice_lines:"
+msgid "Leave empty for all lines."
+msgstr "Dejarlo vacío para todas las líneas."
+
+msgctxt "help:sale.complaint.action,quantity:"
+msgid "Leave empty for the same quantity."
+msgstr "Dejarlo vacío para la misma cantidad."
+
+msgctxt "help:sale.complaint.action,sale_lines:"
+msgid "Leave empty for all lines."
+msgstr "Dejarlo vacío para todas las líneas."
+
+msgctxt "help:sale.complaint.action,unit_price:"
+msgid "Leave empty for the same price."
+msgstr "Dejarlo vacío para el mismo precio."
+
+msgctxt "help:sale.complaint.action-account.invoice.line,unit_price:"
+msgid "Leave empty for the same price."
+msgstr "Dejarlo vacío para el mismo precio."
+
+msgctxt "help:sale.complaint.action-sale.line,unit_price:"
+msgid "Leave empty for the same price."
+msgstr "Dejarlo vacío para el mismo precio."
+
+msgctxt "model:ir.action,name:act_complaint_form"
+msgid "Complaints"
+msgstr "Reclamaciones"
+
+msgctxt "model:ir.action,name:act_complaint_relate_party"
+msgid "Customer Complaints"
+msgstr "Reclamaciones de cliente"
+
+msgctxt "model:ir.action,name:act_complaint_relate_sale"
+msgid "Complaints"
+msgstr "Reclamaciones"
+
+msgctxt "model:ir.action,name:act_type_form"
+msgid "Types"
+msgstr "Tipos"
+
+msgctxt "model:ir.action.act_window.domain,name:act_complaint_form_domain_all"
+msgid "All"
+msgstr "Todo"
+
+msgctxt ""
+"model:ir.action.act_window.domain,name:act_complaint_form_domain_approved"
+msgid "Approved"
+msgstr "Aprobada"
+
+msgctxt ""
+"model:ir.action.act_window.domain,name:act_complaint_form_domain_draft"
+msgid "Draft"
+msgstr "Borrador"
+
+msgctxt ""
+"model:ir.action.act_window.domain,name:act_complaint_form_domain_waiting"
+msgid "Waiting"
+msgstr "En espera"
+
+msgctxt "model:ir.message,text:msg_action_delete_result"
+msgid "You cannot delete action \"%(action)s\" because it has a result."
+msgstr "No puede eliminar la acción \"%(action)s\" porque tiene un resultado."
+
+msgctxt "model:ir.message,text:msg_complaint_delete_draft"
+msgid "To delete complaint \"%(complaint)s\" you must reset it to draft state."
+msgstr ""
+"Para eliminar la reclamación \"%(complaint)s\" debe establecerla a borrador."
+
+msgctxt "model:ir.model.button,string:complaint_approve_button"
+msgid "Approve"
+msgstr "Aprobar"
+
+msgctxt "model:ir.model.button,string:complaint_cancel_button"
+msgid "Cancel"
+msgstr "Cancelar"
+
+msgctxt "model:ir.model.button,string:complaint_do_button"
+msgid "Process"
+msgstr "Procesar"
+
+msgctxt "model:ir.model.button,string:complaint_draft_button"
+msgid "Draft"
+msgstr "Borrador"
+
+msgctxt "model:ir.model.button,string:complaint_reject_button"
+msgid "Reject"
+msgstr "Rechazar"
+
+msgctxt "model:ir.model.button,string:complaint_wait_button"
+msgid "Wait"
+msgstr "En espera"
+
+msgctxt "model:ir.rule.group,name:rule_group_complaint_companies"
+msgid "User in companies"
+msgstr "Usuario en las empresas"
+
+msgctxt "model:ir.sequence,name:sequence_complaint"
+msgid "Customer Complaint"
+msgstr "Reclamación de cliente"
+
+msgctxt "model:ir.sequence.type,name:sequence_type_complaint"
+msgid "Customer Complaint"
+msgstr "Reclamación de cliente"
+
+msgctxt "model:ir.ui.menu,name:menu_complaint"
+msgid "Complaints"
+msgstr "Reclamaciones"
+
+msgctxt "model:ir.ui.menu,name:menu_configuration"
+msgid "Customer Complaint"
+msgstr "Reclamación de cliente"
+
+msgctxt "model:ir.ui.menu,name:menu_type"
+msgid "Types"
+msgstr "Tipos"
+
+msgctxt "model:sale.complaint,name:"
+msgid "Customer Complaint"
+msgstr "Reclamación de cliente"
+
+msgctxt "model:sale.complaint.action,name:"
+msgid "Customer Complaint Action"
+msgstr "Acción de reclamación de cliente"
+
+msgctxt "model:sale.complaint.action-account.invoice.line,name:"
+msgid "Customer Complaint Action - Invoice Line"
+msgstr "Acción de reclamación de cliente - Línea de factura"
+
+msgctxt "model:sale.complaint.action-sale.line,name:"
+msgid "Customer Complaint Action - Sale Line"
+msgstr "Acción de reclamación de cliente - Línea de venta"
+
+msgctxt "model:sale.complaint.type,name:"
+msgid "Customer Complaint Type"
+msgstr "Tipo de reclamación de cliente"
+
+msgctxt "selection:sale.complaint,state:"
+msgid "Approved"
+msgstr "Aprobada"
+
+msgctxt "selection:sale.complaint,state:"
+msgid "Cancelled"
+msgstr "Cancelada"
+
+msgctxt "selection:sale.complaint,state:"
+msgid "Done"
+msgstr "Finalizada"
+
+msgctxt "selection:sale.complaint,state:"
+msgid "Draft"
+msgstr "Borrador"
+
+msgctxt "selection:sale.complaint,state:"
+msgid "Rejected"
+msgstr "Rechazada"
+
+msgctxt "selection:sale.complaint,state:"
+msgid "Waiting"
+msgstr "En espera"
+
+msgctxt "selection:sale.complaint.action,action:"
+msgid "Create Credit Note"
+msgstr "Crear factura de abono"
+
+msgctxt "selection:sale.complaint.action,action:"
+msgid "Create Sale Return"
+msgstr "Crear venta de devolución"
+
+msgctxt "view:sale.complaint.action:"
+msgid "Amount"
+msgstr "Importe"
+
+msgctxt "view:sale.complaint:"
+msgid "Complaint"
+msgstr "Reclamación"
+
+msgctxt "view:sale.complaint:"
+msgid "Process"
+msgstr "Procesar"
diff --git a/modules/sale_complaint/locale/es_419.po b/modules/sale_complaint/locale/es_419.po
new file mode 100644
index 0000000000..1bc285fc4f
--- /dev/null
+++ b/modules/sale_complaint/locale/es_419.po
@@ -0,0 +1,397 @@
+#
+msgid ""
+msgstr "Content-Type: text/plain; charset=utf-8\n"
+
+msgctxt "field:sale.complaint,actions:"
+msgid "Actions"
+msgstr ""
+
+msgctxt "field:sale.complaint,address:"
+msgid "Address"
+msgstr ""
+
+msgctxt "field:sale.complaint,company:"
+msgid "Company"
+msgstr ""
+
+msgctxt "field:sale.complaint,customer:"
+msgid "Customer"
+msgstr ""
+
+msgctxt "field:sale.complaint,date:"
+msgid "Date"
+msgstr ""
+
+msgctxt "field:sale.complaint,description:"
+msgid "Description"
+msgstr ""
+
+msgctxt "field:sale.complaint,employee:"
+msgid "Employee"
+msgstr ""
+
+msgctxt "field:sale.complaint,number:"
+msgid "Number"
+msgstr ""
+
+msgctxt "field:sale.complaint,origin:"
+msgid "Origin"
+msgstr ""
+
+msgctxt "field:sale.complaint,origin_id:"
+msgid "Origin ID"
+msgstr ""
+
+msgctxt "field:sale.complaint,origin_model:"
+msgid "Origin Model"
+msgstr ""
+
+msgctxt "field:sale.complaint,reference:"
+msgid "Reference"
+msgstr ""
+
+msgctxt "field:sale.complaint,state:"
+msgid "State"
+msgstr ""
+
+msgctxt "field:sale.complaint,type:"
+msgid "Type"
+msgstr ""
+
+msgctxt "field:sale.complaint.action,action:"
+msgid "Action"
+msgstr ""
+
+msgctxt "field:sale.complaint.action,amount:"
+msgid "Amount"
+msgstr ""
+
+msgctxt "field:sale.complaint.action,complaint:"
+msgid "Complaint"
+msgstr ""
+
+msgctxt "field:sale.complaint.action,complaint_state:"
+msgid "Complaint State"
+msgstr ""
+
+msgctxt "field:sale.complaint.action,currency:"
+msgid "Currency"
+msgstr ""
+
+msgctxt "field:sale.complaint.action,currency_digits:"
+msgid "Currency Digits"
+msgstr ""
+
+msgctxt "field:sale.complaint.action,invoice_lines:"
+msgid "Invoice Lines"
+msgstr ""
+
+msgctxt "field:sale.complaint.action,quantity:"
+msgid "Quantity"
+msgstr ""
+
+msgctxt "field:sale.complaint.action,result:"
+msgid "Result"
+msgstr ""
+
+msgctxt "field:sale.complaint.action,sale_lines:"
+msgid "Sale Lines"
+msgstr ""
+
+msgctxt "field:sale.complaint.action,unit:"
+msgid "Unit"
+msgstr ""
+
+msgctxt "field:sale.complaint.action,unit_digits:"
+msgid "Unit Digits"
+msgstr ""
+
+msgctxt "field:sale.complaint.action,unit_price:"
+msgid "Unit Price"
+msgstr "Precio unitario"
+
+msgctxt "field:sale.complaint.action-account.invoice.line,action:"
+msgid "Action"
+msgstr ""
+
+msgctxt "field:sale.complaint.action-account.invoice.line,amount:"
+msgid "Amount"
+msgstr ""
+
+msgctxt ""
+"field:sale.complaint.action-account.invoice.line,complaint_origin_id:"
+msgid "Complaint Origin ID"
+msgstr ""
+
+msgctxt "field:sale.complaint.action-account.invoice.line,complaint_state:"
+msgid "Complaint State"
+msgstr ""
+
+msgctxt "field:sale.complaint.action-account.invoice.line,currency:"
+msgid "Currency"
+msgstr ""
+
+msgctxt "field:sale.complaint.action-account.invoice.line,currency_digits:"
+msgid "Currency Digits"
+msgstr ""
+
+msgctxt "field:sale.complaint.action-account.invoice.line,line:"
+msgid "Invoice Line"
+msgstr ""
+
+msgctxt "field:sale.complaint.action-account.invoice.line,quantity:"
+msgid "Quantity"
+msgstr ""
+
+msgctxt "field:sale.complaint.action-account.invoice.line,unit:"
+msgid "Unit"
+msgstr ""
+
+msgctxt "field:sale.complaint.action-account.invoice.line,unit_digits:"
+msgid "Unit Digits"
+msgstr ""
+
+#, fuzzy
+msgctxt "field:sale.complaint.action-account.invoice.line,unit_price:"
+msgid "Unit Price"
+msgstr "Precio unitario"
+
+msgctxt "field:sale.complaint.action-sale.line,action:"
+msgid "Action"
+msgstr ""
+
+msgctxt "field:sale.complaint.action-sale.line,amount:"
+msgid "Amount"
+msgstr ""
+
+msgctxt "field:sale.complaint.action-sale.line,complaint_origin_id:"
+msgid "Complaint Origin ID"
+msgstr ""
+
+msgctxt "field:sale.complaint.action-sale.line,complaint_state:"
+msgid "Complaint State"
+msgstr ""
+
+msgctxt "field:sale.complaint.action-sale.line,currency:"
+msgid "Currency"
+msgstr ""
+
+msgctxt "field:sale.complaint.action-sale.line,currency_digits:"
+msgid "Currency Digits"
+msgstr ""
+
+msgctxt "field:sale.complaint.action-sale.line,line:"
+msgid "Sale Line"
+msgstr ""
+
+msgctxt "field:sale.complaint.action-sale.line,quantity:"
+msgid "Quantity"
+msgstr ""
+
+msgctxt "field:sale.complaint.action-sale.line,unit:"
+msgid "Unit"
+msgstr ""
+
+msgctxt "field:sale.complaint.action-sale.line,unit_digits:"
+msgid "Unit Digits"
+msgstr ""
+
+#, fuzzy
+msgctxt "field:sale.complaint.action-sale.line,unit_price:"
+msgid "Unit Price"
+msgstr "Precio unitario"
+
+msgctxt "field:sale.complaint.type,name:"
+msgid "Name"
+msgstr ""
+
+msgctxt "field:sale.complaint.type,origin:"
+msgid "Origin"
+msgstr ""
+
+msgctxt "field:sale.configuration,complaint_sequence:"
+msgid "Complaint Sequence"
+msgstr ""
+
+msgctxt "field:sale.configuration.sequence,complaint_sequence:"
+msgid "Complaint Sequence"
+msgstr ""
+
+msgctxt "help:sale.complaint.action,invoice_lines:"
+msgid "Leave empty for all lines."
+msgstr ""
+
+msgctxt "help:sale.complaint.action,quantity:"
+msgid "Leave empty for the same quantity."
+msgstr ""
+
+msgctxt "help:sale.complaint.action,sale_lines:"
+msgid "Leave empty for all lines."
+msgstr ""
+
+msgctxt "help:sale.complaint.action,unit_price:"
+msgid "Leave empty for the same price."
+msgstr ""
+
+msgctxt "help:sale.complaint.action-account.invoice.line,unit_price:"
+msgid "Leave empty for the same price."
+msgstr ""
+
+msgctxt "help:sale.complaint.action-sale.line,unit_price:"
+msgid "Leave empty for the same price."
+msgstr ""
+
+msgctxt "model:ir.action,name:act_complaint_form"
+msgid "Complaints"
+msgstr ""
+
+msgctxt "model:ir.action,name:act_complaint_relate_party"
+msgid "Customer Complaints"
+msgstr ""
+
+msgctxt "model:ir.action,name:act_complaint_relate_sale"
+msgid "Complaints"
+msgstr ""
+
+msgctxt "model:ir.action,name:act_type_form"
+msgid "Types"
+msgstr ""
+
+msgctxt "model:ir.action.act_window.domain,name:act_complaint_form_domain_all"
+msgid "All"
+msgstr ""
+
+msgctxt ""
+"model:ir.action.act_window.domain,name:act_complaint_form_domain_approved"
+msgid "Approved"
+msgstr ""
+
+msgctxt ""
+"model:ir.action.act_window.domain,name:act_complaint_form_domain_draft"
+msgid "Draft"
+msgstr ""
+
+msgctxt ""
+"model:ir.action.act_window.domain,name:act_complaint_form_domain_waiting"
+msgid "Waiting"
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_action_delete_result"
+msgid "You cannot delete action \"%(action)s\" because it has a result."
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_complaint_delete_draft"
+msgid "To delete complaint \"%(complaint)s\" you must reset it to draft state."
+msgstr ""
+
+msgctxt "model:ir.model.button,string:complaint_approve_button"
+msgid "Approve"
+msgstr ""
+
+msgctxt "model:ir.model.button,string:complaint_cancel_button"
+msgid "Cancel"
+msgstr ""
+
+msgctxt "model:ir.model.button,string:complaint_do_button"
+msgid "Process"
+msgstr ""
+
+msgctxt "model:ir.model.button,string:complaint_draft_button"
+msgid "Draft"
+msgstr ""
+
+msgctxt "model:ir.model.button,string:complaint_reject_button"
+msgid "Reject"
+msgstr ""
+
+msgctxt "model:ir.model.button,string:complaint_wait_button"
+msgid "Wait"
+msgstr ""
+
+msgctxt "model:ir.rule.group,name:rule_group_complaint_companies"
+msgid "User in companies"
+msgstr ""
+
+msgctxt "model:ir.sequence,name:sequence_complaint"
+msgid "Customer Complaint"
+msgstr ""
+
+msgctxt "model:ir.sequence.type,name:sequence_type_complaint"
+msgid "Customer Complaint"
+msgstr ""
+
+msgctxt "model:ir.ui.menu,name:menu_complaint"
+msgid "Complaints"
+msgstr ""
+
+msgctxt "model:ir.ui.menu,name:menu_configuration"
+msgid "Customer Complaint"
+msgstr ""
+
+msgctxt "model:ir.ui.menu,name:menu_type"
+msgid "Types"
+msgstr ""
+
+msgctxt "model:sale.complaint,name:"
+msgid "Customer Complaint"
+msgstr ""
+
+msgctxt "model:sale.complaint.action,name:"
+msgid "Customer Complaint Action"
+msgstr ""
+
+msgctxt "model:sale.complaint.action-account.invoice.line,name:"
+msgid "Customer Complaint Action - Invoice Line"
+msgstr ""
+
+msgctxt "model:sale.complaint.action-sale.line,name:"
+msgid "Customer Complaint Action - Sale Line"
+msgstr ""
+
+msgctxt "model:sale.complaint.type,name:"
+msgid "Customer Complaint Type"
+msgstr ""
+
+msgctxt "selection:sale.complaint,state:"
+msgid "Approved"
+msgstr ""
+
+msgctxt "selection:sale.complaint,state:"
+msgid "Cancelled"
+msgstr ""
+
+msgctxt "selection:sale.complaint,state:"
+msgid "Done"
+msgstr ""
+
+msgctxt "selection:sale.complaint,state:"
+msgid "Draft"
+msgstr ""
+
+msgctxt "selection:sale.complaint,state:"
+msgid "Rejected"
+msgstr ""
+
+msgctxt "selection:sale.complaint,state:"
+msgid "Waiting"
+msgstr ""
+
+msgctxt "selection:sale.complaint.action,action:"
+msgid "Create Credit Note"
+msgstr "Crear nota de crédito"
+
+msgctxt "selection:sale.complaint.action,action:"
+msgid "Create Sale Return"
+msgstr "Crear devolución de venta"
+
+msgctxt "view:sale.complaint.action:"
+msgid "Amount"
+msgstr ""
+
+msgctxt "view:sale.complaint:"
+msgid "Complaint"
+msgstr ""
+
+msgctxt "view:sale.complaint:"
+msgid "Process"
+msgstr ""
diff --git a/modules/sale_complaint/locale/et.po b/modules/sale_complaint/locale/et.po
new file mode 100644
index 0000000000..e08e6e32bb
--- /dev/null
+++ b/modules/sale_complaint/locale/et.po
@@ -0,0 +1,420 @@
+#
+msgid ""
+msgstr "Content-Type: text/plain; charset=utf-8\n"
+
+msgctxt "field:sale.complaint,actions:"
+msgid "Actions"
+msgstr "Toimingud"
+
+msgctxt "field:sale.complaint,address:"
+msgid "Address"
+msgstr "Aadress"
+
+msgctxt "field:sale.complaint,company:"
+msgid "Company"
+msgstr "Ettevõte"
+
+msgctxt "field:sale.complaint,customer:"
+msgid "Customer"
+msgstr "Klient"
+
+msgctxt "field:sale.complaint,date:"
+msgid "Date"
+msgstr "Kuupäev"
+
+msgctxt "field:sale.complaint,description:"
+msgid "Description"
+msgstr "Kirjeldus"
+
+msgctxt "field:sale.complaint,employee:"
+msgid "Employee"
+msgstr "Töötaja"
+
+msgctxt "field:sale.complaint,number:"
+msgid "Number"
+msgstr "Number"
+
+msgctxt "field:sale.complaint,origin:"
+msgid "Origin"
+msgstr "Päritolu"
+
+msgctxt "field:sale.complaint,origin_id:"
+msgid "Origin ID"
+msgstr "Päritolu ID"
+
+msgctxt "field:sale.complaint,origin_model:"
+msgid "Origin Model"
+msgstr "Päritplu mudel"
+
+msgctxt "field:sale.complaint,reference:"
+msgid "Reference"
+msgstr "Viide"
+
+msgctxt "field:sale.complaint,state:"
+msgid "State"
+msgstr "Olek"
+
+msgctxt "field:sale.complaint,type:"
+msgid "Type"
+msgstr "Tüüp"
+
+msgctxt "field:sale.complaint.action,action:"
+msgid "Action"
+msgstr "Toiming"
+
+msgctxt "field:sale.complaint.action,amount:"
+msgid "Amount"
+msgstr ""
+
+msgctxt "field:sale.complaint.action,complaint:"
+msgid "Complaint"
+msgstr "Kaebus"
+
+#, fuzzy
+msgctxt "field:sale.complaint.action,complaint_state:"
+msgid "Complaint State"
+msgstr "Kaebus"
+
+msgctxt "field:sale.complaint.action,currency:"
+msgid "Currency"
+msgstr ""
+
+#, fuzzy
+msgctxt "field:sale.complaint.action,currency_digits:"
+msgid "Currency Digits"
+msgstr "Ühiku numbriväärtus"
+
+msgctxt "field:sale.complaint.action,invoice_lines:"
+msgid "Invoice Lines"
+msgstr "Arve read"
+
+msgctxt "field:sale.complaint.action,quantity:"
+msgid "Quantity"
+msgstr "Kogus"
+
+msgctxt "field:sale.complaint.action,result:"
+msgid "Result"
+msgstr "Tulemus"
+
+msgctxt "field:sale.complaint.action,sale_lines:"
+msgid "Sale Lines"
+msgstr "Müügiread"
+
+msgctxt "field:sale.complaint.action,unit:"
+msgid "Unit"
+msgstr "Ühik"
+
+msgctxt "field:sale.complaint.action,unit_digits:"
+msgid "Unit Digits"
+msgstr "Ühiku numbriväärtus"
+
+msgctxt "field:sale.complaint.action,unit_price:"
+msgid "Unit Price"
+msgstr "Ühiku hind"
+
+msgctxt "field:sale.complaint.action-account.invoice.line,action:"
+msgid "Action"
+msgstr "Toiming"
+
+msgctxt "field:sale.complaint.action-account.invoice.line,amount:"
+msgid "Amount"
+msgstr ""
+
+#, fuzzy
+msgctxt ""
+"field:sale.complaint.action-account.invoice.line,complaint_origin_id:"
+msgid "Complaint Origin ID"
+msgstr "Päritolu ID"
+
+#, fuzzy
+msgctxt "field:sale.complaint.action-account.invoice.line,complaint_state:"
+msgid "Complaint State"
+msgstr "Kaebus"
+
+msgctxt "field:sale.complaint.action-account.invoice.line,currency:"
+msgid "Currency"
+msgstr ""
+
+#, fuzzy
+msgctxt "field:sale.complaint.action-account.invoice.line,currency_digits:"
+msgid "Currency Digits"
+msgstr "Ühiku numbriväärtus"
+
+msgctxt "field:sale.complaint.action-account.invoice.line,line:"
+msgid "Invoice Line"
+msgstr "Arve rida"
+
+#, fuzzy
+msgctxt "field:sale.complaint.action-account.invoice.line,quantity:"
+msgid "Quantity"
+msgstr "Kogus"
+
+#, fuzzy
+msgctxt "field:sale.complaint.action-account.invoice.line,unit:"
+msgid "Unit"
+msgstr "Ühik"
+
+#, fuzzy
+msgctxt "field:sale.complaint.action-account.invoice.line,unit_digits:"
+msgid "Unit Digits"
+msgstr "Ühiku numbriväärtus"
+
+#, fuzzy
+msgctxt "field:sale.complaint.action-account.invoice.line,unit_price:"
+msgid "Unit Price"
+msgstr "Ühiku hind"
+
+msgctxt "field:sale.complaint.action-sale.line,action:"
+msgid "Action"
+msgstr "Toiming"
+
+msgctxt "field:sale.complaint.action-sale.line,amount:"
+msgid "Amount"
+msgstr ""
+
+#, fuzzy
+msgctxt "field:sale.complaint.action-sale.line,complaint_origin_id:"
+msgid "Complaint Origin ID"
+msgstr "Päritolu ID"
+
+#, fuzzy
+msgctxt "field:sale.complaint.action-sale.line,complaint_state:"
+msgid "Complaint State"
+msgstr "Kaebus"
+
+msgctxt "field:sale.complaint.action-sale.line,currency:"
+msgid "Currency"
+msgstr ""
+
+#, fuzzy
+msgctxt "field:sale.complaint.action-sale.line,currency_digits:"
+msgid "Currency Digits"
+msgstr "Ühiku numbriväärtus"
+
+msgctxt "field:sale.complaint.action-sale.line,line:"
+msgid "Sale Line"
+msgstr "Müügi rida"
+
+#, fuzzy
+msgctxt "field:sale.complaint.action-sale.line,quantity:"
+msgid "Quantity"
+msgstr "Kogus"
+
+#, fuzzy
+msgctxt "field:sale.complaint.action-sale.line,unit:"
+msgid "Unit"
+msgstr "Ühik"
+
+#, fuzzy
+msgctxt "field:sale.complaint.action-sale.line,unit_digits:"
+msgid "Unit Digits"
+msgstr "Ühiku numbriväärtus"
+
+#, fuzzy
+msgctxt "field:sale.complaint.action-sale.line,unit_price:"
+msgid "Unit Price"
+msgstr "Ühiku hind"
+
+msgctxt "field:sale.complaint.type,name:"
+msgid "Name"
+msgstr "Nimetus"
+
+msgctxt "field:sale.complaint.type,origin:"
+msgid "Origin"
+msgstr "Päritolu"
+
+msgctxt "field:sale.configuration,complaint_sequence:"
+msgid "Complaint Sequence"
+msgstr "Kaebuse järjestus"
+
+msgctxt "field:sale.configuration.sequence,complaint_sequence:"
+msgid "Complaint Sequence"
+msgstr "Kaebuse järjestus"
+
+#, fuzzy
+msgctxt "help:sale.complaint.action,invoice_lines:"
+msgid "Leave empty for all lines."
+msgstr "Kõikide ridade jaosk jäta tühjaks"
+
+#, fuzzy
+msgctxt "help:sale.complaint.action,quantity:"
+msgid "Leave empty for the same quantity."
+msgstr "Sama koguse jaoks jäta tühjaks"
+
+#, fuzzy
+msgctxt "help:sale.complaint.action,sale_lines:"
+msgid "Leave empty for all lines."
+msgstr "Kõikide ridade jaoks jäta tühjaks"
+
+#, fuzzy
+msgctxt "help:sale.complaint.action,unit_price:"
+msgid "Leave empty for the same price."
+msgstr "Sama hinna jaoks jäta tühjaks"
+
+#, fuzzy
+msgctxt "help:sale.complaint.action-account.invoice.line,unit_price:"
+msgid "Leave empty for the same price."
+msgstr "Sama hinna jaoks jäta tühjaks"
+
+#, fuzzy
+msgctxt "help:sale.complaint.action-sale.line,unit_price:"
+msgid "Leave empty for the same price."
+msgstr "Sama hinna jaoks jäta tühjaks"
+
+msgctxt "model:ir.action,name:act_complaint_form"
+msgid "Complaints"
+msgstr "Kaebused"
+
+msgctxt "model:ir.action,name:act_complaint_relate_party"
+msgid "Customer Complaints"
+msgstr "Kliendikaebused"
+
+msgctxt "model:ir.action,name:act_complaint_relate_sale"
+msgid "Complaints"
+msgstr "Kaebused"
+
+msgctxt "model:ir.action,name:act_type_form"
+msgid "Types"
+msgstr "Tüübid"
+
+msgctxt "model:ir.action.act_window.domain,name:act_complaint_form_domain_all"
+msgid "All"
+msgstr "Kõik"
+
+msgctxt ""
+"model:ir.action.act_window.domain,name:act_complaint_form_domain_approved"
+msgid "Approved"
+msgstr "Kinnitatud"
+
+msgctxt ""
+"model:ir.action.act_window.domain,name:act_complaint_form_domain_draft"
+msgid "Draft"
+msgstr "Mustand"
+
+msgctxt ""
+"model:ir.action.act_window.domain,name:act_complaint_form_domain_waiting"
+msgid "Waiting"
+msgstr "Ootel"
+
+msgctxt "model:ir.message,text:msg_action_delete_result"
+msgid "You cannot delete action \"%(action)s\" because it has a result."
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_complaint_delete_draft"
+msgid "To delete complaint \"%(complaint)s\" you must reset it to draft state."
+msgstr ""
+"Kaebuse \"%(complaint)s\" kustutamiseks tuleb selle staatus muuta "
+"mustandiks."
+
+msgctxt "model:ir.model.button,string:complaint_approve_button"
+msgid "Approve"
+msgstr "Kinnita"
+
+msgctxt "model:ir.model.button,string:complaint_cancel_button"
+msgid "Cancel"
+msgstr "Tühista"
+
+msgctxt "model:ir.model.button,string:complaint_do_button"
+msgid "Process"
+msgstr "Töötle"
+
+msgctxt "model:ir.model.button,string:complaint_draft_button"
+msgid "Draft"
+msgstr "Mustand"
+
+msgctxt "model:ir.model.button,string:complaint_reject_button"
+msgid "Reject"
+msgstr "Lükka tagasi"
+
+msgctxt "model:ir.model.button,string:complaint_wait_button"
+msgid "Wait"
+msgstr "Oota"
+
+#, fuzzy
+msgctxt "model:ir.rule.group,name:rule_group_complaint_companies"
+msgid "User in companies"
+msgstr "Kasutaja ettevõttes"
+
+msgctxt "model:ir.sequence,name:sequence_complaint"
+msgid "Customer Complaint"
+msgstr "Kliendikaebus"
+
+msgctxt "model:ir.sequence.type,name:sequence_type_complaint"
+msgid "Customer Complaint"
+msgstr "Kliendikaebus"
+
+msgctxt "model:ir.ui.menu,name:menu_complaint"
+msgid "Complaints"
+msgstr "Kaebused"
+
+msgctxt "model:ir.ui.menu,name:menu_configuration"
+msgid "Customer Complaint"
+msgstr "Kliendikaebus"
+
+msgctxt "model:ir.ui.menu,name:menu_type"
+msgid "Types"
+msgstr "Tüübid"
+
+msgctxt "model:sale.complaint,name:"
+msgid "Customer Complaint"
+msgstr "Kliendikaebus"
+
+msgctxt "model:sale.complaint.action,name:"
+msgid "Customer Complaint Action"
+msgstr "Kliendikaebuse toiming"
+
+msgctxt "model:sale.complaint.action-account.invoice.line,name:"
+msgid "Customer Complaint Action - Invoice Line"
+msgstr "Kliendikaebuse toiming - arverida"
+
+msgctxt "model:sale.complaint.action-sale.line,name:"
+msgid "Customer Complaint Action - Sale Line"
+msgstr "Kliendikaebuse toiming - müügirida"
+
+msgctxt "model:sale.complaint.type,name:"
+msgid "Customer Complaint Type"
+msgstr "Kliendikaebuse tüüp"
+
+msgctxt "selection:sale.complaint,state:"
+msgid "Approved"
+msgstr "Kinnitatud"
+
+msgctxt "selection:sale.complaint,state:"
+msgid "Cancelled"
+msgstr "Tühistatud"
+
+msgctxt "selection:sale.complaint,state:"
+msgid "Done"
+msgstr "Tehtud"
+
+msgctxt "selection:sale.complaint,state:"
+msgid "Draft"
+msgstr "Mustand"
+
+msgctxt "selection:sale.complaint,state:"
+msgid "Rejected"
+msgstr "Tagasi lükatud"
+
+msgctxt "selection:sale.complaint,state:"
+msgid "Waiting"
+msgstr "Ootel"
+
+msgctxt "selection:sale.complaint.action,action:"
+msgid "Create Credit Note"
+msgstr "Loo kreeditarve"
+
+msgctxt "selection:sale.complaint.action,action:"
+msgid "Create Sale Return"
+msgstr "Loo tagastus"
+
+msgctxt "view:sale.complaint.action:"
+msgid "Amount"
+msgstr ""
+
+msgctxt "view:sale.complaint:"
+msgid "Complaint"
+msgstr "Kaebus"
+
+msgctxt "view:sale.complaint:"
+msgid "Process"
+msgstr "Töötle"
diff --git a/modules/sale_complaint/locale/fa.po b/modules/sale_complaint/locale/fa.po
new file mode 100644
index 0000000000..bb7c2c29e6
--- /dev/null
+++ b/modules/sale_complaint/locale/fa.po
@@ -0,0 +1,420 @@
+#
+msgid ""
+msgstr "Content-Type: text/plain; charset=utf-8\n"
+
+msgctxt "field:sale.complaint,actions:"
+msgid "Actions"
+msgstr "اقدامات"
+
+msgctxt "field:sale.complaint,address:"
+msgid "Address"
+msgstr "آدرس"
+
+msgctxt "field:sale.complaint,company:"
+msgid "Company"
+msgstr "شرکت"
+
+msgctxt "field:sale.complaint,customer:"
+msgid "Customer"
+msgstr "مشتری"
+
+msgctxt "field:sale.complaint,date:"
+msgid "Date"
+msgstr "تاریخ"
+
+msgctxt "field:sale.complaint,description:"
+msgid "Description"
+msgstr "شرح"
+
+msgctxt "field:sale.complaint,employee:"
+msgid "Employee"
+msgstr "کارمند"
+
+msgctxt "field:sale.complaint,number:"
+msgid "Number"
+msgstr "شماره"
+
+msgctxt "field:sale.complaint,origin:"
+msgid "Origin"
+msgstr "اصل"
+
+msgctxt "field:sale.complaint,origin_id:"
+msgid "Origin ID"
+msgstr "شناسه اصلی"
+
+msgctxt "field:sale.complaint,origin_model:"
+msgid "Origin Model"
+msgstr "مدل اصلی"
+
+msgctxt "field:sale.complaint,reference:"
+msgid "Reference"
+msgstr "مرجع"
+
+msgctxt "field:sale.complaint,state:"
+msgid "State"
+msgstr "وضعیت"
+
+msgctxt "field:sale.complaint,type:"
+msgid "Type"
+msgstr "نوع"
+
+msgctxt "field:sale.complaint.action,action:"
+msgid "Action"
+msgstr "اقدام"
+
+msgctxt "field:sale.complaint.action,amount:"
+msgid "Amount"
+msgstr ""
+
+msgctxt "field:sale.complaint.action,complaint:"
+msgid "Complaint"
+msgstr "شکایت"
+
+#, fuzzy
+msgctxt "field:sale.complaint.action,complaint_state:"
+msgid "Complaint State"
+msgstr "شکایت"
+
+msgctxt "field:sale.complaint.action,currency:"
+msgid "Currency"
+msgstr ""
+
+#, fuzzy
+msgctxt "field:sale.complaint.action,currency_digits:"
+msgid "Currency Digits"
+msgstr "ارقام واحد"
+
+msgctxt "field:sale.complaint.action,invoice_lines:"
+msgid "Invoice Lines"
+msgstr "سطرهای صورتحساب"
+
+msgctxt "field:sale.complaint.action,quantity:"
+msgid "Quantity"
+msgstr "مقدار/تعداد"
+
+msgctxt "field:sale.complaint.action,result:"
+msgid "Result"
+msgstr "نتیجه"
+
+msgctxt "field:sale.complaint.action,sale_lines:"
+msgid "Sale Lines"
+msgstr "سطرهای فروش"
+
+msgctxt "field:sale.complaint.action,unit:"
+msgid "Unit"
+msgstr "واحد"
+
+msgctxt "field:sale.complaint.action,unit_digits:"
+msgid "Unit Digits"
+msgstr "ارقام واحد"
+
+msgctxt "field:sale.complaint.action,unit_price:"
+msgid "Unit Price"
+msgstr "قیمت واحد"
+
+msgctxt "field:sale.complaint.action-account.invoice.line,action:"
+msgid "Action"
+msgstr "اقدام"
+
+msgctxt "field:sale.complaint.action-account.invoice.line,amount:"
+msgid "Amount"
+msgstr ""
+
+#, fuzzy
+msgctxt ""
+"field:sale.complaint.action-account.invoice.line,complaint_origin_id:"
+msgid "Complaint Origin ID"
+msgstr "شناسه اصلی"
+
+#, fuzzy
+msgctxt "field:sale.complaint.action-account.invoice.line,complaint_state:"
+msgid "Complaint State"
+msgstr "شکایت"
+
+msgctxt "field:sale.complaint.action-account.invoice.line,currency:"
+msgid "Currency"
+msgstr ""
+
+#, fuzzy
+msgctxt "field:sale.complaint.action-account.invoice.line,currency_digits:"
+msgid "Currency Digits"
+msgstr "ارقام واحد"
+
+msgctxt "field:sale.complaint.action-account.invoice.line,line:"
+msgid "Invoice Line"
+msgstr "سطر صورتحساب"
+
+#, fuzzy
+msgctxt "field:sale.complaint.action-account.invoice.line,quantity:"
+msgid "Quantity"
+msgstr "مقدار/تعداد"
+
+#, fuzzy
+msgctxt "field:sale.complaint.action-account.invoice.line,unit:"
+msgid "Unit"
+msgstr "واحد"
+
+#, fuzzy
+msgctxt "field:sale.complaint.action-account.invoice.line,unit_digits:"
+msgid "Unit Digits"
+msgstr "ارقام واحد"
+
+#, fuzzy
+msgctxt "field:sale.complaint.action-account.invoice.line,unit_price:"
+msgid "Unit Price"
+msgstr "قیمت واحد"
+
+msgctxt "field:sale.complaint.action-sale.line,action:"
+msgid "Action"
+msgstr "اقدام"
+
+msgctxt "field:sale.complaint.action-sale.line,amount:"
+msgid "Amount"
+msgstr ""
+
+#, fuzzy
+msgctxt "field:sale.complaint.action-sale.line,complaint_origin_id:"
+msgid "Complaint Origin ID"
+msgstr "شناسه اصلی"
+
+#, fuzzy
+msgctxt "field:sale.complaint.action-sale.line,complaint_state:"
+msgid "Complaint State"
+msgstr "شکایت"
+
+msgctxt "field:sale.complaint.action-sale.line,currency:"
+msgid "Currency"
+msgstr ""
+
+#, fuzzy
+msgctxt "field:sale.complaint.action-sale.line,currency_digits:"
+msgid "Currency Digits"
+msgstr "ارقام واحد"
+
+msgctxt "field:sale.complaint.action-sale.line,line:"
+msgid "Sale Line"
+msgstr "سطر فروش"
+
+#, fuzzy
+msgctxt "field:sale.complaint.action-sale.line,quantity:"
+msgid "Quantity"
+msgstr "مقدار/تعداد"
+
+#, fuzzy
+msgctxt "field:sale.complaint.action-sale.line,unit:"
+msgid "Unit"
+msgstr "واحد"
+
+#, fuzzy
+msgctxt "field:sale.complaint.action-sale.line,unit_digits:"
+msgid "Unit Digits"
+msgstr "ارقام واحد"
+
+#, fuzzy
+msgctxt "field:sale.complaint.action-sale.line,unit_price:"
+msgid "Unit Price"
+msgstr "قیمت واحد"
+
+msgctxt "field:sale.complaint.type,name:"
+msgid "Name"
+msgstr "نام"
+
+msgctxt "field:sale.complaint.type,origin:"
+msgid "Origin"
+msgstr "مبداء"
+
+msgctxt "field:sale.configuration,complaint_sequence:"
+msgid "Complaint Sequence"
+msgstr "ادامه شکایت"
+
+msgctxt "field:sale.configuration.sequence,complaint_sequence:"
+msgid "Complaint Sequence"
+msgstr "ادامه شکایت"
+
+#, fuzzy
+msgctxt "help:sale.complaint.action,invoice_lines:"
+msgid "Leave empty for all lines."
+msgstr "تمام سطرها را خالی بگذارید"
+
+#, fuzzy
+msgctxt "help:sale.complaint.action,quantity:"
+msgid "Leave empty for the same quantity."
+msgstr "برای همان مقدار خالی بگذارید"
+
+#, fuzzy
+msgctxt "help:sale.complaint.action,sale_lines:"
+msgid "Leave empty for all lines."
+msgstr "تمام سطرها را خالی بگذارید"
+
+#, fuzzy
+msgctxt "help:sale.complaint.action,unit_price:"
+msgid "Leave empty for the same price."
+msgstr "برای همان مبلغ خالی بگذارید"
+
+#, fuzzy
+msgctxt "help:sale.complaint.action-account.invoice.line,unit_price:"
+msgid "Leave empty for the same price."
+msgstr "برای همان مبلغ خالی بگذارید"
+
+#, fuzzy
+msgctxt "help:sale.complaint.action-sale.line,unit_price:"
+msgid "Leave empty for the same price."
+msgstr "برای همان مبلغ خالی بگذارید"
+
+msgctxt "model:ir.action,name:act_complaint_form"
+msgid "Complaints"
+msgstr "شکایات"
+
+msgctxt "model:ir.action,name:act_complaint_relate_party"
+msgid "Customer Complaints"
+msgstr "شکایات مشتری"
+
+msgctxt "model:ir.action,name:act_complaint_relate_sale"
+msgid "Complaints"
+msgstr "شکایات"
+
+msgctxt "model:ir.action,name:act_type_form"
+msgid "Types"
+msgstr "انواع"
+
+msgctxt "model:ir.action.act_window.domain,name:act_complaint_form_domain_all"
+msgid "All"
+msgstr "همه"
+
+msgctxt ""
+"model:ir.action.act_window.domain,name:act_complaint_form_domain_approved"
+msgid "Approved"
+msgstr "تصویب شده"
+
+msgctxt ""
+"model:ir.action.act_window.domain,name:act_complaint_form_domain_draft"
+msgid "Draft"
+msgstr "پیشنویس"
+
+msgctxt ""
+"model:ir.action.act_window.domain,name:act_complaint_form_domain_waiting"
+msgid "Waiting"
+msgstr "در انتظار"
+
+msgctxt "model:ir.message,text:msg_action_delete_result"
+msgid "You cannot delete action \"%(action)s\" because it has a result."
+msgstr "شما نمی توانید عمل :\"%(action)s\"را حذف کنید، چون این یک نتیجه است."
+
+msgctxt "model:ir.message,text:msg_complaint_delete_draft"
+msgid "To delete complaint \"%(complaint)s\" you must reset it to draft state."
+msgstr ""
+"برای حذف شکایت :\"%(complaint)s\" شما باید ابتدا آنرا به حالت پیش نویس "
+"بازنشانی کنید."
+
+msgctxt "model:ir.model.button,string:complaint_approve_button"
+msgid "Approve"
+msgstr "Approve"
+
+msgctxt "model:ir.model.button,string:complaint_cancel_button"
+msgid "Cancel"
+msgstr "Cancel"
+
+msgctxt "model:ir.model.button,string:complaint_do_button"
+msgid "Process"
+msgstr "Process"
+
+msgctxt "model:ir.model.button,string:complaint_draft_button"
+msgid "Draft"
+msgstr "Draft"
+
+msgctxt "model:ir.model.button,string:complaint_reject_button"
+msgid "Reject"
+msgstr "Reject"
+
+msgctxt "model:ir.model.button,string:complaint_wait_button"
+msgid "Wait"
+msgstr "Wait"
+
+#, fuzzy
+msgctxt "model:ir.rule.group,name:rule_group_complaint_companies"
+msgid "User in companies"
+msgstr "اقدام شکایت مشتری"
+
+msgctxt "model:ir.sequence,name:sequence_complaint"
+msgid "Customer Complaint"
+msgstr "شکایت مشتری"
+
+msgctxt "model:ir.sequence.type,name:sequence_type_complaint"
+msgid "Customer Complaint"
+msgstr "شکایت مشتری"
+
+msgctxt "model:ir.ui.menu,name:menu_complaint"
+msgid "Complaints"
+msgstr "شکایات"
+
+msgctxt "model:ir.ui.menu,name:menu_configuration"
+msgid "Customer Complaint"
+msgstr "شکایت مشتری"
+
+msgctxt "model:ir.ui.menu,name:menu_type"
+msgid "Types"
+msgstr "انواع"
+
+msgctxt "model:sale.complaint,name:"
+msgid "Customer Complaint"
+msgstr "شکایت مشتری"
+
+msgctxt "model:sale.complaint.action,name:"
+msgid "Customer Complaint Action"
+msgstr "اقدام شکایت مشتری"
+
+msgctxt "model:sale.complaint.action-account.invoice.line,name:"
+msgid "Customer Complaint Action - Invoice Line"
+msgstr "سطر صورتحساب - اقدام شکایت مشتری"
+
+msgctxt "model:sale.complaint.action-sale.line,name:"
+msgid "Customer Complaint Action - Sale Line"
+msgstr "سطر فروش - اقدام شکایت مشتری"
+
+msgctxt "model:sale.complaint.type,name:"
+msgid "Customer Complaint Type"
+msgstr "نوع شکایت مشتری"
+
+msgctxt "selection:sale.complaint,state:"
+msgid "Approved"
+msgstr "تصویب شده"
+
+msgctxt "selection:sale.complaint,state:"
+msgid "Cancelled"
+msgstr "لغو شده"
+
+msgctxt "selection:sale.complaint,state:"
+msgid "Done"
+msgstr "انجام شد"
+
+msgctxt "selection:sale.complaint,state:"
+msgid "Draft"
+msgstr "پیشنویس"
+
+msgctxt "selection:sale.complaint,state:"
+msgid "Rejected"
+msgstr "رد شده"
+
+msgctxt "selection:sale.complaint,state:"
+msgid "Waiting"
+msgstr "در انتظار"
+
+msgctxt "selection:sale.complaint.action,action:"
+msgid "Create Credit Note"
+msgstr "ایجاد ملاحظات خرید"
+
+msgctxt "selection:sale.complaint.action,action:"
+msgid "Create Sale Return"
+msgstr "ایجاد فروش برگشتی"
+
+msgctxt "view:sale.complaint.action:"
+msgid "Amount"
+msgstr ""
+
+msgctxt "view:sale.complaint:"
+msgid "Complaint"
+msgstr "شکایت"
+
+msgctxt "view:sale.complaint:"
+msgid "Process"
+msgstr "پردازش"
diff --git a/modules/sale_complaint/locale/fi.po b/modules/sale_complaint/locale/fi.po
new file mode 100644
index 0000000000..9541df8e51
--- /dev/null
+++ b/modules/sale_complaint/locale/fi.po
@@ -0,0 +1,413 @@
+#
+msgid ""
+msgstr "Content-Type: text/plain; charset=utf-8\n"
+
+msgctxt "field:sale.complaint,actions:"
+msgid "Actions"
+msgstr ""
+
+msgctxt "field:sale.complaint,address:"
+msgid "Address"
+msgstr ""
+
+msgctxt "field:sale.complaint,company:"
+msgid "Company"
+msgstr ""
+
+msgctxt "field:sale.complaint,customer:"
+msgid "Customer"
+msgstr ""
+
+msgctxt "field:sale.complaint,date:"
+msgid "Date"
+msgstr ""
+
+msgctxt "field:sale.complaint,description:"
+msgid "Description"
+msgstr ""
+
+msgctxt "field:sale.complaint,employee:"
+msgid "Employee"
+msgstr ""
+
+msgctxt "field:sale.complaint,number:"
+msgid "Number"
+msgstr ""
+
+msgctxt "field:sale.complaint,origin:"
+msgid "Origin"
+msgstr ""
+
+msgctxt "field:sale.complaint,origin_id:"
+msgid "Origin ID"
+msgstr ""
+
+msgctxt "field:sale.complaint,origin_model:"
+msgid "Origin Model"
+msgstr ""
+
+msgctxt "field:sale.complaint,reference:"
+msgid "Reference"
+msgstr ""
+
+msgctxt "field:sale.complaint,state:"
+msgid "State"
+msgstr ""
+
+#, fuzzy
+msgctxt "field:sale.complaint,type:"
+msgid "Type"
+msgstr "Types"
+
+msgctxt "field:sale.complaint.action,action:"
+msgid "Action"
+msgstr ""
+
+msgctxt "field:sale.complaint.action,amount:"
+msgid "Amount"
+msgstr ""
+
+#, fuzzy
+msgctxt "field:sale.complaint.action,complaint:"
+msgid "Complaint"
+msgstr "Complaints"
+
+#, fuzzy
+msgctxt "field:sale.complaint.action,complaint_state:"
+msgid "Complaint State"
+msgstr "Complaints"
+
+msgctxt "field:sale.complaint.action,currency:"
+msgid "Currency"
+msgstr ""
+
+msgctxt "field:sale.complaint.action,currency_digits:"
+msgid "Currency Digits"
+msgstr ""
+
+msgctxt "field:sale.complaint.action,invoice_lines:"
+msgid "Invoice Lines"
+msgstr ""
+
+msgctxt "field:sale.complaint.action,quantity:"
+msgid "Quantity"
+msgstr ""
+
+msgctxt "field:sale.complaint.action,result:"
+msgid "Result"
+msgstr ""
+
+msgctxt "field:sale.complaint.action,sale_lines:"
+msgid "Sale Lines"
+msgstr ""
+
+msgctxt "field:sale.complaint.action,unit:"
+msgid "Unit"
+msgstr ""
+
+msgctxt "field:sale.complaint.action,unit_digits:"
+msgid "Unit Digits"
+msgstr ""
+
+msgctxt "field:sale.complaint.action,unit_price:"
+msgid "Unit Price"
+msgstr ""
+
+msgctxt "field:sale.complaint.action-account.invoice.line,action:"
+msgid "Action"
+msgstr ""
+
+msgctxt "field:sale.complaint.action-account.invoice.line,amount:"
+msgid "Amount"
+msgstr ""
+
+#, fuzzy
+msgctxt ""
+"field:sale.complaint.action-account.invoice.line,complaint_origin_id:"
+msgid "Complaint Origin ID"
+msgstr "Complaints"
+
+#, fuzzy
+msgctxt "field:sale.complaint.action-account.invoice.line,complaint_state:"
+msgid "Complaint State"
+msgstr "Complaints"
+
+msgctxt "field:sale.complaint.action-account.invoice.line,currency:"
+msgid "Currency"
+msgstr ""
+
+msgctxt "field:sale.complaint.action-account.invoice.line,currency_digits:"
+msgid "Currency Digits"
+msgstr ""
+
+msgctxt "field:sale.complaint.action-account.invoice.line,line:"
+msgid "Invoice Line"
+msgstr ""
+
+msgctxt "field:sale.complaint.action-account.invoice.line,quantity:"
+msgid "Quantity"
+msgstr ""
+
+msgctxt "field:sale.complaint.action-account.invoice.line,unit:"
+msgid "Unit"
+msgstr ""
+
+msgctxt "field:sale.complaint.action-account.invoice.line,unit_digits:"
+msgid "Unit Digits"
+msgstr ""
+
+msgctxt "field:sale.complaint.action-account.invoice.line,unit_price:"
+msgid "Unit Price"
+msgstr ""
+
+msgctxt "field:sale.complaint.action-sale.line,action:"
+msgid "Action"
+msgstr ""
+
+msgctxt "field:sale.complaint.action-sale.line,amount:"
+msgid "Amount"
+msgstr ""
+
+#, fuzzy
+msgctxt "field:sale.complaint.action-sale.line,complaint_origin_id:"
+msgid "Complaint Origin ID"
+msgstr "Complaints"
+
+#, fuzzy
+msgctxt "field:sale.complaint.action-sale.line,complaint_state:"
+msgid "Complaint State"
+msgstr "Complaints"
+
+msgctxt "field:sale.complaint.action-sale.line,currency:"
+msgid "Currency"
+msgstr ""
+
+msgctxt "field:sale.complaint.action-sale.line,currency_digits:"
+msgid "Currency Digits"
+msgstr ""
+
+msgctxt "field:sale.complaint.action-sale.line,line:"
+msgid "Sale Line"
+msgstr ""
+
+msgctxt "field:sale.complaint.action-sale.line,quantity:"
+msgid "Quantity"
+msgstr ""
+
+msgctxt "field:sale.complaint.action-sale.line,unit:"
+msgid "Unit"
+msgstr ""
+
+msgctxt "field:sale.complaint.action-sale.line,unit_digits:"
+msgid "Unit Digits"
+msgstr ""
+
+msgctxt "field:sale.complaint.action-sale.line,unit_price:"
+msgid "Unit Price"
+msgstr ""
+
+msgctxt "field:sale.complaint.type,name:"
+msgid "Name"
+msgstr ""
+
+msgctxt "field:sale.complaint.type,origin:"
+msgid "Origin"
+msgstr ""
+
+msgctxt "field:sale.configuration,complaint_sequence:"
+msgid "Complaint Sequence"
+msgstr ""
+
+msgctxt "field:sale.configuration.sequence,complaint_sequence:"
+msgid "Complaint Sequence"
+msgstr ""
+
+msgctxt "help:sale.complaint.action,invoice_lines:"
+msgid "Leave empty for all lines."
+msgstr ""
+
+msgctxt "help:sale.complaint.action,quantity:"
+msgid "Leave empty for the same quantity."
+msgstr ""
+
+msgctxt "help:sale.complaint.action,sale_lines:"
+msgid "Leave empty for all lines."
+msgstr ""
+
+msgctxt "help:sale.complaint.action,unit_price:"
+msgid "Leave empty for the same price."
+msgstr ""
+
+msgctxt "help:sale.complaint.action-account.invoice.line,unit_price:"
+msgid "Leave empty for the same price."
+msgstr ""
+
+msgctxt "help:sale.complaint.action-sale.line,unit_price:"
+msgid "Leave empty for the same price."
+msgstr ""
+
+msgctxt "model:ir.action,name:act_complaint_form"
+msgid "Complaints"
+msgstr "Complaints"
+
+msgctxt "model:ir.action,name:act_complaint_relate_party"
+msgid "Customer Complaints"
+msgstr "Customer Complaints"
+
+msgctxt "model:ir.action,name:act_complaint_relate_sale"
+msgid "Complaints"
+msgstr "Complaints"
+
+msgctxt "model:ir.action,name:act_type_form"
+msgid "Types"
+msgstr "Types"
+
+msgctxt "model:ir.action.act_window.domain,name:act_complaint_form_domain_all"
+msgid "All"
+msgstr "All"
+
+#, fuzzy
+msgctxt ""
+"model:ir.action.act_window.domain,name:act_complaint_form_domain_approved"
+msgid "Approved"
+msgstr "Approved"
+
+msgctxt ""
+"model:ir.action.act_window.domain,name:act_complaint_form_domain_draft"
+msgid "Draft"
+msgstr "Draft"
+
+msgctxt ""
+"model:ir.action.act_window.domain,name:act_complaint_form_domain_waiting"
+msgid "Waiting"
+msgstr "Waiting"
+
+msgctxt "model:ir.message,text:msg_action_delete_result"
+msgid "You cannot delete action \"%(action)s\" because it has a result."
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_complaint_delete_draft"
+msgid "To delete complaint \"%(complaint)s\" you must reset it to draft state."
+msgstr ""
+
+msgctxt "model:ir.model.button,string:complaint_approve_button"
+msgid "Approve"
+msgstr "Approve"
+
+msgctxt "model:ir.model.button,string:complaint_cancel_button"
+msgid "Cancel"
+msgstr "Cancel"
+
+msgctxt "model:ir.model.button,string:complaint_do_button"
+msgid "Process"
+msgstr "Process"
+
+msgctxt "model:ir.model.button,string:complaint_draft_button"
+msgid "Draft"
+msgstr "Draft"
+
+msgctxt "model:ir.model.button,string:complaint_reject_button"
+msgid "Reject"
+msgstr "Reject"
+
+msgctxt "model:ir.model.button,string:complaint_wait_button"
+msgid "Wait"
+msgstr "Wait"
+
+#, fuzzy
+msgctxt "model:ir.rule.group,name:rule_group_complaint_companies"
+msgid "User in companies"
+msgstr "Customer Complaint"
+
+msgctxt "model:ir.sequence,name:sequence_complaint"
+msgid "Customer Complaint"
+msgstr "Customer Complaint"
+
+msgctxt "model:ir.sequence.type,name:sequence_type_complaint"
+msgid "Customer Complaint"
+msgstr "Customer Complaint"
+
+msgctxt "model:ir.ui.menu,name:menu_complaint"
+msgid "Complaints"
+msgstr "Complaints"
+
+msgctxt "model:ir.ui.menu,name:menu_configuration"
+msgid "Customer Complaint"
+msgstr "Customer Complaint"
+
+msgctxt "model:ir.ui.menu,name:menu_type"
+msgid "Types"
+msgstr "Types"
+
+#, fuzzy
+msgctxt "model:sale.complaint,name:"
+msgid "Customer Complaint"
+msgstr "Customer Complaint"
+
+#, fuzzy
+msgctxt "model:sale.complaint.action,name:"
+msgid "Customer Complaint Action"
+msgstr "Customer Complaint"
+
+msgctxt "model:sale.complaint.action-account.invoice.line,name:"
+msgid "Customer Complaint Action - Invoice Line"
+msgstr ""
+
+msgctxt "model:sale.complaint.action-sale.line,name:"
+msgid "Customer Complaint Action - Sale Line"
+msgstr ""
+
+#, fuzzy
+msgctxt "model:sale.complaint.type,name:"
+msgid "Customer Complaint Type"
+msgstr "Customer Complaint"
+
+#, fuzzy
+msgctxt "selection:sale.complaint,state:"
+msgid "Approved"
+msgstr "Approve"
+
+msgctxt "selection:sale.complaint,state:"
+msgid "Cancelled"
+msgstr ""
+
+msgctxt "selection:sale.complaint,state:"
+msgid "Done"
+msgstr ""
+
+#, fuzzy
+msgctxt "selection:sale.complaint,state:"
+msgid "Draft"
+msgstr "Draft"
+
+#, fuzzy
+msgctxt "selection:sale.complaint,state:"
+msgid "Rejected"
+msgstr "Reject"
+
+#, fuzzy
+msgctxt "selection:sale.complaint,state:"
+msgid "Waiting"
+msgstr "Waiting"
+
+msgctxt "selection:sale.complaint.action,action:"
+msgid "Create Credit Note"
+msgstr ""
+
+msgctxt "selection:sale.complaint.action,action:"
+msgid "Create Sale Return"
+msgstr ""
+
+msgctxt "view:sale.complaint.action:"
+msgid "Amount"
+msgstr ""
+
+#, fuzzy
+msgctxt "view:sale.complaint:"
+msgid "Complaint"
+msgstr "Complaints"
+
+#, fuzzy
+msgctxt "view:sale.complaint:"
+msgid "Process"
+msgstr "Process"
diff --git a/modules/sale_complaint/locale/fr.po b/modules/sale_complaint/locale/fr.po
new file mode 100644
index 0000000000..d6101a2316
--- /dev/null
+++ b/modules/sale_complaint/locale/fr.po
@@ -0,0 +1,399 @@
+#
+msgid ""
+msgstr "Content-Type: text/plain; charset=utf-8\n"
+
+msgctxt "field:sale.complaint,actions:"
+msgid "Actions"
+msgstr "Actions"
+
+msgctxt "field:sale.complaint,address:"
+msgid "Address"
+msgstr "Adresse"
+
+msgctxt "field:sale.complaint,company:"
+msgid "Company"
+msgstr "Société"
+
+msgctxt "field:sale.complaint,customer:"
+msgid "Customer"
+msgstr "Client"
+
+msgctxt "field:sale.complaint,date:"
+msgid "Date"
+msgstr "Date"
+
+msgctxt "field:sale.complaint,description:"
+msgid "Description"
+msgstr "Description"
+
+msgctxt "field:sale.complaint,employee:"
+msgid "Employee"
+msgstr "Employé"
+
+msgctxt "field:sale.complaint,number:"
+msgid "Number"
+msgstr "Numéro"
+
+msgctxt "field:sale.complaint,origin:"
+msgid "Origin"
+msgstr "Origine"
+
+msgctxt "field:sale.complaint,origin_id:"
+msgid "Origin ID"
+msgstr "ID de l'origine"
+
+msgctxt "field:sale.complaint,origin_model:"
+msgid "Origin Model"
+msgstr "Modèle de l'origine"
+
+msgctxt "field:sale.complaint,reference:"
+msgid "Reference"
+msgstr "Référence"
+
+msgctxt "field:sale.complaint,state:"
+msgid "State"
+msgstr "État"
+
+msgctxt "field:sale.complaint,type:"
+msgid "Type"
+msgstr "Type"
+
+msgctxt "field:sale.complaint.action,action:"
+msgid "Action"
+msgstr "Action"
+
+msgctxt "field:sale.complaint.action,amount:"
+msgid "Amount"
+msgstr "Montant"
+
+msgctxt "field:sale.complaint.action,complaint:"
+msgid "Complaint"
+msgstr "Plainte"
+
+msgctxt "field:sale.complaint.action,complaint_state:"
+msgid "Complaint State"
+msgstr "État de la plainte"
+
+msgctxt "field:sale.complaint.action,currency:"
+msgid "Currency"
+msgstr "Devise"
+
+msgctxt "field:sale.complaint.action,currency_digits:"
+msgid "Currency Digits"
+msgstr "Décimales de la devise"
+
+msgctxt "field:sale.complaint.action,invoice_lines:"
+msgid "Invoice Lines"
+msgstr "Lignes de facture"
+
+msgctxt "field:sale.complaint.action,quantity:"
+msgid "Quantity"
+msgstr "Quantité"
+
+msgctxt "field:sale.complaint.action,result:"
+msgid "Result"
+msgstr "Résultat"
+
+msgctxt "field:sale.complaint.action,sale_lines:"
+msgid "Sale Lines"
+msgstr "Lignes de vente"
+
+msgctxt "field:sale.complaint.action,unit:"
+msgid "Unit"
+msgstr "Unité"
+
+msgctxt "field:sale.complaint.action,unit_digits:"
+msgid "Unit Digits"
+msgstr "Décimales de l'unité"
+
+msgctxt "field:sale.complaint.action,unit_price:"
+msgid "Unit Price"
+msgstr "Prix unitaire"
+
+msgctxt "field:sale.complaint.action-account.invoice.line,action:"
+msgid "Action"
+msgstr "Action"
+
+msgctxt "field:sale.complaint.action-account.invoice.line,amount:"
+msgid "Amount"
+msgstr "Montant"
+
+msgctxt ""
+"field:sale.complaint.action-account.invoice.line,complaint_origin_id:"
+msgid "Complaint Origin ID"
+msgstr "ID de l'origine de la plainte"
+
+msgctxt "field:sale.complaint.action-account.invoice.line,complaint_state:"
+msgid "Complaint State"
+msgstr "État de la plainte"
+
+msgctxt "field:sale.complaint.action-account.invoice.line,currency:"
+msgid "Currency"
+msgstr "Devise"
+
+msgctxt "field:sale.complaint.action-account.invoice.line,currency_digits:"
+msgid "Currency Digits"
+msgstr "Décimales de la devise"
+
+msgctxt "field:sale.complaint.action-account.invoice.line,line:"
+msgid "Invoice Line"
+msgstr "Ligne de facture"
+
+msgctxt "field:sale.complaint.action-account.invoice.line,quantity:"
+msgid "Quantity"
+msgstr "Quantité"
+
+msgctxt "field:sale.complaint.action-account.invoice.line,unit:"
+msgid "Unit"
+msgstr "Unité"
+
+msgctxt "field:sale.complaint.action-account.invoice.line,unit_digits:"
+msgid "Unit Digits"
+msgstr "Décimales de l'unité"
+
+msgctxt "field:sale.complaint.action-account.invoice.line,unit_price:"
+msgid "Unit Price"
+msgstr "Prix unitaire"
+
+msgctxt "field:sale.complaint.action-sale.line,action:"
+msgid "Action"
+msgstr "Action"
+
+msgctxt "field:sale.complaint.action-sale.line,amount:"
+msgid "Amount"
+msgstr "Montant"
+
+msgctxt "field:sale.complaint.action-sale.line,complaint_origin_id:"
+msgid "Complaint Origin ID"
+msgstr "ID de l'origine de la plainte"
+
+msgctxt "field:sale.complaint.action-sale.line,complaint_state:"
+msgid "Complaint State"
+msgstr "État de la plainte"
+
+msgctxt "field:sale.complaint.action-sale.line,currency:"
+msgid "Currency"
+msgstr "Devise"
+
+msgctxt "field:sale.complaint.action-sale.line,currency_digits:"
+msgid "Currency Digits"
+msgstr "Décimales de la devise"
+
+msgctxt "field:sale.complaint.action-sale.line,line:"
+msgid "Sale Line"
+msgstr "Ligne de vente"
+
+msgctxt "field:sale.complaint.action-sale.line,quantity:"
+msgid "Quantity"
+msgstr "Quantité"
+
+msgctxt "field:sale.complaint.action-sale.line,unit:"
+msgid "Unit"
+msgstr "Unité"
+
+msgctxt "field:sale.complaint.action-sale.line,unit_digits:"
+msgid "Unit Digits"
+msgstr "Décimales de l'unité"
+
+msgctxt "field:sale.complaint.action-sale.line,unit_price:"
+msgid "Unit Price"
+msgstr "Prix unitaire"
+
+msgctxt "field:sale.complaint.type,name:"
+msgid "Name"
+msgstr "Nom"
+
+msgctxt "field:sale.complaint.type,origin:"
+msgid "Origin"
+msgstr "Origine"
+
+msgctxt "field:sale.configuration,complaint_sequence:"
+msgid "Complaint Sequence"
+msgstr "Séquence de plainte"
+
+msgctxt "field:sale.configuration.sequence,complaint_sequence:"
+msgid "Complaint Sequence"
+msgstr "Séquence de plainte"
+
+msgctxt "help:sale.complaint.action,invoice_lines:"
+msgid "Leave empty for all lines."
+msgstr "Laisser vide pour toutes les lignes."
+
+msgctxt "help:sale.complaint.action,quantity:"
+msgid "Leave empty for the same quantity."
+msgstr "Laisser vide pour la même quantité."
+
+msgctxt "help:sale.complaint.action,sale_lines:"
+msgid "Leave empty for all lines."
+msgstr "Laisser vide pour toutes les lignes."
+
+msgctxt "help:sale.complaint.action,unit_price:"
+msgid "Leave empty for the same price."
+msgstr "Laisser vide pour le même prix."
+
+msgctxt "help:sale.complaint.action-account.invoice.line,unit_price:"
+msgid "Leave empty for the same price."
+msgstr "Laisser vide pour le même prix."
+
+msgctxt "help:sale.complaint.action-sale.line,unit_price:"
+msgid "Leave empty for the same price."
+msgstr "Laisser vide pour le même prix."
+
+msgctxt "model:ir.action,name:act_complaint_form"
+msgid "Complaints"
+msgstr "Plaintes"
+
+msgctxt "model:ir.action,name:act_complaint_relate_party"
+msgid "Customer Complaints"
+msgstr "Plaintes clientes"
+
+msgctxt "model:ir.action,name:act_complaint_relate_sale"
+msgid "Complaints"
+msgstr "Plaintes"
+
+msgctxt "model:ir.action,name:act_type_form"
+msgid "Types"
+msgstr "Types"
+
+msgctxt "model:ir.action.act_window.domain,name:act_complaint_form_domain_all"
+msgid "All"
+msgstr "Toutes"
+
+msgctxt ""
+"model:ir.action.act_window.domain,name:act_complaint_form_domain_approved"
+msgid "Approved"
+msgstr "Approuvées"
+
+msgctxt ""
+"model:ir.action.act_window.domain,name:act_complaint_form_domain_draft"
+msgid "Draft"
+msgstr "Brouillons"
+
+msgctxt ""
+"model:ir.action.act_window.domain,name:act_complaint_form_domain_waiting"
+msgid "Waiting"
+msgstr "En attentes"
+
+msgctxt "model:ir.message,text:msg_action_delete_result"
+msgid "You cannot delete action \"%(action)s\" because it has a result."
+msgstr ""
+"Vous ne pouvez pas supprimer l'action « %(action)s » parce qu'elle a un "
+"résultat."
+
+msgctxt "model:ir.message,text:msg_complaint_delete_draft"
+msgid "To delete complaint \"%(complaint)s\" you must reset it to draft state."
+msgstr ""
+"Pour supprimer la plainte « %(complaint)s », vous devez la réinitialiser à "
+"l'état brouillon."
+
+msgctxt "model:ir.model.button,string:complaint_approve_button"
+msgid "Approve"
+msgstr "Approuver"
+
+msgctxt "model:ir.model.button,string:complaint_cancel_button"
+msgid "Cancel"
+msgstr "Annuler"
+
+msgctxt "model:ir.model.button,string:complaint_do_button"
+msgid "Process"
+msgstr "Traiter"
+
+msgctxt "model:ir.model.button,string:complaint_draft_button"
+msgid "Draft"
+msgstr "Brouillon"
+
+msgctxt "model:ir.model.button,string:complaint_reject_button"
+msgid "Reject"
+msgstr "Rejeter"
+
+msgctxt "model:ir.model.button,string:complaint_wait_button"
+msgid "Wait"
+msgstr "Attendre"
+
+msgctxt "model:ir.rule.group,name:rule_group_complaint_companies"
+msgid "User in companies"
+msgstr "Utilisateur dans les sociétés"
+
+msgctxt "model:ir.sequence,name:sequence_complaint"
+msgid "Customer Complaint"
+msgstr "Plainte cliente"
+
+msgctxt "model:ir.sequence.type,name:sequence_type_complaint"
+msgid "Customer Complaint"
+msgstr "Plainte cliente"
+
+msgctxt "model:ir.ui.menu,name:menu_complaint"
+msgid "Complaints"
+msgstr "Plaintes"
+
+msgctxt "model:ir.ui.menu,name:menu_configuration"
+msgid "Customer Complaint"
+msgstr "Plainte cliente"
+
+msgctxt "model:ir.ui.menu,name:menu_type"
+msgid "Types"
+msgstr "Types"
+
+msgctxt "model:sale.complaint,name:"
+msgid "Customer Complaint"
+msgstr "Plainte cliente"
+
+msgctxt "model:sale.complaint.action,name:"
+msgid "Customer Complaint Action"
+msgstr "Action de plainte cliente"
+
+msgctxt "model:sale.complaint.action-account.invoice.line,name:"
+msgid "Customer Complaint Action - Invoice Line"
+msgstr "Action de plainte cliente - Ligne de facture"
+
+msgctxt "model:sale.complaint.action-sale.line,name:"
+msgid "Customer Complaint Action - Sale Line"
+msgstr "Action de plainte cliente - Ligne de facture"
+
+msgctxt "model:sale.complaint.type,name:"
+msgid "Customer Complaint Type"
+msgstr "Type de plainte cliente"
+
+msgctxt "selection:sale.complaint,state:"
+msgid "Approved"
+msgstr "Approuvée"
+
+msgctxt "selection:sale.complaint,state:"
+msgid "Cancelled"
+msgstr "Annulée"
+
+msgctxt "selection:sale.complaint,state:"
+msgid "Done"
+msgstr "Terminée"
+
+msgctxt "selection:sale.complaint,state:"
+msgid "Draft"
+msgstr "Brouillon"
+
+msgctxt "selection:sale.complaint,state:"
+msgid "Rejected"
+msgstr "Rejetée"
+
+msgctxt "selection:sale.complaint,state:"
+msgid "Waiting"
+msgstr "En attente"
+
+msgctxt "selection:sale.complaint.action,action:"
+msgid "Create Credit Note"
+msgstr "Créer une note de crédit"
+
+msgctxt "selection:sale.complaint.action,action:"
+msgid "Create Sale Return"
+msgstr "Créer un retour de vente"
+
+msgctxt "view:sale.complaint.action:"
+msgid "Amount"
+msgstr "Montant"
+
+msgctxt "view:sale.complaint:"
+msgid "Complaint"
+msgstr "Plainte"
+
+msgctxt "view:sale.complaint:"
+msgid "Process"
+msgstr "Traiter"
diff --git a/modules/sale_complaint/locale/hu.po b/modules/sale_complaint/locale/hu.po
new file mode 100644
index 0000000000..4af4b7156a
--- /dev/null
+++ b/modules/sale_complaint/locale/hu.po
@@ -0,0 +1,431 @@
+#
+msgid ""
+msgstr "Content-Type: text/plain; charset=utf-8\n"
+
+msgctxt "field:sale.complaint,actions:"
+msgid "Actions"
+msgstr "Műveletek"
+
+msgctxt "field:sale.complaint,address:"
+msgid "Address"
+msgstr "Cím"
+
+msgctxt "field:sale.complaint,company:"
+msgid "Company"
+msgstr "Társaság"
+
+msgctxt "field:sale.complaint,customer:"
+msgid "Customer"
+msgstr "Vevő"
+
+msgctxt "field:sale.complaint,date:"
+msgid "Date"
+msgstr "Dátum"
+
+msgctxt "field:sale.complaint,description:"
+msgid "Description"
+msgstr "Leírás"
+
+msgctxt "field:sale.complaint,employee:"
+msgid "Employee"
+msgstr "Alkalmazott"
+
+msgctxt "field:sale.complaint,number:"
+msgid "Number"
+msgstr "Szám"
+
+msgctxt "field:sale.complaint,origin:"
+msgid "Origin"
+msgstr "Származás"
+
+msgctxt "field:sale.complaint,origin_id:"
+msgid "Origin ID"
+msgstr "Származási ID"
+
+msgctxt "field:sale.complaint,origin_model:"
+msgid "Origin Model"
+msgstr "Származási modell"
+
+msgctxt "field:sale.complaint,reference:"
+msgid "Reference"
+msgstr "Hivatkozás"
+
+msgctxt "field:sale.complaint,state:"
+msgid "State"
+msgstr "Státusz"
+
+msgctxt "field:sale.complaint,type:"
+msgid "Type"
+msgstr "Típus"
+
+msgctxt "field:sale.complaint.action,action:"
+msgid "Action"
+msgstr "Művelet"
+
+msgctxt "field:sale.complaint.action,amount:"
+msgid "Amount"
+msgstr ""
+
+msgctxt "field:sale.complaint.action,complaint:"
+msgid "Complaint"
+msgstr "Reklamáció"
+
+#, fuzzy
+msgctxt "field:sale.complaint.action,complaint_state:"
+msgid "Complaint State"
+msgstr "Reklamáció"
+
+msgctxt "field:sale.complaint.action,currency:"
+msgid "Currency"
+msgstr ""
+
+#, fuzzy
+msgctxt "field:sale.complaint.action,currency_digits:"
+msgid "Currency Digits"
+msgstr "Tizedes vessző utáni számjegy"
+
+msgctxt "field:sale.complaint.action,invoice_lines:"
+msgid "Invoice Lines"
+msgstr "Számla pozíció"
+
+msgctxt "field:sale.complaint.action,quantity:"
+msgid "Quantity"
+msgstr "Mennyiség"
+
+msgctxt "field:sale.complaint.action,result:"
+msgid "Result"
+msgstr "Eredmény"
+
+msgctxt "field:sale.complaint.action,sale_lines:"
+msgid "Sale Lines"
+msgstr "Eladási pozíció"
+
+msgctxt "field:sale.complaint.action,unit:"
+msgid "Unit"
+msgstr "Egység"
+
+msgctxt "field:sale.complaint.action,unit_digits:"
+msgid "Unit Digits"
+msgstr "Tizedes vessző utáni számjegy"
+
+msgctxt "field:sale.complaint.action,unit_price:"
+msgid "Unit Price"
+msgstr "Darab ár"
+
+msgctxt "field:sale.complaint.action-account.invoice.line,action:"
+msgid "Action"
+msgstr "Művelet"
+
+msgctxt "field:sale.complaint.action-account.invoice.line,amount:"
+msgid "Amount"
+msgstr ""
+
+#, fuzzy
+msgctxt ""
+"field:sale.complaint.action-account.invoice.line,complaint_origin_id:"
+msgid "Complaint Origin ID"
+msgstr "Származási ID"
+
+#, fuzzy
+msgctxt "field:sale.complaint.action-account.invoice.line,complaint_state:"
+msgid "Complaint State"
+msgstr "Reklamáció"
+
+msgctxt "field:sale.complaint.action-account.invoice.line,currency:"
+msgid "Currency"
+msgstr ""
+
+#, fuzzy
+msgctxt "field:sale.complaint.action-account.invoice.line,currency_digits:"
+msgid "Currency Digits"
+msgstr "Tizedes vessző utáni számjegy"
+
+msgctxt "field:sale.complaint.action-account.invoice.line,line:"
+msgid "Invoice Line"
+msgstr "Számla pozíció"
+
+#, fuzzy
+msgctxt "field:sale.complaint.action-account.invoice.line,quantity:"
+msgid "Quantity"
+msgstr "Mennyiség"
+
+#, fuzzy
+msgctxt "field:sale.complaint.action-account.invoice.line,unit:"
+msgid "Unit"
+msgstr "Egység"
+
+#, fuzzy
+msgctxt "field:sale.complaint.action-account.invoice.line,unit_digits:"
+msgid "Unit Digits"
+msgstr "Tizedes vessző utáni számjegy"
+
+#, fuzzy
+msgctxt "field:sale.complaint.action-account.invoice.line,unit_price:"
+msgid "Unit Price"
+msgstr "Darab ár"
+
+msgctxt "field:sale.complaint.action-sale.line,action:"
+msgid "Action"
+msgstr "Művelet"
+
+msgctxt "field:sale.complaint.action-sale.line,amount:"
+msgid "Amount"
+msgstr ""
+
+#, fuzzy
+msgctxt "field:sale.complaint.action-sale.line,complaint_origin_id:"
+msgid "Complaint Origin ID"
+msgstr "Származási ID"
+
+#, fuzzy
+msgctxt "field:sale.complaint.action-sale.line,complaint_state:"
+msgid "Complaint State"
+msgstr "Reklamáció"
+
+msgctxt "field:sale.complaint.action-sale.line,currency:"
+msgid "Currency"
+msgstr ""
+
+#, fuzzy
+msgctxt "field:sale.complaint.action-sale.line,currency_digits:"
+msgid "Currency Digits"
+msgstr "Tizedes vessző utáni számjegy"
+
+msgctxt "field:sale.complaint.action-sale.line,line:"
+msgid "Sale Line"
+msgstr "Eladási pozíció"
+
+#, fuzzy
+msgctxt "field:sale.complaint.action-sale.line,quantity:"
+msgid "Quantity"
+msgstr "Mennyiség"
+
+#, fuzzy
+msgctxt "field:sale.complaint.action-sale.line,unit:"
+msgid "Unit"
+msgstr "Egység"
+
+#, fuzzy
+msgctxt "field:sale.complaint.action-sale.line,unit_digits:"
+msgid "Unit Digits"
+msgstr "Tizedes vessző utáni számjegy"
+
+#, fuzzy
+msgctxt "field:sale.complaint.action-sale.line,unit_price:"
+msgid "Unit Price"
+msgstr "Darab ár"
+
+msgctxt "field:sale.complaint.type,name:"
+msgid "Name"
+msgstr "Név"
+
+msgctxt "field:sale.complaint.type,origin:"
+msgid "Origin"
+msgstr "Származás"
+
+msgctxt "field:sale.configuration,complaint_sequence:"
+msgid "Complaint Sequence"
+msgstr "Reklamáció számkör"
+
+#, fuzzy
+msgctxt "field:sale.configuration.sequence,complaint_sequence:"
+msgid "Complaint Sequence"
+msgstr "Reklamáció számkör"
+
+#, fuzzy
+msgctxt "help:sale.complaint.action,invoice_lines:"
+msgid "Leave empty for all lines."
+msgstr "Üresen hagyni a soroknak"
+
+#, fuzzy
+msgctxt "help:sale.complaint.action,quantity:"
+msgid "Leave empty for the same quantity."
+msgstr "Üresen hagyni az azonos mennyiségnek"
+
+msgctxt "help:sale.complaint.action,sale_lines:"
+msgid "Leave empty for all lines."
+msgstr "Hagyja üresen az összes sorhoz."
+
+#, fuzzy
+msgctxt "help:sale.complaint.action,unit_price:"
+msgid "Leave empty for the same price."
+msgstr "Üresen hagyni az azonos árnak"
+
+#, fuzzy
+msgctxt "help:sale.complaint.action-account.invoice.line,unit_price:"
+msgid "Leave empty for the same price."
+msgstr "Üresen hagyni az azonos árnak"
+
+#, fuzzy
+msgctxt "help:sale.complaint.action-sale.line,unit_price:"
+msgid "Leave empty for the same price."
+msgstr "Üresen hagyni az azonos árnak"
+
+#, fuzzy
+msgctxt "model:ir.action,name:act_complaint_form"
+msgid "Complaints"
+msgstr "Complaints"
+
+#, fuzzy
+msgctxt "model:ir.action,name:act_complaint_relate_party"
+msgid "Customer Complaints"
+msgstr "Customer Complaints"
+
+#, fuzzy
+msgctxt "model:ir.action,name:act_complaint_relate_sale"
+msgid "Complaints"
+msgstr "Complaints"
+
+#, fuzzy
+msgctxt "model:ir.action,name:act_type_form"
+msgid "Types"
+msgstr "Types"
+
+#, fuzzy
+msgctxt "model:ir.action.act_window.domain,name:act_complaint_form_domain_all"
+msgid "All"
+msgstr "All"
+
+#, fuzzy
+msgctxt ""
+"model:ir.action.act_window.domain,name:act_complaint_form_domain_approved"
+msgid "Approved"
+msgstr "Approved"
+
+#, fuzzy
+msgctxt ""
+"model:ir.action.act_window.domain,name:act_complaint_form_domain_draft"
+msgid "Draft"
+msgstr "Draft"
+
+#, fuzzy
+msgctxt ""
+"model:ir.action.act_window.domain,name:act_complaint_form_domain_waiting"
+msgid "Waiting"
+msgstr "Waiting"
+
+msgctxt "model:ir.message,text:msg_action_delete_result"
+msgid "You cannot delete action \"%(action)s\" because it has a result."
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_complaint_delete_draft"
+msgid "To delete complaint \"%(complaint)s\" you must reset it to draft state."
+msgstr ""
+
+msgctxt "model:ir.model.button,string:complaint_approve_button"
+msgid "Approve"
+msgstr "Approve"
+
+msgctxt "model:ir.model.button,string:complaint_cancel_button"
+msgid "Cancel"
+msgstr "Cancel"
+
+msgctxt "model:ir.model.button,string:complaint_do_button"
+msgid "Process"
+msgstr "Process"
+
+msgctxt "model:ir.model.button,string:complaint_draft_button"
+msgid "Draft"
+msgstr "Draft"
+
+msgctxt "model:ir.model.button,string:complaint_reject_button"
+msgid "Reject"
+msgstr "Reject"
+
+msgctxt "model:ir.model.button,string:complaint_wait_button"
+msgid "Wait"
+msgstr "Wait"
+
+#, fuzzy
+msgctxt "model:ir.rule.group,name:rule_group_complaint_companies"
+msgid "User in companies"
+msgstr "Reklamációs művelet"
+
+#, fuzzy
+msgctxt "model:ir.sequence,name:sequence_complaint"
+msgid "Customer Complaint"
+msgstr "Customer Complaint"
+
+#, fuzzy
+msgctxt "model:ir.sequence.type,name:sequence_type_complaint"
+msgid "Customer Complaint"
+msgstr "Customer Complaint"
+
+#, fuzzy
+msgctxt "model:ir.ui.menu,name:menu_complaint"
+msgid "Complaints"
+msgstr "Complaints"
+
+#, fuzzy
+msgctxt "model:ir.ui.menu,name:menu_configuration"
+msgid "Customer Complaint"
+msgstr "Customer Complaint"
+
+#, fuzzy
+msgctxt "model:ir.ui.menu,name:menu_type"
+msgid "Types"
+msgstr "Types"
+
+msgctxt "model:sale.complaint,name:"
+msgid "Customer Complaint"
+msgstr "Reklamáció"
+
+msgctxt "model:sale.complaint.action,name:"
+msgid "Customer Complaint Action"
+msgstr "Reklamációs művelet"
+
+msgctxt "model:sale.complaint.action-account.invoice.line,name:"
+msgid "Customer Complaint Action - Invoice Line"
+msgstr "Reklamációs művelet- Számla pozíció"
+
+msgctxt "model:sale.complaint.action-sale.line,name:"
+msgid "Customer Complaint Action - Sale Line"
+msgstr "Reklamációs művelet- Eladási pozíció"
+
+msgctxt "model:sale.complaint.type,name:"
+msgid "Customer Complaint Type"
+msgstr "Reklamáció típusa"
+
+msgctxt "selection:sale.complaint,state:"
+msgid "Approved"
+msgstr "Jóváhagyva"
+
+msgctxt "selection:sale.complaint,state:"
+msgid "Cancelled"
+msgstr "Megszakítva"
+
+msgctxt "selection:sale.complaint,state:"
+msgid "Done"
+msgstr "Kész"
+
+msgctxt "selection:sale.complaint,state:"
+msgid "Draft"
+msgstr "Piszkozat"
+
+msgctxt "selection:sale.complaint,state:"
+msgid "Rejected"
+msgstr "Elutasított"
+
+msgctxt "selection:sale.complaint,state:"
+msgid "Waiting"
+msgstr "Várakozás"
+
+msgctxt "selection:sale.complaint.action,action:"
+msgid "Create Credit Note"
+msgstr "Jóváíró kiállítása"
+
+msgctxt "selection:sale.complaint.action,action:"
+msgid "Create Sale Return"
+msgstr "Visszavonás kiállítása"
+
+msgctxt "view:sale.complaint.action:"
+msgid "Amount"
+msgstr ""
+
+msgctxt "view:sale.complaint:"
+msgid "Complaint"
+msgstr "Reklamáció"
+
+msgctxt "view:sale.complaint:"
+msgid "Process"
+msgstr "Kivitelez"
diff --git a/modules/sale_complaint/locale/id.po b/modules/sale_complaint/locale/id.po
new file mode 100644
index 0000000000..1d507c232b
--- /dev/null
+++ b/modules/sale_complaint/locale/id.po
@@ -0,0 +1,401 @@
+#
+msgid ""
+msgstr "Content-Type: text/plain; charset=utf-8\n"
+
+msgctxt "field:sale.complaint,actions:"
+msgid "Actions"
+msgstr "Tindakan"
+
+msgctxt "field:sale.complaint,address:"
+msgid "Address"
+msgstr "Alamat"
+
+msgctxt "field:sale.complaint,company:"
+msgid "Company"
+msgstr "Perusahaan"
+
+msgctxt "field:sale.complaint,customer:"
+msgid "Customer"
+msgstr "Pelanggan"
+
+msgctxt "field:sale.complaint,date:"
+msgid "Date"
+msgstr "Tanggal"
+
+msgctxt "field:sale.complaint,description:"
+msgid "Description"
+msgstr "Deskripsi"
+
+msgctxt "field:sale.complaint,employee:"
+msgid "Employee"
+msgstr "Pegawai"
+
+msgctxt "field:sale.complaint,number:"
+msgid "Number"
+msgstr "Nomor"
+
+msgctxt "field:sale.complaint,origin:"
+msgid "Origin"
+msgstr "Asal"
+
+msgctxt "field:sale.complaint,origin_id:"
+msgid "Origin ID"
+msgstr "ID Asal"
+
+msgctxt "field:sale.complaint,origin_model:"
+msgid "Origin Model"
+msgstr "Model Asal"
+
+msgctxt "field:sale.complaint,reference:"
+msgid "Reference"
+msgstr "Referensi"
+
+msgctxt "field:sale.complaint,state:"
+msgid "State"
+msgstr "Status"
+
+msgctxt "field:sale.complaint,type:"
+msgid "Type"
+msgstr "Jenis"
+
+msgctxt "field:sale.complaint.action,action:"
+msgid "Action"
+msgstr "Tindakan"
+
+msgctxt "field:sale.complaint.action,amount:"
+msgid "Amount"
+msgstr ""
+
+msgctxt "field:sale.complaint.action,complaint:"
+msgid "Complaint"
+msgstr "Keluhan"
+
+#, fuzzy
+msgctxt "field:sale.complaint.action,complaint_state:"
+msgid "Complaint State"
+msgstr "Keluhan"
+
+msgctxt "field:sale.complaint.action,currency:"
+msgid "Currency"
+msgstr ""
+
+msgctxt "field:sale.complaint.action,currency_digits:"
+msgid "Currency Digits"
+msgstr ""
+
+msgctxt "field:sale.complaint.action,invoice_lines:"
+msgid "Invoice Lines"
+msgstr "Baris Faktur"
+
+msgctxt "field:sale.complaint.action,quantity:"
+msgid "Quantity"
+msgstr ""
+
+msgctxt "field:sale.complaint.action,result:"
+msgid "Result"
+msgstr ""
+
+msgctxt "field:sale.complaint.action,sale_lines:"
+msgid "Sale Lines"
+msgstr ""
+
+msgctxt "field:sale.complaint.action,unit:"
+msgid "Unit"
+msgstr ""
+
+msgctxt "field:sale.complaint.action,unit_digits:"
+msgid "Unit Digits"
+msgstr ""
+
+msgctxt "field:sale.complaint.action,unit_price:"
+msgid "Unit Price"
+msgstr ""
+
+msgctxt "field:sale.complaint.action-account.invoice.line,action:"
+msgid "Action"
+msgstr "Tindakan"
+
+msgctxt "field:sale.complaint.action-account.invoice.line,amount:"
+msgid "Amount"
+msgstr ""
+
+#, fuzzy
+msgctxt ""
+"field:sale.complaint.action-account.invoice.line,complaint_origin_id:"
+msgid "Complaint Origin ID"
+msgstr "ID Asal"
+
+#, fuzzy
+msgctxt "field:sale.complaint.action-account.invoice.line,complaint_state:"
+msgid "Complaint State"
+msgstr "Keluhan"
+
+msgctxt "field:sale.complaint.action-account.invoice.line,currency:"
+msgid "Currency"
+msgstr ""
+
+msgctxt "field:sale.complaint.action-account.invoice.line,currency_digits:"
+msgid "Currency Digits"
+msgstr ""
+
+msgctxt "field:sale.complaint.action-account.invoice.line,line:"
+msgid "Invoice Line"
+msgstr "Baris Faktur"
+
+msgctxt "field:sale.complaint.action-account.invoice.line,quantity:"
+msgid "Quantity"
+msgstr ""
+
+msgctxt "field:sale.complaint.action-account.invoice.line,unit:"
+msgid "Unit"
+msgstr ""
+
+msgctxt "field:sale.complaint.action-account.invoice.line,unit_digits:"
+msgid "Unit Digits"
+msgstr ""
+
+msgctxt "field:sale.complaint.action-account.invoice.line,unit_price:"
+msgid "Unit Price"
+msgstr ""
+
+msgctxt "field:sale.complaint.action-sale.line,action:"
+msgid "Action"
+msgstr "Tindakan"
+
+msgctxt "field:sale.complaint.action-sale.line,amount:"
+msgid "Amount"
+msgstr ""
+
+#, fuzzy
+msgctxt "field:sale.complaint.action-sale.line,complaint_origin_id:"
+msgid "Complaint Origin ID"
+msgstr "ID Asal"
+
+#, fuzzy
+msgctxt "field:sale.complaint.action-sale.line,complaint_state:"
+msgid "Complaint State"
+msgstr "Keluhan"
+
+msgctxt "field:sale.complaint.action-sale.line,currency:"
+msgid "Currency"
+msgstr ""
+
+msgctxt "field:sale.complaint.action-sale.line,currency_digits:"
+msgid "Currency Digits"
+msgstr ""
+
+msgctxt "field:sale.complaint.action-sale.line,line:"
+msgid "Sale Line"
+msgstr "Baris Penjualan"
+
+msgctxt "field:sale.complaint.action-sale.line,quantity:"
+msgid "Quantity"
+msgstr ""
+
+msgctxt "field:sale.complaint.action-sale.line,unit:"
+msgid "Unit"
+msgstr ""
+
+msgctxt "field:sale.complaint.action-sale.line,unit_digits:"
+msgid "Unit Digits"
+msgstr ""
+
+msgctxt "field:sale.complaint.action-sale.line,unit_price:"
+msgid "Unit Price"
+msgstr ""
+
+msgctxt "field:sale.complaint.type,name:"
+msgid "Name"
+msgstr "Nama"
+
+msgctxt "field:sale.complaint.type,origin:"
+msgid "Origin"
+msgstr "Asal"
+
+msgctxt "field:sale.configuration,complaint_sequence:"
+msgid "Complaint Sequence"
+msgstr "Urutan Keluhan"
+
+msgctxt "field:sale.configuration.sequence,complaint_sequence:"
+msgid "Complaint Sequence"
+msgstr "Urutan Keluhan"
+
+msgctxt "help:sale.complaint.action,invoice_lines:"
+msgid "Leave empty for all lines."
+msgstr "Biarkan kosong untuk semua baris."
+
+msgctxt "help:sale.complaint.action,quantity:"
+msgid "Leave empty for the same quantity."
+msgstr "Biarkan kosong untuk jumlah yang sama."
+
+msgctxt "help:sale.complaint.action,sale_lines:"
+msgid "Leave empty for all lines."
+msgstr "Biarkan kosong untuk semua baris."
+
+msgctxt "help:sale.complaint.action,unit_price:"
+msgid "Leave empty for the same price."
+msgstr "Biarkan kosong untuk harga yang sama."
+
+msgctxt "help:sale.complaint.action-account.invoice.line,unit_price:"
+msgid "Leave empty for the same price."
+msgstr "Biarkan kosong untuk harga yang sama."
+
+msgctxt "help:sale.complaint.action-sale.line,unit_price:"
+msgid "Leave empty for the same price."
+msgstr "Biarkan kosong untuk harga yang sama."
+
+msgctxt "model:ir.action,name:act_complaint_form"
+msgid "Complaints"
+msgstr "Keluhan-keluhan"
+
+msgctxt "model:ir.action,name:act_complaint_relate_party"
+msgid "Customer Complaints"
+msgstr "Keluhan Pelanggan"
+
+msgctxt "model:ir.action,name:act_complaint_relate_sale"
+msgid "Complaints"
+msgstr "Keluhan-keluhan"
+
+msgctxt "model:ir.action,name:act_type_form"
+msgid "Types"
+msgstr ""
+
+msgctxt "model:ir.action.act_window.domain,name:act_complaint_form_domain_all"
+msgid "All"
+msgstr ""
+
+msgctxt ""
+"model:ir.action.act_window.domain,name:act_complaint_form_domain_approved"
+msgid "Approved"
+msgstr ""
+
+msgctxt ""
+"model:ir.action.act_window.domain,name:act_complaint_form_domain_draft"
+msgid "Draft"
+msgstr "Rancangan"
+
+msgctxt ""
+"model:ir.action.act_window.domain,name:act_complaint_form_domain_waiting"
+msgid "Waiting"
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_action_delete_result"
+msgid "You cannot delete action \"%(action)s\" because it has a result."
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_complaint_delete_draft"
+msgid "To delete complaint \"%(complaint)s\" you must reset it to draft state."
+msgstr ""
+
+msgctxt "model:ir.model.button,string:complaint_approve_button"
+msgid "Approve"
+msgstr ""
+
+msgctxt "model:ir.model.button,string:complaint_cancel_button"
+msgid "Cancel"
+msgstr "Batal"
+
+msgctxt "model:ir.model.button,string:complaint_do_button"
+msgid "Process"
+msgstr "Proses"
+
+msgctxt "model:ir.model.button,string:complaint_draft_button"
+msgid "Draft"
+msgstr "Rancangan"
+
+msgctxt "model:ir.model.button,string:complaint_reject_button"
+msgid "Reject"
+msgstr ""
+
+msgctxt "model:ir.model.button,string:complaint_wait_button"
+msgid "Wait"
+msgstr ""
+
+#, fuzzy
+msgctxt "model:ir.rule.group,name:rule_group_complaint_companies"
+msgid "User in companies"
+msgstr "Pengguna di dalam perusahaan"
+
+msgctxt "model:ir.sequence,name:sequence_complaint"
+msgid "Customer Complaint"
+msgstr "Keluhan Pelanggan"
+
+msgctxt "model:ir.sequence.type,name:sequence_type_complaint"
+msgid "Customer Complaint"
+msgstr "Keluhan Pelanggan"
+
+msgctxt "model:ir.ui.menu,name:menu_complaint"
+msgid "Complaints"
+msgstr "Keluhan-keluhan"
+
+msgctxt "model:ir.ui.menu,name:menu_configuration"
+msgid "Customer Complaint"
+msgstr "Keluhan Pelanggan"
+
+msgctxt "model:ir.ui.menu,name:menu_type"
+msgid "Types"
+msgstr ""
+
+msgctxt "model:sale.complaint,name:"
+msgid "Customer Complaint"
+msgstr ""
+
+msgctxt "model:sale.complaint.action,name:"
+msgid "Customer Complaint Action"
+msgstr ""
+
+msgctxt "model:sale.complaint.action-account.invoice.line,name:"
+msgid "Customer Complaint Action - Invoice Line"
+msgstr ""
+
+msgctxt "model:sale.complaint.action-sale.line,name:"
+msgid "Customer Complaint Action - Sale Line"
+msgstr ""
+
+msgctxt "model:sale.complaint.type,name:"
+msgid "Customer Complaint Type"
+msgstr ""
+
+msgctxt "selection:sale.complaint,state:"
+msgid "Approved"
+msgstr ""
+
+msgctxt "selection:sale.complaint,state:"
+msgid "Cancelled"
+msgstr ""
+
+msgctxt "selection:sale.complaint,state:"
+msgid "Done"
+msgstr ""
+
+msgctxt "selection:sale.complaint,state:"
+msgid "Draft"
+msgstr "Rancangan"
+
+msgctxt "selection:sale.complaint,state:"
+msgid "Rejected"
+msgstr ""
+
+msgctxt "selection:sale.complaint,state:"
+msgid "Waiting"
+msgstr ""
+
+msgctxt "selection:sale.complaint.action,action:"
+msgid "Create Credit Note"
+msgstr ""
+
+msgctxt "selection:sale.complaint.action,action:"
+msgid "Create Sale Return"
+msgstr ""
+
+msgctxt "view:sale.complaint.action:"
+msgid "Amount"
+msgstr ""
+
+msgctxt "view:sale.complaint:"
+msgid "Complaint"
+msgstr "Keluhan"
+
+msgctxt "view:sale.complaint:"
+msgid "Process"
+msgstr "Proses"
diff --git a/modules/sale_complaint/locale/it.po b/modules/sale_complaint/locale/it.po
new file mode 100644
index 0000000000..aece5cb4c9
--- /dev/null
+++ b/modules/sale_complaint/locale/it.po
@@ -0,0 +1,430 @@
+#
+msgid ""
+msgstr "Content-Type: text/plain; charset=utf-8\n"
+
+msgctxt "field:sale.complaint,actions:"
+msgid "Actions"
+msgstr "Azioni"
+
+msgctxt "field:sale.complaint,address:"
+msgid "Address"
+msgstr "Indirizzo"
+
+msgctxt "field:sale.complaint,company:"
+msgid "Company"
+msgstr "Azienda"
+
+msgctxt "field:sale.complaint,customer:"
+msgid "Customer"
+msgstr "Cliente"
+
+msgctxt "field:sale.complaint,date:"
+msgid "Date"
+msgstr "Data"
+
+msgctxt "field:sale.complaint,description:"
+msgid "Description"
+msgstr "Descrizione"
+
+msgctxt "field:sale.complaint,employee:"
+msgid "Employee"
+msgstr "Dipendente"
+
+msgctxt "field:sale.complaint,number:"
+msgid "Number"
+msgstr "Numero"
+
+msgctxt "field:sale.complaint,origin:"
+msgid "Origin"
+msgstr "Origine"
+
+msgctxt "field:sale.complaint,origin_id:"
+msgid "Origin ID"
+msgstr "ID origine"
+
+msgctxt "field:sale.complaint,origin_model:"
+msgid "Origin Model"
+msgstr "modello origine"
+
+msgctxt "field:sale.complaint,reference:"
+msgid "Reference"
+msgstr "Riferimento"
+
+msgctxt "field:sale.complaint,state:"
+msgid "State"
+msgstr "Stato"
+
+msgctxt "field:sale.complaint,type:"
+msgid "Type"
+msgstr "Tipo"
+
+msgctxt "field:sale.complaint.action,action:"
+msgid "Action"
+msgstr "Azione"
+
+msgctxt "field:sale.complaint.action,amount:"
+msgid "Amount"
+msgstr ""
+
+msgctxt "field:sale.complaint.action,complaint:"
+msgid "Complaint"
+msgstr "reclamo"
+
+#, fuzzy
+msgctxt "field:sale.complaint.action,complaint_state:"
+msgid "Complaint State"
+msgstr "reclamo"
+
+msgctxt "field:sale.complaint.action,currency:"
+msgid "Currency"
+msgstr ""
+
+#, fuzzy
+msgctxt "field:sale.complaint.action,currency_digits:"
+msgid "Currency Digits"
+msgstr "Posizioni Unità"
+
+msgctxt "field:sale.complaint.action,invoice_lines:"
+msgid "Invoice Lines"
+msgstr "Righe fattura"
+
+msgctxt "field:sale.complaint.action,quantity:"
+msgid "Quantity"
+msgstr "Quantità"
+
+msgctxt "field:sale.complaint.action,result:"
+msgid "Result"
+msgstr "Risultato"
+
+msgctxt "field:sale.complaint.action,sale_lines:"
+msgid "Sale Lines"
+msgstr "righe vendita"
+
+msgctxt "field:sale.complaint.action,unit:"
+msgid "Unit"
+msgstr "Unità"
+
+msgctxt "field:sale.complaint.action,unit_digits:"
+msgid "Unit Digits"
+msgstr "Posizioni Unità"
+
+msgctxt "field:sale.complaint.action,unit_price:"
+msgid "Unit Price"
+msgstr "Prezzo unitario"
+
+msgctxt "field:sale.complaint.action-account.invoice.line,action:"
+msgid "Action"
+msgstr "Azione"
+
+msgctxt "field:sale.complaint.action-account.invoice.line,amount:"
+msgid "Amount"
+msgstr ""
+
+#, fuzzy
+msgctxt ""
+"field:sale.complaint.action-account.invoice.line,complaint_origin_id:"
+msgid "Complaint Origin ID"
+msgstr "ID origine"
+
+#, fuzzy
+msgctxt "field:sale.complaint.action-account.invoice.line,complaint_state:"
+msgid "Complaint State"
+msgstr "reclamo"
+
+msgctxt "field:sale.complaint.action-account.invoice.line,currency:"
+msgid "Currency"
+msgstr ""
+
+#, fuzzy
+msgctxt "field:sale.complaint.action-account.invoice.line,currency_digits:"
+msgid "Currency Digits"
+msgstr "Posizioni Unità"
+
+msgctxt "field:sale.complaint.action-account.invoice.line,line:"
+msgid "Invoice Line"
+msgstr "Riga fattura"
+
+msgctxt "field:sale.complaint.action-account.invoice.line,quantity:"
+msgid "Quantity"
+msgstr "Quantità"
+
+#, fuzzy
+msgctxt "field:sale.complaint.action-account.invoice.line,unit:"
+msgid "Unit"
+msgstr "Unità"
+
+#, fuzzy
+msgctxt "field:sale.complaint.action-account.invoice.line,unit_digits:"
+msgid "Unit Digits"
+msgstr "Posizioni Unità"
+
+#, fuzzy
+msgctxt "field:sale.complaint.action-account.invoice.line,unit_price:"
+msgid "Unit Price"
+msgstr "Prezzo unitario"
+
+msgctxt "field:sale.complaint.action-sale.line,action:"
+msgid "Action"
+msgstr "Azione"
+
+msgctxt "field:sale.complaint.action-sale.line,amount:"
+msgid "Amount"
+msgstr ""
+
+#, fuzzy
+msgctxt "field:sale.complaint.action-sale.line,complaint_origin_id:"
+msgid "Complaint Origin ID"
+msgstr "ID origine"
+
+#, fuzzy
+msgctxt "field:sale.complaint.action-sale.line,complaint_state:"
+msgid "Complaint State"
+msgstr "reclamo"
+
+msgctxt "field:sale.complaint.action-sale.line,currency:"
+msgid "Currency"
+msgstr ""
+
+#, fuzzy
+msgctxt "field:sale.complaint.action-sale.line,currency_digits:"
+msgid "Currency Digits"
+msgstr "Posizioni Unità"
+
+msgctxt "field:sale.complaint.action-sale.line,line:"
+msgid "Sale Line"
+msgstr "riga vendita"
+
+msgctxt "field:sale.complaint.action-sale.line,quantity:"
+msgid "Quantity"
+msgstr "Quantità"
+
+#, fuzzy
+msgctxt "field:sale.complaint.action-sale.line,unit:"
+msgid "Unit"
+msgstr "Unità"
+
+#, fuzzy
+msgctxt "field:sale.complaint.action-sale.line,unit_digits:"
+msgid "Unit Digits"
+msgstr "Posizioni Unità"
+
+#, fuzzy
+msgctxt "field:sale.complaint.action-sale.line,unit_price:"
+msgid "Unit Price"
+msgstr "Prezzo unitario"
+
+msgctxt "field:sale.complaint.type,name:"
+msgid "Name"
+msgstr "Nome"
+
+msgctxt "field:sale.complaint.type,origin:"
+msgid "Origin"
+msgstr "Origine"
+
+msgctxt "field:sale.configuration,complaint_sequence:"
+msgid "Complaint Sequence"
+msgstr "sequenza reclamo"
+
+#, fuzzy
+msgctxt "field:sale.configuration.sequence,complaint_sequence:"
+msgid "Complaint Sequence"
+msgstr "sequenza reclamo"
+
+#, fuzzy
+msgctxt "help:sale.complaint.action,invoice_lines:"
+msgid "Leave empty for all lines."
+msgstr "lasciare vuoto per tutte le righe"
+
+#, fuzzy
+msgctxt "help:sale.complaint.action,quantity:"
+msgid "Leave empty for the same quantity."
+msgstr "lasciare vuoto per la stessa quantita"
+
+#, fuzzy
+msgctxt "help:sale.complaint.action,sale_lines:"
+msgid "Leave empty for all lines."
+msgstr "lasciare vuoto per tutte le righe"
+
+#, fuzzy
+msgctxt "help:sale.complaint.action,unit_price:"
+msgid "Leave empty for the same price."
+msgstr "lasciare vuoto per stesso prezzo"
+
+#, fuzzy
+msgctxt "help:sale.complaint.action-account.invoice.line,unit_price:"
+msgid "Leave empty for the same price."
+msgstr "lasciare vuoto per stesso prezzo"
+
+#, fuzzy
+msgctxt "help:sale.complaint.action-sale.line,unit_price:"
+msgid "Leave empty for the same price."
+msgstr "lasciare vuoto per stesso prezzo"
+
+#, fuzzy
+msgctxt "model:ir.action,name:act_complaint_form"
+msgid "Complaints"
+msgstr "Complaints"
+
+#, fuzzy
+msgctxt "model:ir.action,name:act_complaint_relate_party"
+msgid "Customer Complaints"
+msgstr "Customer Complaints"
+
+#, fuzzy
+msgctxt "model:ir.action,name:act_complaint_relate_sale"
+msgid "Complaints"
+msgstr "Complaints"
+
+#, fuzzy
+msgctxt "model:ir.action,name:act_type_form"
+msgid "Types"
+msgstr "Types"
+
+#, fuzzy
+msgctxt "model:ir.action.act_window.domain,name:act_complaint_form_domain_all"
+msgid "All"
+msgstr "All"
+
+#, fuzzy
+msgctxt ""
+"model:ir.action.act_window.domain,name:act_complaint_form_domain_approved"
+msgid "Approved"
+msgstr "Approved"
+
+#, fuzzy
+msgctxt ""
+"model:ir.action.act_window.domain,name:act_complaint_form_domain_draft"
+msgid "Draft"
+msgstr "Draft"
+
+#, fuzzy
+msgctxt ""
+"model:ir.action.act_window.domain,name:act_complaint_form_domain_waiting"
+msgid "Waiting"
+msgstr "Waiting"
+
+msgctxt "model:ir.message,text:msg_action_delete_result"
+msgid "You cannot delete action \"%(action)s\" because it has a result."
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_complaint_delete_draft"
+msgid "To delete complaint \"%(complaint)s\" you must reset it to draft state."
+msgstr ""
+
+msgctxt "model:ir.model.button,string:complaint_approve_button"
+msgid "Approve"
+msgstr "Approve"
+
+msgctxt "model:ir.model.button,string:complaint_cancel_button"
+msgid "Cancel"
+msgstr "Annulla"
+
+msgctxt "model:ir.model.button,string:complaint_do_button"
+msgid "Process"
+msgstr "Process"
+
+msgctxt "model:ir.model.button,string:complaint_draft_button"
+msgid "Draft"
+msgstr "Draft"
+
+msgctxt "model:ir.model.button,string:complaint_reject_button"
+msgid "Reject"
+msgstr "Reject"
+
+msgctxt "model:ir.model.button,string:complaint_wait_button"
+msgid "Wait"
+msgstr "Wait"
+
+#, fuzzy
+msgctxt "model:ir.rule.group,name:rule_group_complaint_companies"
+msgid "User in companies"
+msgstr "azione reclamo da cliente"
+
+#, fuzzy
+msgctxt "model:ir.sequence,name:sequence_complaint"
+msgid "Customer Complaint"
+msgstr "Customer Complaint"
+
+#, fuzzy
+msgctxt "model:ir.sequence.type,name:sequence_type_complaint"
+msgid "Customer Complaint"
+msgstr "Customer Complaint"
+
+#, fuzzy
+msgctxt "model:ir.ui.menu,name:menu_complaint"
+msgid "Complaints"
+msgstr "Complaints"
+
+#, fuzzy
+msgctxt "model:ir.ui.menu,name:menu_configuration"
+msgid "Customer Complaint"
+msgstr "Customer Complaint"
+
+#, fuzzy
+msgctxt "model:ir.ui.menu,name:menu_type"
+msgid "Types"
+msgstr "Types"
+
+msgctxt "model:sale.complaint,name:"
+msgid "Customer Complaint"
+msgstr "reclamo da cliente"
+
+msgctxt "model:sale.complaint.action,name:"
+msgid "Customer Complaint Action"
+msgstr "azione reclamo da cliente"
+
+msgctxt "model:sale.complaint.action-account.invoice.line,name:"
+msgid "Customer Complaint Action - Invoice Line"
+msgstr "azione reclamo cliente - riga fattura"
+
+msgctxt "model:sale.complaint.action-sale.line,name:"
+msgid "Customer Complaint Action - Sale Line"
+msgstr "azione reclamo cliente - riga vendita"
+
+msgctxt "model:sale.complaint.type,name:"
+msgid "Customer Complaint Type"
+msgstr "tipo reclamo cliente"
+
+msgctxt "selection:sale.complaint,state:"
+msgid "Approved"
+msgstr "Approvato"
+
+msgctxt "selection:sale.complaint,state:"
+msgid "Cancelled"
+msgstr "Annullato"
+
+msgctxt "selection:sale.complaint,state:"
+msgid "Done"
+msgstr "Fatto"
+
+msgctxt "selection:sale.complaint,state:"
+msgid "Draft"
+msgstr "Bozza"
+
+msgctxt "selection:sale.complaint,state:"
+msgid "Rejected"
+msgstr "Rifiutato"
+
+msgctxt "selection:sale.complaint,state:"
+msgid "Waiting"
+msgstr "In attesa"
+
+msgctxt "selection:sale.complaint.action,action:"
+msgid "Create Credit Note"
+msgstr "creazione nota di credito"
+
+msgctxt "selection:sale.complaint.action,action:"
+msgid "Create Sale Return"
+msgstr "creazione reso da vendita"
+
+msgctxt "view:sale.complaint.action:"
+msgid "Amount"
+msgstr ""
+
+msgctxt "view:sale.complaint:"
+msgid "Complaint"
+msgstr "reclamo"
+
+msgctxt "view:sale.complaint:"
+msgid "Process"
+msgstr "Processa"
diff --git a/modules/sale_complaint/locale/lo.po b/modules/sale_complaint/locale/lo.po
new file mode 100644
index 0000000000..dd05f97915
--- /dev/null
+++ b/modules/sale_complaint/locale/lo.po
@@ -0,0 +1,450 @@
+#
+msgid ""
+msgstr "Content-Type: text/plain; charset=utf-8\n"
+
+#, fuzzy
+msgctxt "field:sale.complaint,actions:"
+msgid "Actions"
+msgstr "ການປະຕິບັດ"
+
+#, fuzzy
+msgctxt "field:sale.complaint,address:"
+msgid "Address"
+msgstr "ທີ່ຢູ່"
+
+#, fuzzy
+msgctxt "field:sale.complaint,company:"
+msgid "Company"
+msgstr "ຫ້ອງການ/ສຳນັກງານ"
+
+msgctxt "field:sale.complaint,customer:"
+msgid "Customer"
+msgstr ""
+
+#, fuzzy
+msgctxt "field:sale.complaint,date:"
+msgid "Date"
+msgstr "ວັນທີ:"
+
+#, fuzzy
+msgctxt "field:sale.complaint,description:"
+msgid "Description"
+msgstr "ເນື້ອໃນລາຍການ"
+
+#, fuzzy
+msgctxt "field:sale.complaint,employee:"
+msgid "Employee"
+msgstr "ພະນັກງານ"
+
+#, fuzzy
+msgctxt "field:sale.complaint,number:"
+msgid "Number"
+msgstr "ເລກທີ"
+
+#, fuzzy
+msgctxt "field:sale.complaint,origin:"
+msgid "Origin"
+msgstr "ລາຍການຂັ້ນຕົ້ນ"
+
+msgctxt "field:sale.complaint,origin_id:"
+msgid "Origin ID"
+msgstr ""
+
+msgctxt "field:sale.complaint,origin_model:"
+msgid "Origin Model"
+msgstr ""
+
+#, fuzzy
+msgctxt "field:sale.complaint,reference:"
+msgid "Reference"
+msgstr "ເອກະສານອ້າງອີງ"
+
+#, fuzzy
+msgctxt "field:sale.complaint,state:"
+msgid "State"
+msgstr "ສະຖານະ"
+
+#, fuzzy
+msgctxt "field:sale.complaint,type:"
+msgid "Type"
+msgstr "ຮູບແບບ"
+
+#, fuzzy
+msgctxt "field:sale.complaint.action,action:"
+msgid "Action"
+msgstr "ການປະຕິບັດ"
+
+msgctxt "field:sale.complaint.action,amount:"
+msgid "Amount"
+msgstr ""
+
+#, fuzzy
+msgctxt "field:sale.complaint.action,complaint:"
+msgid "Complaint"
+msgstr "Complaints"
+
+#, fuzzy
+msgctxt "field:sale.complaint.action,complaint_state:"
+msgid "Complaint State"
+msgstr "Complaints"
+
+msgctxt "field:sale.complaint.action,currency:"
+msgid "Currency"
+msgstr ""
+
+#, fuzzy
+msgctxt "field:sale.complaint.action,currency_digits:"
+msgid "Currency Digits"
+msgstr "ຫົວໜ່ວຍເສດ"
+
+#, fuzzy
+msgctxt "field:sale.complaint.action,invoice_lines:"
+msgid "Invoice Lines"
+msgstr "ລາຍການເກັບເງິນ"
+
+#, fuzzy
+msgctxt "field:sale.complaint.action,quantity:"
+msgid "Quantity"
+msgstr "ຈຳນວນ"
+
+msgctxt "field:sale.complaint.action,result:"
+msgid "Result"
+msgstr ""
+
+msgctxt "field:sale.complaint.action,sale_lines:"
+msgid "Sale Lines"
+msgstr ""
+
+#, fuzzy
+msgctxt "field:sale.complaint.action,unit:"
+msgid "Unit"
+msgstr "ໜ່ວຍ"
+
+#, fuzzy
+msgctxt "field:sale.complaint.action,unit_digits:"
+msgid "Unit Digits"
+msgstr "ຫົວໜ່ວຍເສດ"
+
+#, fuzzy
+msgctxt "field:sale.complaint.action,unit_price:"
+msgid "Unit Price"
+msgstr "ລາຄາຫົວໜ່ວຍ"
+
+#, fuzzy
+msgctxt "field:sale.complaint.action-account.invoice.line,action:"
+msgid "Action"
+msgstr "ການປະຕິບັດ"
+
+msgctxt "field:sale.complaint.action-account.invoice.line,amount:"
+msgid "Amount"
+msgstr ""
+
+#, fuzzy
+msgctxt ""
+"field:sale.complaint.action-account.invoice.line,complaint_origin_id:"
+msgid "Complaint Origin ID"
+msgstr "Complaints"
+
+#, fuzzy
+msgctxt "field:sale.complaint.action-account.invoice.line,complaint_state:"
+msgid "Complaint State"
+msgstr "Complaints"
+
+msgctxt "field:sale.complaint.action-account.invoice.line,currency:"
+msgid "Currency"
+msgstr ""
+
+#, fuzzy
+msgctxt "field:sale.complaint.action-account.invoice.line,currency_digits:"
+msgid "Currency Digits"
+msgstr "ຫົວໜ່ວຍເສດ"
+
+#, fuzzy
+msgctxt "field:sale.complaint.action-account.invoice.line,line:"
+msgid "Invoice Line"
+msgstr "ລາຍການ"
+
+#, fuzzy
+msgctxt "field:sale.complaint.action-account.invoice.line,quantity:"
+msgid "Quantity"
+msgstr "ຈຳນວນ"
+
+#, fuzzy
+msgctxt "field:sale.complaint.action-account.invoice.line,unit:"
+msgid "Unit"
+msgstr "ໜ່ວຍ"
+
+#, fuzzy
+msgctxt "field:sale.complaint.action-account.invoice.line,unit_digits:"
+msgid "Unit Digits"
+msgstr "ຫົວໜ່ວຍເສດ"
+
+#, fuzzy
+msgctxt "field:sale.complaint.action-account.invoice.line,unit_price:"
+msgid "Unit Price"
+msgstr "ລາຄາຫົວໜ່ວຍ"
+
+#, fuzzy
+msgctxt "field:sale.complaint.action-sale.line,action:"
+msgid "Action"
+msgstr "ການປະຕິບັດ"
+
+msgctxt "field:sale.complaint.action-sale.line,amount:"
+msgid "Amount"
+msgstr ""
+
+#, fuzzy
+msgctxt "field:sale.complaint.action-sale.line,complaint_origin_id:"
+msgid "Complaint Origin ID"
+msgstr "Complaints"
+
+#, fuzzy
+msgctxt "field:sale.complaint.action-sale.line,complaint_state:"
+msgid "Complaint State"
+msgstr "Complaints"
+
+msgctxt "field:sale.complaint.action-sale.line,currency:"
+msgid "Currency"
+msgstr ""
+
+#, fuzzy
+msgctxt "field:sale.complaint.action-sale.line,currency_digits:"
+msgid "Currency Digits"
+msgstr "ຫົວໜ່ວຍເສດ"
+
+msgctxt "field:sale.complaint.action-sale.line,line:"
+msgid "Sale Line"
+msgstr ""
+
+#, fuzzy
+msgctxt "field:sale.complaint.action-sale.line,quantity:"
+msgid "Quantity"
+msgstr "ຈຳນວນ"
+
+#, fuzzy
+msgctxt "field:sale.complaint.action-sale.line,unit:"
+msgid "Unit"
+msgstr "ໜ່ວຍ"
+
+#, fuzzy
+msgctxt "field:sale.complaint.action-sale.line,unit_digits:"
+msgid "Unit Digits"
+msgstr "ຫົວໜ່ວຍເສດ"
+
+#, fuzzy
+msgctxt "field:sale.complaint.action-sale.line,unit_price:"
+msgid "Unit Price"
+msgstr "ລາຄາຫົວໜ່ວຍ"
+
+#, fuzzy
+msgctxt "field:sale.complaint.type,name:"
+msgid "Name"
+msgstr "ຊື່"
+
+#, fuzzy
+msgctxt "field:sale.complaint.type,origin:"
+msgid "Origin"
+msgstr "ລາຍການຂັ້ນຕົ້ນ"
+
+msgctxt "field:sale.configuration,complaint_sequence:"
+msgid "Complaint Sequence"
+msgstr ""
+
+msgctxt "field:sale.configuration.sequence,complaint_sequence:"
+msgid "Complaint Sequence"
+msgstr ""
+
+msgctxt "help:sale.complaint.action,invoice_lines:"
+msgid "Leave empty for all lines."
+msgstr ""
+
+msgctxt "help:sale.complaint.action,quantity:"
+msgid "Leave empty for the same quantity."
+msgstr ""
+
+msgctxt "help:sale.complaint.action,sale_lines:"
+msgid "Leave empty for all lines."
+msgstr ""
+
+msgctxt "help:sale.complaint.action,unit_price:"
+msgid "Leave empty for the same price."
+msgstr ""
+
+msgctxt "help:sale.complaint.action-account.invoice.line,unit_price:"
+msgid "Leave empty for the same price."
+msgstr ""
+
+msgctxt "help:sale.complaint.action-sale.line,unit_price:"
+msgid "Leave empty for the same price."
+msgstr ""
+
+msgctxt "model:ir.action,name:act_complaint_form"
+msgid "Complaints"
+msgstr "Complaints"
+
+msgctxt "model:ir.action,name:act_complaint_relate_party"
+msgid "Customer Complaints"
+msgstr "Customer Complaints"
+
+msgctxt "model:ir.action,name:act_complaint_relate_sale"
+msgid "Complaints"
+msgstr "Complaints"
+
+#, fuzzy
+msgctxt "model:ir.action,name:act_type_form"
+msgid "Types"
+msgstr "ຮູບແບບ"
+
+#, fuzzy
+msgctxt "model:ir.action.act_window.domain,name:act_complaint_form_domain_all"
+msgid "All"
+msgstr "ທັງໝົດ"
+
+#, fuzzy
+msgctxt ""
+"model:ir.action.act_window.domain,name:act_complaint_form_domain_approved"
+msgid "Approved"
+msgstr "ອະນຸມັດແລ້ວ"
+
+#, fuzzy
+msgctxt ""
+"model:ir.action.act_window.domain,name:act_complaint_form_domain_draft"
+msgid "Draft"
+msgstr "ຮ່າງກຽມ"
+
+msgctxt ""
+"model:ir.action.act_window.domain,name:act_complaint_form_domain_waiting"
+msgid "Waiting"
+msgstr "Waiting"
+
+msgctxt "model:ir.message,text:msg_action_delete_result"
+msgid "You cannot delete action \"%(action)s\" because it has a result."
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_complaint_delete_draft"
+msgid "To delete complaint \"%(complaint)s\" you must reset it to draft state."
+msgstr ""
+
+msgctxt "model:ir.model.button,string:complaint_approve_button"
+msgid "Approve"
+msgstr "Approve"
+
+msgctxt "model:ir.model.button,string:complaint_cancel_button"
+msgid "Cancel"
+msgstr "Cancel"
+
+msgctxt "model:ir.model.button,string:complaint_do_button"
+msgid "Process"
+msgstr "Process"
+
+msgctxt "model:ir.model.button,string:complaint_draft_button"
+msgid "Draft"
+msgstr "Draft"
+
+msgctxt "model:ir.model.button,string:complaint_reject_button"
+msgid "Reject"
+msgstr "Reject"
+
+msgctxt "model:ir.model.button,string:complaint_wait_button"
+msgid "Wait"
+msgstr "Wait"
+
+#, fuzzy
+msgctxt "model:ir.rule.group,name:rule_group_complaint_companies"
+msgid "User in companies"
+msgstr "Customer Complaint"
+
+msgctxt "model:ir.sequence,name:sequence_complaint"
+msgid "Customer Complaint"
+msgstr "Customer Complaint"
+
+msgctxt "model:ir.sequence.type,name:sequence_type_complaint"
+msgid "Customer Complaint"
+msgstr "Customer Complaint"
+
+msgctxt "model:ir.ui.menu,name:menu_complaint"
+msgid "Complaints"
+msgstr "Complaints"
+
+msgctxt "model:ir.ui.menu,name:menu_configuration"
+msgid "Customer Complaint"
+msgstr "Customer Complaint"
+
+#, fuzzy
+msgctxt "model:ir.ui.menu,name:menu_type"
+msgid "Types"
+msgstr "ຮູບແບບ"
+
+#, fuzzy
+msgctxt "model:sale.complaint,name:"
+msgid "Customer Complaint"
+msgstr "Customer Complaint"
+
+#, fuzzy
+msgctxt "model:sale.complaint.action,name:"
+msgid "Customer Complaint Action"
+msgstr "Customer Complaint"
+
+msgctxt "model:sale.complaint.action-account.invoice.line,name:"
+msgid "Customer Complaint Action - Invoice Line"
+msgstr ""
+
+msgctxt "model:sale.complaint.action-sale.line,name:"
+msgid "Customer Complaint Action - Sale Line"
+msgstr ""
+
+#, fuzzy
+msgctxt "model:sale.complaint.type,name:"
+msgid "Customer Complaint Type"
+msgstr "Customer Complaint"
+
+#, fuzzy
+msgctxt "selection:sale.complaint,state:"
+msgid "Approved"
+msgstr "ອະນຸມັດແລ້ວ"
+
+msgctxt "selection:sale.complaint,state:"
+msgid "Cancelled"
+msgstr ""
+
+#, fuzzy
+msgctxt "selection:sale.complaint,state:"
+msgid "Done"
+msgstr "ແລ້ວໆ"
+
+#, fuzzy
+msgctxt "selection:sale.complaint,state:"
+msgid "Draft"
+msgstr "ຮ່າງກຽມ"
+
+#, fuzzy
+msgctxt "selection:sale.complaint,state:"
+msgid "Rejected"
+msgstr "Reject"
+
+#, fuzzy
+msgctxt "selection:sale.complaint,state:"
+msgid "Waiting"
+msgstr "Waiting"
+
+msgctxt "selection:sale.complaint.action,action:"
+msgid "Create Credit Note"
+msgstr ""
+
+msgctxt "selection:sale.complaint.action,action:"
+msgid "Create Sale Return"
+msgstr ""
+
+msgctxt "view:sale.complaint.action:"
+msgid "Amount"
+msgstr ""
+
+#, fuzzy
+msgctxt "view:sale.complaint:"
+msgid "Complaint"
+msgstr "Complaints"
+
+#, fuzzy
+msgctxt "view:sale.complaint:"
+msgid "Process"
+msgstr "ປະມວນຜົນ"
diff --git a/modules/sale_complaint/locale/lt.po b/modules/sale_complaint/locale/lt.po
new file mode 100644
index 0000000000..2f7190f218
--- /dev/null
+++ b/modules/sale_complaint/locale/lt.po
@@ -0,0 +1,414 @@
+#
+msgid ""
+msgstr "Content-Type: text/plain; charset=utf-8\n"
+
+msgctxt "field:sale.complaint,actions:"
+msgid "Actions"
+msgstr ""
+
+msgctxt "field:sale.complaint,address:"
+msgid "Address"
+msgstr "Adresas"
+
+msgctxt "field:sale.complaint,company:"
+msgid "Company"
+msgstr "Organizacija"
+
+msgctxt "field:sale.complaint,customer:"
+msgid "Customer"
+msgstr ""
+
+msgctxt "field:sale.complaint,date:"
+msgid "Date"
+msgstr ""
+
+msgctxt "field:sale.complaint,description:"
+msgid "Description"
+msgstr ""
+
+msgctxt "field:sale.complaint,employee:"
+msgid "Employee"
+msgstr ""
+
+msgctxt "field:sale.complaint,number:"
+msgid "Number"
+msgstr ""
+
+msgctxt "field:sale.complaint,origin:"
+msgid "Origin"
+msgstr ""
+
+msgctxt "field:sale.complaint,origin_id:"
+msgid "Origin ID"
+msgstr ""
+
+msgctxt "field:sale.complaint,origin_model:"
+msgid "Origin Model"
+msgstr ""
+
+msgctxt "field:sale.complaint,reference:"
+msgid "Reference"
+msgstr ""
+
+msgctxt "field:sale.complaint,state:"
+msgid "State"
+msgstr ""
+
+#, fuzzy
+msgctxt "field:sale.complaint,type:"
+msgid "Type"
+msgstr "Types"
+
+msgctxt "field:sale.complaint.action,action:"
+msgid "Action"
+msgstr ""
+
+msgctxt "field:sale.complaint.action,amount:"
+msgid "Amount"
+msgstr ""
+
+#, fuzzy
+msgctxt "field:sale.complaint.action,complaint:"
+msgid "Complaint"
+msgstr "Complaints"
+
+#, fuzzy
+msgctxt "field:sale.complaint.action,complaint_state:"
+msgid "Complaint State"
+msgstr "Complaints"
+
+msgctxt "field:sale.complaint.action,currency:"
+msgid "Currency"
+msgstr ""
+
+msgctxt "field:sale.complaint.action,currency_digits:"
+msgid "Currency Digits"
+msgstr ""
+
+msgctxt "field:sale.complaint.action,invoice_lines:"
+msgid "Invoice Lines"
+msgstr "Sąskaitos faktūros eilutės"
+
+msgctxt "field:sale.complaint.action,quantity:"
+msgid "Quantity"
+msgstr ""
+
+msgctxt "field:sale.complaint.action,result:"
+msgid "Result"
+msgstr ""
+
+msgctxt "field:sale.complaint.action,sale_lines:"
+msgid "Sale Lines"
+msgstr ""
+
+msgctxt "field:sale.complaint.action,unit:"
+msgid "Unit"
+msgstr ""
+
+msgctxt "field:sale.complaint.action,unit_digits:"
+msgid "Unit Digits"
+msgstr ""
+
+msgctxt "field:sale.complaint.action,unit_price:"
+msgid "Unit Price"
+msgstr ""
+
+msgctxt "field:sale.complaint.action-account.invoice.line,action:"
+msgid "Action"
+msgstr ""
+
+msgctxt "field:sale.complaint.action-account.invoice.line,amount:"
+msgid "Amount"
+msgstr ""
+
+#, fuzzy
+msgctxt ""
+"field:sale.complaint.action-account.invoice.line,complaint_origin_id:"
+msgid "Complaint Origin ID"
+msgstr "Complaints"
+
+#, fuzzy
+msgctxt "field:sale.complaint.action-account.invoice.line,complaint_state:"
+msgid "Complaint State"
+msgstr "Complaints"
+
+msgctxt "field:sale.complaint.action-account.invoice.line,currency:"
+msgid "Currency"
+msgstr ""
+
+msgctxt "field:sale.complaint.action-account.invoice.line,currency_digits:"
+msgid "Currency Digits"
+msgstr ""
+
+msgctxt "field:sale.complaint.action-account.invoice.line,line:"
+msgid "Invoice Line"
+msgstr "Sąskaitos faktūros eilutė"
+
+msgctxt "field:sale.complaint.action-account.invoice.line,quantity:"
+msgid "Quantity"
+msgstr ""
+
+msgctxt "field:sale.complaint.action-account.invoice.line,unit:"
+msgid "Unit"
+msgstr ""
+
+msgctxt "field:sale.complaint.action-account.invoice.line,unit_digits:"
+msgid "Unit Digits"
+msgstr ""
+
+msgctxt "field:sale.complaint.action-account.invoice.line,unit_price:"
+msgid "Unit Price"
+msgstr ""
+
+msgctxt "field:sale.complaint.action-sale.line,action:"
+msgid "Action"
+msgstr ""
+
+msgctxt "field:sale.complaint.action-sale.line,amount:"
+msgid "Amount"
+msgstr ""
+
+#, fuzzy
+msgctxt "field:sale.complaint.action-sale.line,complaint_origin_id:"
+msgid "Complaint Origin ID"
+msgstr "Complaints"
+
+#, fuzzy
+msgctxt "field:sale.complaint.action-sale.line,complaint_state:"
+msgid "Complaint State"
+msgstr "Complaints"
+
+msgctxt "field:sale.complaint.action-sale.line,currency:"
+msgid "Currency"
+msgstr ""
+
+msgctxt "field:sale.complaint.action-sale.line,currency_digits:"
+msgid "Currency Digits"
+msgstr ""
+
+msgctxt "field:sale.complaint.action-sale.line,line:"
+msgid "Sale Line"
+msgstr ""
+
+msgctxt "field:sale.complaint.action-sale.line,quantity:"
+msgid "Quantity"
+msgstr ""
+
+msgctxt "field:sale.complaint.action-sale.line,unit:"
+msgid "Unit"
+msgstr ""
+
+msgctxt "field:sale.complaint.action-sale.line,unit_digits:"
+msgid "Unit Digits"
+msgstr ""
+
+msgctxt "field:sale.complaint.action-sale.line,unit_price:"
+msgid "Unit Price"
+msgstr ""
+
+#, fuzzy
+msgctxt "field:sale.complaint.type,name:"
+msgid "Name"
+msgstr "Namu"
+
+msgctxt "field:sale.complaint.type,origin:"
+msgid "Origin"
+msgstr ""
+
+msgctxt "field:sale.configuration,complaint_sequence:"
+msgid "Complaint Sequence"
+msgstr ""
+
+msgctxt "field:sale.configuration.sequence,complaint_sequence:"
+msgid "Complaint Sequence"
+msgstr ""
+
+msgctxt "help:sale.complaint.action,invoice_lines:"
+msgid "Leave empty for all lines."
+msgstr ""
+
+msgctxt "help:sale.complaint.action,quantity:"
+msgid "Leave empty for the same quantity."
+msgstr ""
+
+msgctxt "help:sale.complaint.action,sale_lines:"
+msgid "Leave empty for all lines."
+msgstr ""
+
+msgctxt "help:sale.complaint.action,unit_price:"
+msgid "Leave empty for the same price."
+msgstr ""
+
+msgctxt "help:sale.complaint.action-account.invoice.line,unit_price:"
+msgid "Leave empty for the same price."
+msgstr ""
+
+msgctxt "help:sale.complaint.action-sale.line,unit_price:"
+msgid "Leave empty for the same price."
+msgstr ""
+
+msgctxt "model:ir.action,name:act_complaint_form"
+msgid "Complaints"
+msgstr "Complaints"
+
+msgctxt "model:ir.action,name:act_complaint_relate_party"
+msgid "Customer Complaints"
+msgstr "Customer Complaints"
+
+msgctxt "model:ir.action,name:act_complaint_relate_sale"
+msgid "Complaints"
+msgstr "Complaints"
+
+msgctxt "model:ir.action,name:act_type_form"
+msgid "Types"
+msgstr "Types"
+
+msgctxt "model:ir.action.act_window.domain,name:act_complaint_form_domain_all"
+msgid "All"
+msgstr "All"
+
+#, fuzzy
+msgctxt ""
+"model:ir.action.act_window.domain,name:act_complaint_form_domain_approved"
+msgid "Approved"
+msgstr "Approved"
+
+msgctxt ""
+"model:ir.action.act_window.domain,name:act_complaint_form_domain_draft"
+msgid "Draft"
+msgstr "Draft"
+
+msgctxt ""
+"model:ir.action.act_window.domain,name:act_complaint_form_domain_waiting"
+msgid "Waiting"
+msgstr "Waiting"
+
+msgctxt "model:ir.message,text:msg_action_delete_result"
+msgid "You cannot delete action \"%(action)s\" because it has a result."
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_complaint_delete_draft"
+msgid "To delete complaint \"%(complaint)s\" you must reset it to draft state."
+msgstr ""
+
+msgctxt "model:ir.model.button,string:complaint_approve_button"
+msgid "Approve"
+msgstr "Approve"
+
+msgctxt "model:ir.model.button,string:complaint_cancel_button"
+msgid "Cancel"
+msgstr "Cancel"
+
+msgctxt "model:ir.model.button,string:complaint_do_button"
+msgid "Process"
+msgstr "Process"
+
+msgctxt "model:ir.model.button,string:complaint_draft_button"
+msgid "Draft"
+msgstr "Draft"
+
+msgctxt "model:ir.model.button,string:complaint_reject_button"
+msgid "Reject"
+msgstr "Reject"
+
+msgctxt "model:ir.model.button,string:complaint_wait_button"
+msgid "Wait"
+msgstr "Wait"
+
+#, fuzzy
+msgctxt "model:ir.rule.group,name:rule_group_complaint_companies"
+msgid "User in companies"
+msgstr "Customer Complaint"
+
+msgctxt "model:ir.sequence,name:sequence_complaint"
+msgid "Customer Complaint"
+msgstr "Customer Complaint"
+
+msgctxt "model:ir.sequence.type,name:sequence_type_complaint"
+msgid "Customer Complaint"
+msgstr "Customer Complaint"
+
+msgctxt "model:ir.ui.menu,name:menu_complaint"
+msgid "Complaints"
+msgstr "Complaints"
+
+msgctxt "model:ir.ui.menu,name:menu_configuration"
+msgid "Customer Complaint"
+msgstr "Customer Complaint"
+
+msgctxt "model:ir.ui.menu,name:menu_type"
+msgid "Types"
+msgstr "Types"
+
+#, fuzzy
+msgctxt "model:sale.complaint,name:"
+msgid "Customer Complaint"
+msgstr "Customer Complaint"
+
+#, fuzzy
+msgctxt "model:sale.complaint.action,name:"
+msgid "Customer Complaint Action"
+msgstr "Customer Complaint"
+
+msgctxt "model:sale.complaint.action-account.invoice.line,name:"
+msgid "Customer Complaint Action - Invoice Line"
+msgstr ""
+
+msgctxt "model:sale.complaint.action-sale.line,name:"
+msgid "Customer Complaint Action - Sale Line"
+msgstr ""
+
+#, fuzzy
+msgctxt "model:sale.complaint.type,name:"
+msgid "Customer Complaint Type"
+msgstr "Customer Complaint"
+
+#, fuzzy
+msgctxt "selection:sale.complaint,state:"
+msgid "Approved"
+msgstr "Approve"
+
+msgctxt "selection:sale.complaint,state:"
+msgid "Cancelled"
+msgstr ""
+
+msgctxt "selection:sale.complaint,state:"
+msgid "Done"
+msgstr ""
+
+#, fuzzy
+msgctxt "selection:sale.complaint,state:"
+msgid "Draft"
+msgstr "Draft"
+
+#, fuzzy
+msgctxt "selection:sale.complaint,state:"
+msgid "Rejected"
+msgstr "Reject"
+
+#, fuzzy
+msgctxt "selection:sale.complaint,state:"
+msgid "Waiting"
+msgstr "Waiting"
+
+msgctxt "selection:sale.complaint.action,action:"
+msgid "Create Credit Note"
+msgstr ""
+
+msgctxt "selection:sale.complaint.action,action:"
+msgid "Create Sale Return"
+msgstr ""
+
+msgctxt "view:sale.complaint.action:"
+msgid "Amount"
+msgstr ""
+
+#, fuzzy
+msgctxt "view:sale.complaint:"
+msgid "Complaint"
+msgstr "Complaints"
+
+#, fuzzy
+msgctxt "view:sale.complaint:"
+msgid "Process"
+msgstr "Process"
diff --git a/modules/sale_complaint/locale/nl.po b/modules/sale_complaint/locale/nl.po
new file mode 100644
index 0000000000..a9241c44e1
--- /dev/null
+++ b/modules/sale_complaint/locale/nl.po
@@ -0,0 +1,399 @@
+#
+msgid ""
+msgstr "Content-Type: text/plain; charset=utf-8\n"
+
+msgctxt "field:sale.complaint,actions:"
+msgid "Actions"
+msgstr "Acties"
+
+msgctxt "field:sale.complaint,address:"
+msgid "Address"
+msgstr "Adres"
+
+msgctxt "field:sale.complaint,company:"
+msgid "Company"
+msgstr "Bedrijf"
+
+msgctxt "field:sale.complaint,customer:"
+msgid "Customer"
+msgstr "Klant"
+
+msgctxt "field:sale.complaint,date:"
+msgid "Date"
+msgstr "datum"
+
+msgctxt "field:sale.complaint,description:"
+msgid "Description"
+msgstr "Omschrijving"
+
+msgctxt "field:sale.complaint,employee:"
+msgid "Employee"
+msgstr "Werknemer"
+
+msgctxt "field:sale.complaint,number:"
+msgid "Number"
+msgstr "Nummer"
+
+msgctxt "field:sale.complaint,origin:"
+msgid "Origin"
+msgstr "Oorsprong"
+
+msgctxt "field:sale.complaint,origin_id:"
+msgid "Origin ID"
+msgstr "oorsprong id"
+
+msgctxt "field:sale.complaint,origin_model:"
+msgid "Origin Model"
+msgstr "Oorsprong Model"
+
+msgctxt "field:sale.complaint,reference:"
+msgid "Reference"
+msgstr "Referentie"
+
+msgctxt "field:sale.complaint,state:"
+msgid "State"
+msgstr "Status"
+
+msgctxt "field:sale.complaint,type:"
+msgid "Type"
+msgstr "Type"
+
+msgctxt "field:sale.complaint.action,action:"
+msgid "Action"
+msgstr "Actie"
+
+msgctxt "field:sale.complaint.action,amount:"
+msgid "Amount"
+msgstr "Bedrag"
+
+msgctxt "field:sale.complaint.action,complaint:"
+msgid "Complaint"
+msgstr "klachten"
+
+msgctxt "field:sale.complaint.action,complaint_state:"
+msgid "Complaint State"
+msgstr "Klacht status"
+
+msgctxt "field:sale.complaint.action,currency:"
+msgid "Currency"
+msgstr "Valuta"
+
+msgctxt "field:sale.complaint.action,currency_digits:"
+msgid "Currency Digits"
+msgstr "Valuta decimalen"
+
+msgctxt "field:sale.complaint.action,invoice_lines:"
+msgid "Invoice Lines"
+msgstr "Factuurregels"
+
+msgctxt "field:sale.complaint.action,quantity:"
+msgid "Quantity"
+msgstr "Hoeveelheid"
+
+msgctxt "field:sale.complaint.action,result:"
+msgid "Result"
+msgstr "Resultaat"
+
+msgctxt "field:sale.complaint.action,sale_lines:"
+msgid "Sale Lines"
+msgstr "Verkooplijnen"
+
+msgctxt "field:sale.complaint.action,unit:"
+msgid "Unit"
+msgstr "Eenheid"
+
+msgctxt "field:sale.complaint.action,unit_digits:"
+msgid "Unit Digits"
+msgstr "Decimalen eenheid"
+
+msgctxt "field:sale.complaint.action,unit_price:"
+msgid "Unit Price"
+msgstr "Eenheidsprijs"
+
+msgctxt "field:sale.complaint.action-account.invoice.line,action:"
+msgid "Action"
+msgstr "Actie"
+
+msgctxt "field:sale.complaint.action-account.invoice.line,amount:"
+msgid "Amount"
+msgstr "Bedrag"
+
+msgctxt ""
+"field:sale.complaint.action-account.invoice.line,complaint_origin_id:"
+msgid "Complaint Origin ID"
+msgstr "Klacht oorsprong ID"
+
+msgctxt "field:sale.complaint.action-account.invoice.line,complaint_state:"
+msgid "Complaint State"
+msgstr "Klacht status"
+
+msgctxt "field:sale.complaint.action-account.invoice.line,currency:"
+msgid "Currency"
+msgstr "Valuta"
+
+msgctxt "field:sale.complaint.action-account.invoice.line,currency_digits:"
+msgid "Currency Digits"
+msgstr "Valuta decimalen"
+
+msgctxt "field:sale.complaint.action-account.invoice.line,line:"
+msgid "Invoice Line"
+msgstr "Factuurregel"
+
+msgctxt "field:sale.complaint.action-account.invoice.line,quantity:"
+msgid "Quantity"
+msgstr "Hoeveelheid"
+
+msgctxt "field:sale.complaint.action-account.invoice.line,unit:"
+msgid "Unit"
+msgstr "Eenheid"
+
+msgctxt "field:sale.complaint.action-account.invoice.line,unit_digits:"
+msgid "Unit Digits"
+msgstr "Decimalen eenheid"
+
+msgctxt "field:sale.complaint.action-account.invoice.line,unit_price:"
+msgid "Unit Price"
+msgstr "Eenheidsprijs"
+
+msgctxt "field:sale.complaint.action-sale.line,action:"
+msgid "Action"
+msgstr "Actie"
+
+msgctxt "field:sale.complaint.action-sale.line,amount:"
+msgid "Amount"
+msgstr "Bedrag"
+
+msgctxt "field:sale.complaint.action-sale.line,complaint_origin_id:"
+msgid "Complaint Origin ID"
+msgstr "Klacht oorsprong ID"
+
+msgctxt "field:sale.complaint.action-sale.line,complaint_state:"
+msgid "Complaint State"
+msgstr "Klacht status"
+
+msgctxt "field:sale.complaint.action-sale.line,currency:"
+msgid "Currency"
+msgstr "Valuta"
+
+msgctxt "field:sale.complaint.action-sale.line,currency_digits:"
+msgid "Currency Digits"
+msgstr "Valuta decimalen"
+
+msgctxt "field:sale.complaint.action-sale.line,line:"
+msgid "Sale Line"
+msgstr "Verkooplijn"
+
+msgctxt "field:sale.complaint.action-sale.line,quantity:"
+msgid "Quantity"
+msgstr "Hoeveelheid"
+
+msgctxt "field:sale.complaint.action-sale.line,unit:"
+msgid "Unit"
+msgstr "Eenheid"
+
+msgctxt "field:sale.complaint.action-sale.line,unit_digits:"
+msgid "Unit Digits"
+msgstr "Decimalen eenheid"
+
+msgctxt "field:sale.complaint.action-sale.line,unit_price:"
+msgid "Unit Price"
+msgstr "Eenheidsprijs"
+
+msgctxt "field:sale.complaint.type,name:"
+msgid "Name"
+msgstr "Naam"
+
+msgctxt "field:sale.complaint.type,origin:"
+msgid "Origin"
+msgstr "Oorsprong"
+
+msgctxt "field:sale.configuration,complaint_sequence:"
+msgid "Complaint Sequence"
+msgstr "Klachtenreeks"
+
+msgctxt "field:sale.configuration.sequence,complaint_sequence:"
+msgid "Complaint Sequence"
+msgstr "Klachtenreeks"
+
+msgctxt "help:sale.complaint.action,invoice_lines:"
+msgid "Leave empty for all lines."
+msgstr "Laat leeg voor alle regels."
+
+msgctxt "help:sale.complaint.action,quantity:"
+msgid "Leave empty for the same quantity."
+msgstr "Laat leeg voor dezelfde hoeveelheid."
+
+msgctxt "help:sale.complaint.action,sale_lines:"
+msgid "Leave empty for all lines."
+msgstr "Laat leeg voor alle regels."
+
+msgctxt "help:sale.complaint.action,unit_price:"
+msgid "Leave empty for the same price."
+msgstr "Laat leeg voor dezelfde prijs."
+
+msgctxt "help:sale.complaint.action-account.invoice.line,unit_price:"
+msgid "Leave empty for the same price."
+msgstr "Laat leeg voor dezelfde prijs."
+
+msgctxt "help:sale.complaint.action-sale.line,unit_price:"
+msgid "Leave empty for the same price."
+msgstr "Laat leeg voor dezelfde prijs."
+
+msgctxt "model:ir.action,name:act_complaint_form"
+msgid "Complaints"
+msgstr "klachten"
+
+msgctxt "model:ir.action,name:act_complaint_relate_party"
+msgid "Customer Complaints"
+msgstr "Klachten van klanten"
+
+msgctxt "model:ir.action,name:act_complaint_relate_sale"
+msgid "Complaints"
+msgstr "klachten"
+
+msgctxt "model:ir.action,name:act_type_form"
+msgid "Types"
+msgstr "Type"
+
+msgctxt "model:ir.action.act_window.domain,name:act_complaint_form_domain_all"
+msgid "All"
+msgstr "Alle"
+
+msgctxt ""
+"model:ir.action.act_window.domain,name:act_complaint_form_domain_approved"
+msgid "Approved"
+msgstr "Goedgekeurd"
+
+msgctxt ""
+"model:ir.action.act_window.domain,name:act_complaint_form_domain_draft"
+msgid "Draft"
+msgstr "Concept"
+
+msgctxt ""
+"model:ir.action.act_window.domain,name:act_complaint_form_domain_waiting"
+msgid "Waiting"
+msgstr "In afwachting"
+
+msgctxt "model:ir.message,text:msg_action_delete_result"
+msgid "You cannot delete action \"%(action)s\" because it has a result."
+msgstr ""
+"U kunt actie \"%(action)s\" niet verwijderen omdat deze een resultaat heeft."
+
+msgctxt "model:ir.message,text:msg_complaint_delete_draft"
+msgid "To delete complaint \"%(complaint)s\" you must reset it to draft state."
+msgstr ""
+"Om de klacht \"% (klacht) s\" te verwijderen, moet u deze tergugzetten naar "
+"conceptstatus."
+
+msgctxt "model:ir.model.button,string:complaint_approve_button"
+msgid "Approve"
+msgstr "Goedkeuren"
+
+msgctxt "model:ir.model.button,string:complaint_cancel_button"
+msgid "Cancel"
+msgstr "Annuleer"
+
+msgctxt "model:ir.model.button,string:complaint_do_button"
+msgid "Process"
+msgstr "Process"
+
+msgctxt "model:ir.model.button,string:complaint_draft_button"
+msgid "Draft"
+msgstr "Concept"
+
+msgctxt "model:ir.model.button,string:complaint_reject_button"
+msgid "Reject"
+msgstr "afwijzen"
+
+msgctxt "model:ir.model.button,string:complaint_wait_button"
+msgid "Wait"
+msgstr "wachten"
+
+#, fuzzy
+msgctxt "model:ir.rule.group,name:rule_group_complaint_companies"
+msgid "User in companies"
+msgstr "Gebruiker in het bedrijf"
+
+msgctxt "model:ir.sequence,name:sequence_complaint"
+msgid "Customer Complaint"
+msgstr "Klacht van de klant"
+
+msgctxt "model:ir.sequence.type,name:sequence_type_complaint"
+msgid "Customer Complaint"
+msgstr "Klacht van de klant"
+
+msgctxt "model:ir.ui.menu,name:menu_complaint"
+msgid "Complaints"
+msgstr "klachten"
+
+msgctxt "model:ir.ui.menu,name:menu_configuration"
+msgid "Customer Complaint"
+msgstr "Klacht van de klant"
+
+msgctxt "model:ir.ui.menu,name:menu_type"
+msgid "Types"
+msgstr "Type"
+
+msgctxt "model:sale.complaint,name:"
+msgid "Customer Complaint"
+msgstr "Klacht van de klant"
+
+msgctxt "model:sale.complaint.action,name:"
+msgid "Customer Complaint Action"
+msgstr "Klacht van klant actie"
+
+msgctxt "model:sale.complaint.action-account.invoice.line,name:"
+msgid "Customer Complaint Action - Invoice Line"
+msgstr "klachten klant actie - factuurregel"
+
+msgctxt "model:sale.complaint.action-sale.line,name:"
+msgid "Customer Complaint Action - Sale Line"
+msgstr "klachten klant actie - verkoopregel"
+
+msgctxt "model:sale.complaint.type,name:"
+msgid "Customer Complaint Type"
+msgstr "klacht van klant Type"
+
+msgctxt "selection:sale.complaint,state:"
+msgid "Approved"
+msgstr "Goedgekeurd"
+
+msgctxt "selection:sale.complaint,state:"
+msgid "Cancelled"
+msgstr "Geannuleerd"
+
+msgctxt "selection:sale.complaint,state:"
+msgid "Done"
+msgstr "Klaar"
+
+msgctxt "selection:sale.complaint,state:"
+msgid "Draft"
+msgstr "Concept"
+
+msgctxt "selection:sale.complaint,state:"
+msgid "Rejected"
+msgstr "Verworpen"
+
+msgctxt "selection:sale.complaint,state:"
+msgid "Waiting"
+msgstr "In afwachting"
+
+msgctxt "selection:sale.complaint.action,action:"
+msgid "Create Credit Note"
+msgstr "Creditnota maken"
+
+msgctxt "selection:sale.complaint.action,action:"
+msgid "Create Sale Return"
+msgstr "maak retour aan"
+
+msgctxt "view:sale.complaint.action:"
+msgid "Amount"
+msgstr "Bedrag"
+
+msgctxt "view:sale.complaint:"
+msgid "Complaint"
+msgstr "klacht"
+
+msgctxt "view:sale.complaint:"
+msgid "Process"
+msgstr "Proces"
diff --git a/modules/sale_complaint/locale/pl.po b/modules/sale_complaint/locale/pl.po
new file mode 100644
index 0000000000..e9b7ac5d7c
--- /dev/null
+++ b/modules/sale_complaint/locale/pl.po
@@ -0,0 +1,433 @@
+#
+msgid ""
+msgstr "Content-Type: text/plain; charset=utf-8\n"
+
+msgctxt "field:sale.complaint,actions:"
+msgid "Actions"
+msgstr "Akcje"
+
+msgctxt "field:sale.complaint,address:"
+msgid "Address"
+msgstr "Adres"
+
+msgctxt "field:sale.complaint,company:"
+msgid "Company"
+msgstr "Firma"
+
+msgctxt "field:sale.complaint,customer:"
+msgid "Customer"
+msgstr "Klient"
+
+msgctxt "field:sale.complaint,date:"
+msgid "Date"
+msgstr "Data"
+
+msgctxt "field:sale.complaint,description:"
+msgid "Description"
+msgstr "Opis"
+
+msgctxt "field:sale.complaint,employee:"
+msgid "Employee"
+msgstr "Pracownik"
+
+msgctxt "field:sale.complaint,number:"
+msgid "Number"
+msgstr "Numer"
+
+msgctxt "field:sale.complaint,origin:"
+msgid "Origin"
+msgstr ""
+
+msgctxt "field:sale.complaint,origin_id:"
+msgid "Origin ID"
+msgstr ""
+
+msgctxt "field:sale.complaint,origin_model:"
+msgid "Origin Model"
+msgstr ""
+
+msgctxt "field:sale.complaint,reference:"
+msgid "Reference"
+msgstr "Referencja"
+
+msgctxt "field:sale.complaint,state:"
+msgid "State"
+msgstr "Stan"
+
+msgctxt "field:sale.complaint,type:"
+msgid "Type"
+msgstr "Typ"
+
+msgctxt "field:sale.complaint.action,action:"
+msgid "Action"
+msgstr "Akcja"
+
+msgctxt "field:sale.complaint.action,amount:"
+msgid "Amount"
+msgstr ""
+
+#, fuzzy
+msgctxt "field:sale.complaint.action,complaint:"
+msgid "Complaint"
+msgstr "Complaints"
+
+#, fuzzy
+msgctxt "field:sale.complaint.action,complaint_state:"
+msgid "Complaint State"
+msgstr "Complaints"
+
+msgctxt "field:sale.complaint.action,currency:"
+msgid "Currency"
+msgstr ""
+
+#, fuzzy
+msgctxt "field:sale.complaint.action,currency_digits:"
+msgid "Currency Digits"
+msgstr "Cyfry jednostki"
+
+msgctxt "field:sale.complaint.action,invoice_lines:"
+msgid "Invoice Lines"
+msgstr "Wiersze faktury"
+
+msgctxt "field:sale.complaint.action,quantity:"
+msgid "Quantity"
+msgstr "Ilość"
+
+msgctxt "field:sale.complaint.action,result:"
+msgid "Result"
+msgstr "Wynik"
+
+msgctxt "field:sale.complaint.action,sale_lines:"
+msgid "Sale Lines"
+msgstr "Wiersze sprzedaży"
+
+msgctxt "field:sale.complaint.action,unit:"
+msgid "Unit"
+msgstr "Jednostka"
+
+msgctxt "field:sale.complaint.action,unit_digits:"
+msgid "Unit Digits"
+msgstr "Cyfry jednostki"
+
+msgctxt "field:sale.complaint.action,unit_price:"
+msgid "Unit Price"
+msgstr "Cena jednostkowa"
+
+msgctxt "field:sale.complaint.action-account.invoice.line,action:"
+msgid "Action"
+msgstr "Akcja"
+
+msgctxt "field:sale.complaint.action-account.invoice.line,amount:"
+msgid "Amount"
+msgstr ""
+
+#, fuzzy
+msgctxt ""
+"field:sale.complaint.action-account.invoice.line,complaint_origin_id:"
+msgid "Complaint Origin ID"
+msgstr "Complaints"
+
+#, fuzzy
+msgctxt "field:sale.complaint.action-account.invoice.line,complaint_state:"
+msgid "Complaint State"
+msgstr "Complaints"
+
+msgctxt "field:sale.complaint.action-account.invoice.line,currency:"
+msgid "Currency"
+msgstr ""
+
+#, fuzzy
+msgctxt "field:sale.complaint.action-account.invoice.line,currency_digits:"
+msgid "Currency Digits"
+msgstr "Cyfry jednostki"
+
+msgctxt "field:sale.complaint.action-account.invoice.line,line:"
+msgid "Invoice Line"
+msgstr "Wiersz faktury"
+
+#, fuzzy
+msgctxt "field:sale.complaint.action-account.invoice.line,quantity:"
+msgid "Quantity"
+msgstr "Ilość"
+
+#, fuzzy
+msgctxt "field:sale.complaint.action-account.invoice.line,unit:"
+msgid "Unit"
+msgstr "Jednostka"
+
+#, fuzzy
+msgctxt "field:sale.complaint.action-account.invoice.line,unit_digits:"
+msgid "Unit Digits"
+msgstr "Cyfry jednostki"
+
+#, fuzzy
+msgctxt "field:sale.complaint.action-account.invoice.line,unit_price:"
+msgid "Unit Price"
+msgstr "Cena jednostkowa"
+
+msgctxt "field:sale.complaint.action-sale.line,action:"
+msgid "Action"
+msgstr "Akcja"
+
+msgctxt "field:sale.complaint.action-sale.line,amount:"
+msgid "Amount"
+msgstr ""
+
+#, fuzzy
+msgctxt "field:sale.complaint.action-sale.line,complaint_origin_id:"
+msgid "Complaint Origin ID"
+msgstr "Complaints"
+
+#, fuzzy
+msgctxt "field:sale.complaint.action-sale.line,complaint_state:"
+msgid "Complaint State"
+msgstr "Complaints"
+
+msgctxt "field:sale.complaint.action-sale.line,currency:"
+msgid "Currency"
+msgstr ""
+
+#, fuzzy
+msgctxt "field:sale.complaint.action-sale.line,currency_digits:"
+msgid "Currency Digits"
+msgstr "Cyfry jednostki"
+
+msgctxt "field:sale.complaint.action-sale.line,line:"
+msgid "Sale Line"
+msgstr "Wiersz sprzedaży"
+
+#, fuzzy
+msgctxt "field:sale.complaint.action-sale.line,quantity:"
+msgid "Quantity"
+msgstr "Ilość"
+
+#, fuzzy
+msgctxt "field:sale.complaint.action-sale.line,unit:"
+msgid "Unit"
+msgstr "Jednostka"
+
+#, fuzzy
+msgctxt "field:sale.complaint.action-sale.line,unit_digits:"
+msgid "Unit Digits"
+msgstr "Cyfry jednostki"
+
+#, fuzzy
+msgctxt "field:sale.complaint.action-sale.line,unit_price:"
+msgid "Unit Price"
+msgstr "Cena jednostkowa"
+
+msgctxt "field:sale.complaint.type,name:"
+msgid "Name"
+msgstr "Nazwa"
+
+msgctxt "field:sale.complaint.type,origin:"
+msgid "Origin"
+msgstr ""
+
+msgctxt "field:sale.configuration,complaint_sequence:"
+msgid "Complaint Sequence"
+msgstr ""
+
+msgctxt "field:sale.configuration.sequence,complaint_sequence:"
+msgid "Complaint Sequence"
+msgstr ""
+
+msgctxt "help:sale.complaint.action,invoice_lines:"
+msgid "Leave empty for all lines."
+msgstr ""
+
+msgctxt "help:sale.complaint.action,quantity:"
+msgid "Leave empty for the same quantity."
+msgstr ""
+
+msgctxt "help:sale.complaint.action,sale_lines:"
+msgid "Leave empty for all lines."
+msgstr ""
+
+msgctxt "help:sale.complaint.action,unit_price:"
+msgid "Leave empty for the same price."
+msgstr ""
+
+msgctxt "help:sale.complaint.action-account.invoice.line,unit_price:"
+msgid "Leave empty for the same price."
+msgstr ""
+
+msgctxt "help:sale.complaint.action-sale.line,unit_price:"
+msgid "Leave empty for the same price."
+msgstr ""
+
+#, fuzzy
+msgctxt "model:ir.action,name:act_complaint_form"
+msgid "Complaints"
+msgstr "Complaints"
+
+#, fuzzy
+msgctxt "model:ir.action,name:act_complaint_relate_party"
+msgid "Customer Complaints"
+msgstr "Customer Complaint"
+
+#, fuzzy
+msgctxt "model:ir.action,name:act_complaint_relate_sale"
+msgid "Complaints"
+msgstr "Complaints"
+
+#, fuzzy
+msgctxt "model:ir.action,name:act_type_form"
+msgid "Types"
+msgstr "Types"
+
+#, fuzzy
+msgctxt "model:ir.action.act_window.domain,name:act_complaint_form_domain_all"
+msgid "All"
+msgstr "All"
+
+#, fuzzy
+msgctxt ""
+"model:ir.action.act_window.domain,name:act_complaint_form_domain_approved"
+msgid "Approved"
+msgstr "Approved"
+
+#, fuzzy
+msgctxt ""
+"model:ir.action.act_window.domain,name:act_complaint_form_domain_draft"
+msgid "Draft"
+msgstr "Draft"
+
+#, fuzzy
+msgctxt ""
+"model:ir.action.act_window.domain,name:act_complaint_form_domain_waiting"
+msgid "Waiting"
+msgstr "Waiting"
+
+msgctxt "model:ir.message,text:msg_action_delete_result"
+msgid "You cannot delete action \"%(action)s\" because it has a result."
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_complaint_delete_draft"
+msgid "To delete complaint \"%(complaint)s\" you must reset it to draft state."
+msgstr ""
+
+msgctxt "model:ir.model.button,string:complaint_approve_button"
+msgid "Approve"
+msgstr "Approve"
+
+msgctxt "model:ir.model.button,string:complaint_cancel_button"
+msgid "Cancel"
+msgstr "Cancel"
+
+msgctxt "model:ir.model.button,string:complaint_do_button"
+msgid "Process"
+msgstr "Process"
+
+msgctxt "model:ir.model.button,string:complaint_draft_button"
+msgid "Draft"
+msgstr "Draft"
+
+msgctxt "model:ir.model.button,string:complaint_reject_button"
+msgid "Reject"
+msgstr "Reject"
+
+msgctxt "model:ir.model.button,string:complaint_wait_button"
+msgid "Wait"
+msgstr "Wait"
+
+#, fuzzy
+msgctxt "model:ir.rule.group,name:rule_group_complaint_companies"
+msgid "User in companies"
+msgstr "Customer Complaint"
+
+#, fuzzy
+msgctxt "model:ir.sequence,name:sequence_complaint"
+msgid "Customer Complaint"
+msgstr "Customer Complaint"
+
+#, fuzzy
+msgctxt "model:ir.sequence.type,name:sequence_type_complaint"
+msgid "Customer Complaint"
+msgstr "Customer Complaint"
+
+#, fuzzy
+msgctxt "model:ir.ui.menu,name:menu_complaint"
+msgid "Complaints"
+msgstr "Complaints"
+
+#, fuzzy
+msgctxt "model:ir.ui.menu,name:menu_configuration"
+msgid "Customer Complaint"
+msgstr "Customer Complaint"
+
+#, fuzzy
+msgctxt "model:ir.ui.menu,name:menu_type"
+msgid "Types"
+msgstr "Types"
+
+#, fuzzy
+msgctxt "model:sale.complaint,name:"
+msgid "Customer Complaint"
+msgstr "Customer Complaint"
+
+#, fuzzy
+msgctxt "model:sale.complaint.action,name:"
+msgid "Customer Complaint Action"
+msgstr "Customer Complaint"
+
+msgctxt "model:sale.complaint.action-account.invoice.line,name:"
+msgid "Customer Complaint Action - Invoice Line"
+msgstr ""
+
+msgctxt "model:sale.complaint.action-sale.line,name:"
+msgid "Customer Complaint Action - Sale Line"
+msgstr ""
+
+#, fuzzy
+msgctxt "model:sale.complaint.type,name:"
+msgid "Customer Complaint Type"
+msgstr "Customer Complaint"
+
+msgctxt "selection:sale.complaint,state:"
+msgid "Approved"
+msgstr "Zatwierdzono"
+
+msgctxt "selection:sale.complaint,state:"
+msgid "Cancelled"
+msgstr "Anulowano"
+
+msgctxt "selection:sale.complaint,state:"
+msgid "Done"
+msgstr "Wykonano"
+
+#, fuzzy
+msgctxt "selection:sale.complaint,state:"
+msgid "Draft"
+msgstr "Draft"
+
+msgctxt "selection:sale.complaint,state:"
+msgid "Rejected"
+msgstr "Odrzucono"
+
+#, fuzzy
+msgctxt "selection:sale.complaint,state:"
+msgid "Waiting"
+msgstr "Waiting"
+
+msgctxt "selection:sale.complaint.action,action:"
+msgid "Create Credit Note"
+msgstr ""
+
+msgctxt "selection:sale.complaint.action,action:"
+msgid "Create Sale Return"
+msgstr ""
+
+msgctxt "view:sale.complaint.action:"
+msgid "Amount"
+msgstr ""
+
+#, fuzzy
+msgctxt "view:sale.complaint:"
+msgid "Complaint"
+msgstr "Complaints"
+
+#, fuzzy
+msgctxt "view:sale.complaint:"
+msgid "Process"
+msgstr "Process"
diff --git a/modules/sale_complaint/locale/pt.po b/modules/sale_complaint/locale/pt.po
new file mode 100644
index 0000000000..95544de91b
--- /dev/null
+++ b/modules/sale_complaint/locale/pt.po
@@ -0,0 +1,431 @@
+#
+msgid ""
+msgstr "Content-Type: text/plain; charset=utf-8\n"
+
+msgctxt "field:sale.complaint,actions:"
+msgid "Actions"
+msgstr "Ações"
+
+msgctxt "field:sale.complaint,address:"
+msgid "Address"
+msgstr "Endereço"
+
+msgctxt "field:sale.complaint,company:"
+msgid "Company"
+msgstr "Empresa"
+
+msgctxt "field:sale.complaint,customer:"
+msgid "Customer"
+msgstr "Cliente"
+
+msgctxt "field:sale.complaint,date:"
+msgid "Date"
+msgstr "Data"
+
+msgctxt "field:sale.complaint,description:"
+msgid "Description"
+msgstr "Descrição"
+
+msgctxt "field:sale.complaint,employee:"
+msgid "Employee"
+msgstr "Empregado"
+
+msgctxt "field:sale.complaint,number:"
+msgid "Number"
+msgstr "Número"
+
+msgctxt "field:sale.complaint,origin:"
+msgid "Origin"
+msgstr "Origem"
+
+msgctxt "field:sale.complaint,origin_id:"
+msgid "Origin ID"
+msgstr "ID de Origem"
+
+msgctxt "field:sale.complaint,origin_model:"
+msgid "Origin Model"
+msgstr "Modelo de Origem"
+
+msgctxt "field:sale.complaint,reference:"
+msgid "Reference"
+msgstr "Referência"
+
+msgctxt "field:sale.complaint,state:"
+msgid "State"
+msgstr "Estado"
+
+msgctxt "field:sale.complaint,type:"
+msgid "Type"
+msgstr "Tipo"
+
+msgctxt "field:sale.complaint.action,action:"
+msgid "Action"
+msgstr "Ação"
+
+msgctxt "field:sale.complaint.action,amount:"
+msgid "Amount"
+msgstr ""
+
+msgctxt "field:sale.complaint.action,complaint:"
+msgid "Complaint"
+msgstr "Reclamação"
+
+#, fuzzy
+msgctxt "field:sale.complaint.action,complaint_state:"
+msgid "Complaint State"
+msgstr "Reclamação"
+
+msgctxt "field:sale.complaint.action,currency:"
+msgid "Currency"
+msgstr ""
+
+#, fuzzy
+msgctxt "field:sale.complaint.action,currency_digits:"
+msgid "Currency Digits"
+msgstr "Dígitos Decimais da Unidade"
+
+msgctxt "field:sale.complaint.action,invoice_lines:"
+msgid "Invoice Lines"
+msgstr "Linhas da fatura"
+
+msgctxt "field:sale.complaint.action,quantity:"
+msgid "Quantity"
+msgstr "Quantidade"
+
+msgctxt "field:sale.complaint.action,result:"
+msgid "Result"
+msgstr "Resultado"
+
+msgctxt "field:sale.complaint.action,sale_lines:"
+msgid "Sale Lines"
+msgstr "Linhas de Venda"
+
+msgctxt "field:sale.complaint.action,unit:"
+msgid "Unit"
+msgstr "Unidade"
+
+msgctxt "field:sale.complaint.action,unit_digits:"
+msgid "Unit Digits"
+msgstr "Dígitos Decimais da Unidade"
+
+msgctxt "field:sale.complaint.action,unit_price:"
+msgid "Unit Price"
+msgstr "Preço Unitário"
+
+msgctxt "field:sale.complaint.action-account.invoice.line,action:"
+msgid "Action"
+msgstr "Ação"
+
+msgctxt "field:sale.complaint.action-account.invoice.line,amount:"
+msgid "Amount"
+msgstr ""
+
+#, fuzzy
+msgctxt ""
+"field:sale.complaint.action-account.invoice.line,complaint_origin_id:"
+msgid "Complaint Origin ID"
+msgstr "ID de Origem"
+
+#, fuzzy
+msgctxt "field:sale.complaint.action-account.invoice.line,complaint_state:"
+msgid "Complaint State"
+msgstr "Reclamação"
+
+msgctxt "field:sale.complaint.action-account.invoice.line,currency:"
+msgid "Currency"
+msgstr ""
+
+#, fuzzy
+msgctxt "field:sale.complaint.action-account.invoice.line,currency_digits:"
+msgid "Currency Digits"
+msgstr "Dígitos Decimais da Unidade"
+
+msgctxt "field:sale.complaint.action-account.invoice.line,line:"
+msgid "Invoice Line"
+msgstr "Linha da Fatura"
+
+#, fuzzy
+msgctxt "field:sale.complaint.action-account.invoice.line,quantity:"
+msgid "Quantity"
+msgstr "Quantidade"
+
+#, fuzzy
+msgctxt "field:sale.complaint.action-account.invoice.line,unit:"
+msgid "Unit"
+msgstr "Unidade"
+
+#, fuzzy
+msgctxt "field:sale.complaint.action-account.invoice.line,unit_digits:"
+msgid "Unit Digits"
+msgstr "Dígitos Decimais da Unidade"
+
+#, fuzzy
+msgctxt "field:sale.complaint.action-account.invoice.line,unit_price:"
+msgid "Unit Price"
+msgstr "Preço Unitário"
+
+msgctxt "field:sale.complaint.action-sale.line,action:"
+msgid "Action"
+msgstr "Ação"
+
+msgctxt "field:sale.complaint.action-sale.line,amount:"
+msgid "Amount"
+msgstr ""
+
+#, fuzzy
+msgctxt "field:sale.complaint.action-sale.line,complaint_origin_id:"
+msgid "Complaint Origin ID"
+msgstr "ID de Origem"
+
+#, fuzzy
+msgctxt "field:sale.complaint.action-sale.line,complaint_state:"
+msgid "Complaint State"
+msgstr "Reclamação"
+
+msgctxt "field:sale.complaint.action-sale.line,currency:"
+msgid "Currency"
+msgstr ""
+
+#, fuzzy
+msgctxt "field:sale.complaint.action-sale.line,currency_digits:"
+msgid "Currency Digits"
+msgstr "Dígitos Decimais da Unidade"
+
+msgctxt "field:sale.complaint.action-sale.line,line:"
+msgid "Sale Line"
+msgstr "Linha de Venda"
+
+#, fuzzy
+msgctxt "field:sale.complaint.action-sale.line,quantity:"
+msgid "Quantity"
+msgstr "Quantidade"
+
+#, fuzzy
+msgctxt "field:sale.complaint.action-sale.line,unit:"
+msgid "Unit"
+msgstr "Unidade"
+
+#, fuzzy
+msgctxt "field:sale.complaint.action-sale.line,unit_digits:"
+msgid "Unit Digits"
+msgstr "Dígitos Decimais da Unidade"
+
+#, fuzzy
+msgctxt "field:sale.complaint.action-sale.line,unit_price:"
+msgid "Unit Price"
+msgstr "Preço Unitário"
+
+msgctxt "field:sale.complaint.type,name:"
+msgid "Name"
+msgstr "Nome"
+
+msgctxt "field:sale.complaint.type,origin:"
+msgid "Origin"
+msgstr "Origem"
+
+msgctxt "field:sale.configuration,complaint_sequence:"
+msgid "Complaint Sequence"
+msgstr "Sequência de Reclamação"
+
+msgctxt "field:sale.configuration.sequence,complaint_sequence:"
+msgid "Complaint Sequence"
+msgstr "Sequência de Reclamação"
+
+#, fuzzy
+msgctxt "help:sale.complaint.action,invoice_lines:"
+msgid "Leave empty for all lines."
+msgstr "Deixe vazio para todas as linhas"
+
+#, fuzzy
+msgctxt "help:sale.complaint.action,quantity:"
+msgid "Leave empty for the same quantity."
+msgstr "Deixe vazio para a mesma quantidade"
+
+#, fuzzy
+msgctxt "help:sale.complaint.action,sale_lines:"
+msgid "Leave empty for all lines."
+msgstr "Deixe vazio para todas as linhas"
+
+#, fuzzy
+msgctxt "help:sale.complaint.action,unit_price:"
+msgid "Leave empty for the same price."
+msgstr "Deixe vazio para o mesmo preço"
+
+#, fuzzy
+msgctxt "help:sale.complaint.action-account.invoice.line,unit_price:"
+msgid "Leave empty for the same price."
+msgstr "Deixe vazio para o mesmo preço"
+
+#, fuzzy
+msgctxt "help:sale.complaint.action-sale.line,unit_price:"
+msgid "Leave empty for the same price."
+msgstr "Deixe vazio para o mesmo preço"
+
+#, fuzzy
+msgctxt "model:ir.action,name:act_complaint_form"
+msgid "Complaints"
+msgstr "Complaints"
+
+#, fuzzy
+msgctxt "model:ir.action,name:act_complaint_relate_party"
+msgid "Customer Complaints"
+msgstr "Customer Complaints"
+
+#, fuzzy
+msgctxt "model:ir.action,name:act_complaint_relate_sale"
+msgid "Complaints"
+msgstr "Complaints"
+
+#, fuzzy
+msgctxt "model:ir.action,name:act_type_form"
+msgid "Types"
+msgstr "Types"
+
+#, fuzzy
+msgctxt "model:ir.action.act_window.domain,name:act_complaint_form_domain_all"
+msgid "All"
+msgstr "All"
+
+#, fuzzy
+msgctxt ""
+"model:ir.action.act_window.domain,name:act_complaint_form_domain_approved"
+msgid "Approved"
+msgstr "Approved"
+
+#, fuzzy
+msgctxt ""
+"model:ir.action.act_window.domain,name:act_complaint_form_domain_draft"
+msgid "Draft"
+msgstr "Draft"
+
+#, fuzzy
+msgctxt ""
+"model:ir.action.act_window.domain,name:act_complaint_form_domain_waiting"
+msgid "Waiting"
+msgstr "Waiting"
+
+msgctxt "model:ir.message,text:msg_action_delete_result"
+msgid "You cannot delete action \"%(action)s\" because it has a result."
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_complaint_delete_draft"
+msgid "To delete complaint \"%(complaint)s\" you must reset it to draft state."
+msgstr ""
+
+msgctxt "model:ir.model.button,string:complaint_approve_button"
+msgid "Approve"
+msgstr "Approve"
+
+msgctxt "model:ir.model.button,string:complaint_cancel_button"
+msgid "Cancel"
+msgstr "Cancel"
+
+msgctxt "model:ir.model.button,string:complaint_do_button"
+msgid "Process"
+msgstr "Process"
+
+msgctxt "model:ir.model.button,string:complaint_draft_button"
+msgid "Draft"
+msgstr "Draft"
+
+msgctxt "model:ir.model.button,string:complaint_reject_button"
+msgid "Reject"
+msgstr "Reject"
+
+msgctxt "model:ir.model.button,string:complaint_wait_button"
+msgid "Wait"
+msgstr "Wait"
+
+#, fuzzy
+msgctxt "model:ir.rule.group,name:rule_group_complaint_companies"
+msgid "User in companies"
+msgstr "Ação da Reclamação do Cliente"
+
+#, fuzzy
+msgctxt "model:ir.sequence,name:sequence_complaint"
+msgid "Customer Complaint"
+msgstr "Customer Complaint"
+
+#, fuzzy
+msgctxt "model:ir.sequence.type,name:sequence_type_complaint"
+msgid "Customer Complaint"
+msgstr "Customer Complaint"
+
+#, fuzzy
+msgctxt "model:ir.ui.menu,name:menu_complaint"
+msgid "Complaints"
+msgstr "Complaints"
+
+#, fuzzy
+msgctxt "model:ir.ui.menu,name:menu_configuration"
+msgid "Customer Complaint"
+msgstr "Customer Complaint"
+
+#, fuzzy
+msgctxt "model:ir.ui.menu,name:menu_type"
+msgid "Types"
+msgstr "Types"
+
+msgctxt "model:sale.complaint,name:"
+msgid "Customer Complaint"
+msgstr "Reclamação do Cliente"
+
+msgctxt "model:sale.complaint.action,name:"
+msgid "Customer Complaint Action"
+msgstr "Ação da Reclamação do Cliente"
+
+msgctxt "model:sale.complaint.action-account.invoice.line,name:"
+msgid "Customer Complaint Action - Invoice Line"
+msgstr "Ação de Reclamação do Cliente - Linha de Fatura"
+
+msgctxt "model:sale.complaint.action-sale.line,name:"
+msgid "Customer Complaint Action - Sale Line"
+msgstr "Ação de Reclamação do Cliente - Linha de Venda"
+
+msgctxt "model:sale.complaint.type,name:"
+msgid "Customer Complaint Type"
+msgstr "Tipo de Reclamação do Cliente"
+
+msgctxt "selection:sale.complaint,state:"
+msgid "Approved"
+msgstr "Aprovado"
+
+msgctxt "selection:sale.complaint,state:"
+msgid "Cancelled"
+msgstr "Cancelado"
+
+msgctxt "selection:sale.complaint,state:"
+msgid "Done"
+msgstr "Concluído"
+
+msgctxt "selection:sale.complaint,state:"
+msgid "Draft"
+msgstr "Rascunho"
+
+msgctxt "selection:sale.complaint,state:"
+msgid "Rejected"
+msgstr "Rejeitado"
+
+msgctxt "selection:sale.complaint,state:"
+msgid "Waiting"
+msgstr "Em espera"
+
+msgctxt "selection:sale.complaint.action,action:"
+msgid "Create Credit Note"
+msgstr "Criar Nota de Crédito"
+
+msgctxt "selection:sale.complaint.action,action:"
+msgid "Create Sale Return"
+msgstr "Criar uma Devolução de Venda"
+
+msgctxt "view:sale.complaint.action:"
+msgid "Amount"
+msgstr ""
+
+msgctxt "view:sale.complaint:"
+msgid "Complaint"
+msgstr "Reclamação"
+
+msgctxt "view:sale.complaint:"
+msgid "Process"
+msgstr "Processar"
diff --git a/modules/sale_complaint/locale/ro.po b/modules/sale_complaint/locale/ro.po
new file mode 100644
index 0000000000..1b370eb736
--- /dev/null
+++ b/modules/sale_complaint/locale/ro.po
@@ -0,0 +1,395 @@
+#
+msgid ""
+msgstr "Content-Type: text/plain; charset=utf-8\n"
+
+msgctxt "field:sale.complaint,actions:"
+msgid "Actions"
+msgstr ""
+
+msgctxt "field:sale.complaint,address:"
+msgid "Address"
+msgstr "Adresa"
+
+msgctxt "field:sale.complaint,company:"
+msgid "Company"
+msgstr "Companie"
+
+msgctxt "field:sale.complaint,customer:"
+msgid "Customer"
+msgstr ""
+
+msgctxt "field:sale.complaint,date:"
+msgid "Date"
+msgstr "Data"
+
+msgctxt "field:sale.complaint,description:"
+msgid "Description"
+msgstr "Descriere"
+
+msgctxt "field:sale.complaint,employee:"
+msgid "Employee"
+msgstr "Angajat"
+
+msgctxt "field:sale.complaint,number:"
+msgid "Number"
+msgstr "Număr"
+
+msgctxt "field:sale.complaint,origin:"
+msgid "Origin"
+msgstr "Origine"
+
+msgctxt "field:sale.complaint,origin_id:"
+msgid "Origin ID"
+msgstr ""
+
+msgctxt "field:sale.complaint,origin_model:"
+msgid "Origin Model"
+msgstr ""
+
+msgctxt "field:sale.complaint,reference:"
+msgid "Reference"
+msgstr ""
+
+msgctxt "field:sale.complaint,state:"
+msgid "State"
+msgstr ""
+
+msgctxt "field:sale.complaint,type:"
+msgid "Type"
+msgstr ""
+
+msgctxt "field:sale.complaint.action,action:"
+msgid "Action"
+msgstr "Acțiune"
+
+msgctxt "field:sale.complaint.action,amount:"
+msgid "Amount"
+msgstr ""
+
+msgctxt "field:sale.complaint.action,complaint:"
+msgid "Complaint"
+msgstr ""
+
+msgctxt "field:sale.complaint.action,complaint_state:"
+msgid "Complaint State"
+msgstr ""
+
+msgctxt "field:sale.complaint.action,currency:"
+msgid "Currency"
+msgstr ""
+
+msgctxt "field:sale.complaint.action,currency_digits:"
+msgid "Currency Digits"
+msgstr ""
+
+msgctxt "field:sale.complaint.action,invoice_lines:"
+msgid "Invoice Lines"
+msgstr ""
+
+msgctxt "field:sale.complaint.action,quantity:"
+msgid "Quantity"
+msgstr ""
+
+msgctxt "field:sale.complaint.action,result:"
+msgid "Result"
+msgstr ""
+
+msgctxt "field:sale.complaint.action,sale_lines:"
+msgid "Sale Lines"
+msgstr ""
+
+msgctxt "field:sale.complaint.action,unit:"
+msgid "Unit"
+msgstr ""
+
+msgctxt "field:sale.complaint.action,unit_digits:"
+msgid "Unit Digits"
+msgstr ""
+
+msgctxt "field:sale.complaint.action,unit_price:"
+msgid "Unit Price"
+msgstr ""
+
+msgctxt "field:sale.complaint.action-account.invoice.line,action:"
+msgid "Action"
+msgstr "Acțiune"
+
+msgctxt "field:sale.complaint.action-account.invoice.line,amount:"
+msgid "Amount"
+msgstr ""
+
+msgctxt ""
+"field:sale.complaint.action-account.invoice.line,complaint_origin_id:"
+msgid "Complaint Origin ID"
+msgstr ""
+
+msgctxt "field:sale.complaint.action-account.invoice.line,complaint_state:"
+msgid "Complaint State"
+msgstr ""
+
+msgctxt "field:sale.complaint.action-account.invoice.line,currency:"
+msgid "Currency"
+msgstr ""
+
+msgctxt "field:sale.complaint.action-account.invoice.line,currency_digits:"
+msgid "Currency Digits"
+msgstr ""
+
+msgctxt "field:sale.complaint.action-account.invoice.line,line:"
+msgid "Invoice Line"
+msgstr ""
+
+msgctxt "field:sale.complaint.action-account.invoice.line,quantity:"
+msgid "Quantity"
+msgstr ""
+
+msgctxt "field:sale.complaint.action-account.invoice.line,unit:"
+msgid "Unit"
+msgstr ""
+
+msgctxt "field:sale.complaint.action-account.invoice.line,unit_digits:"
+msgid "Unit Digits"
+msgstr ""
+
+msgctxt "field:sale.complaint.action-account.invoice.line,unit_price:"
+msgid "Unit Price"
+msgstr ""
+
+msgctxt "field:sale.complaint.action-sale.line,action:"
+msgid "Action"
+msgstr "Acțiune"
+
+msgctxt "field:sale.complaint.action-sale.line,amount:"
+msgid "Amount"
+msgstr ""
+
+msgctxt "field:sale.complaint.action-sale.line,complaint_origin_id:"
+msgid "Complaint Origin ID"
+msgstr ""
+
+msgctxt "field:sale.complaint.action-sale.line,complaint_state:"
+msgid "Complaint State"
+msgstr ""
+
+msgctxt "field:sale.complaint.action-sale.line,currency:"
+msgid "Currency"
+msgstr ""
+
+msgctxt "field:sale.complaint.action-sale.line,currency_digits:"
+msgid "Currency Digits"
+msgstr ""
+
+msgctxt "field:sale.complaint.action-sale.line,line:"
+msgid "Sale Line"
+msgstr ""
+
+msgctxt "field:sale.complaint.action-sale.line,quantity:"
+msgid "Quantity"
+msgstr ""
+
+msgctxt "field:sale.complaint.action-sale.line,unit:"
+msgid "Unit"
+msgstr ""
+
+msgctxt "field:sale.complaint.action-sale.line,unit_digits:"
+msgid "Unit Digits"
+msgstr ""
+
+msgctxt "field:sale.complaint.action-sale.line,unit_price:"
+msgid "Unit Price"
+msgstr ""
+
+msgctxt "field:sale.complaint.type,name:"
+msgid "Name"
+msgstr ""
+
+msgctxt "field:sale.complaint.type,origin:"
+msgid "Origin"
+msgstr "Origine"
+
+msgctxt "field:sale.configuration,complaint_sequence:"
+msgid "Complaint Sequence"
+msgstr ""
+
+msgctxt "field:sale.configuration.sequence,complaint_sequence:"
+msgid "Complaint Sequence"
+msgstr ""
+
+msgctxt "help:sale.complaint.action,invoice_lines:"
+msgid "Leave empty for all lines."
+msgstr ""
+
+msgctxt "help:sale.complaint.action,quantity:"
+msgid "Leave empty for the same quantity."
+msgstr ""
+
+msgctxt "help:sale.complaint.action,sale_lines:"
+msgid "Leave empty for all lines."
+msgstr ""
+
+msgctxt "help:sale.complaint.action,unit_price:"
+msgid "Leave empty for the same price."
+msgstr ""
+
+msgctxt "help:sale.complaint.action-account.invoice.line,unit_price:"
+msgid "Leave empty for the same price."
+msgstr ""
+
+msgctxt "help:sale.complaint.action-sale.line,unit_price:"
+msgid "Leave empty for the same price."
+msgstr ""
+
+msgctxt "model:ir.action,name:act_complaint_form"
+msgid "Complaints"
+msgstr ""
+
+msgctxt "model:ir.action,name:act_complaint_relate_party"
+msgid "Customer Complaints"
+msgstr ""
+
+msgctxt "model:ir.action,name:act_complaint_relate_sale"
+msgid "Complaints"
+msgstr ""
+
+msgctxt "model:ir.action,name:act_type_form"
+msgid "Types"
+msgstr ""
+
+msgctxt "model:ir.action.act_window.domain,name:act_complaint_form_domain_all"
+msgid "All"
+msgstr ""
+
+msgctxt ""
+"model:ir.action.act_window.domain,name:act_complaint_form_domain_approved"
+msgid "Approved"
+msgstr ""
+
+msgctxt ""
+"model:ir.action.act_window.domain,name:act_complaint_form_domain_draft"
+msgid "Draft"
+msgstr ""
+
+msgctxt ""
+"model:ir.action.act_window.domain,name:act_complaint_form_domain_waiting"
+msgid "Waiting"
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_action_delete_result"
+msgid "You cannot delete action \"%(action)s\" because it has a result."
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_complaint_delete_draft"
+msgid "To delete complaint \"%(complaint)s\" you must reset it to draft state."
+msgstr ""
+
+msgctxt "model:ir.model.button,string:complaint_approve_button"
+msgid "Approve"
+msgstr ""
+
+msgctxt "model:ir.model.button,string:complaint_cancel_button"
+msgid "Cancel"
+msgstr ""
+
+msgctxt "model:ir.model.button,string:complaint_do_button"
+msgid "Process"
+msgstr ""
+
+msgctxt "model:ir.model.button,string:complaint_draft_button"
+msgid "Draft"
+msgstr ""
+
+msgctxt "model:ir.model.button,string:complaint_reject_button"
+msgid "Reject"
+msgstr ""
+
+msgctxt "model:ir.model.button,string:complaint_wait_button"
+msgid "Wait"
+msgstr ""
+
+msgctxt "model:ir.rule.group,name:rule_group_complaint_companies"
+msgid "User in companies"
+msgstr ""
+
+msgctxt "model:ir.sequence,name:sequence_complaint"
+msgid "Customer Complaint"
+msgstr ""
+
+msgctxt "model:ir.sequence.type,name:sequence_type_complaint"
+msgid "Customer Complaint"
+msgstr ""
+
+msgctxt "model:ir.ui.menu,name:menu_complaint"
+msgid "Complaints"
+msgstr ""
+
+msgctxt "model:ir.ui.menu,name:menu_configuration"
+msgid "Customer Complaint"
+msgstr ""
+
+msgctxt "model:ir.ui.menu,name:menu_type"
+msgid "Types"
+msgstr ""
+
+msgctxt "model:sale.complaint,name:"
+msgid "Customer Complaint"
+msgstr ""
+
+msgctxt "model:sale.complaint.action,name:"
+msgid "Customer Complaint Action"
+msgstr ""
+
+msgctxt "model:sale.complaint.action-account.invoice.line,name:"
+msgid "Customer Complaint Action - Invoice Line"
+msgstr ""
+
+msgctxt "model:sale.complaint.action-sale.line,name:"
+msgid "Customer Complaint Action - Sale Line"
+msgstr ""
+
+msgctxt "model:sale.complaint.type,name:"
+msgid "Customer Complaint Type"
+msgstr ""
+
+msgctxt "selection:sale.complaint,state:"
+msgid "Approved"
+msgstr ""
+
+msgctxt "selection:sale.complaint,state:"
+msgid "Cancelled"
+msgstr ""
+
+msgctxt "selection:sale.complaint,state:"
+msgid "Done"
+msgstr ""
+
+msgctxt "selection:sale.complaint,state:"
+msgid "Draft"
+msgstr ""
+
+msgctxt "selection:sale.complaint,state:"
+msgid "Rejected"
+msgstr ""
+
+msgctxt "selection:sale.complaint,state:"
+msgid "Waiting"
+msgstr ""
+
+msgctxt "selection:sale.complaint.action,action:"
+msgid "Create Credit Note"
+msgstr ""
+
+msgctxt "selection:sale.complaint.action,action:"
+msgid "Create Sale Return"
+msgstr ""
+
+msgctxt "view:sale.complaint.action:"
+msgid "Amount"
+msgstr ""
+
+msgctxt "view:sale.complaint:"
+msgid "Complaint"
+msgstr ""
+
+msgctxt "view:sale.complaint:"
+msgid "Process"
+msgstr ""
diff --git a/modules/sale_complaint/locale/ru.po b/modules/sale_complaint/locale/ru.po
new file mode 100644
index 0000000000..ca2aada33c
--- /dev/null
+++ b/modules/sale_complaint/locale/ru.po
@@ -0,0 +1,455 @@
+#
+msgid ""
+msgstr "Content-Type: text/plain; charset=utf-8\n"
+
+#, fuzzy
+msgctxt "field:sale.complaint,actions:"
+msgid "Actions"
+msgstr "Действия"
+
+#, fuzzy
+msgctxt "field:sale.complaint,address:"
+msgid "Address"
+msgstr "Адрес"
+
+#, fuzzy
+msgctxt "field:sale.complaint,company:"
+msgid "Company"
+msgstr "Учет.орг."
+
+#, fuzzy
+msgctxt "field:sale.complaint,customer:"
+msgid "Customer"
+msgstr "Заказчик"
+
+#, fuzzy
+msgctxt "field:sale.complaint,date:"
+msgid "Date"
+msgstr "Дата"
+
+#, fuzzy
+msgctxt "field:sale.complaint,description:"
+msgid "Description"
+msgstr "Описание"
+
+#, fuzzy
+msgctxt "field:sale.complaint,employee:"
+msgid "Employee"
+msgstr "Сотрудник"
+
+#, fuzzy
+msgctxt "field:sale.complaint,number:"
+msgid "Number"
+msgstr "Номер"
+
+#, fuzzy
+msgctxt "field:sale.complaint,origin:"
+msgid "Origin"
+msgstr "Первоисточник"
+
+msgctxt "field:sale.complaint,origin_id:"
+msgid "Origin ID"
+msgstr ""
+
+msgctxt "field:sale.complaint,origin_model:"
+msgid "Origin Model"
+msgstr ""
+
+#, fuzzy
+msgctxt "field:sale.complaint,reference:"
+msgid "Reference"
+msgstr "Ссылка"
+
+#, fuzzy
+msgctxt "field:sale.complaint,state:"
+msgid "State"
+msgstr "Штат"
+
+#, fuzzy
+msgctxt "field:sale.complaint,type:"
+msgid "Type"
+msgstr "Тип"
+
+#, fuzzy
+msgctxt "field:sale.complaint.action,action:"
+msgid "Action"
+msgstr "Действие"
+
+msgctxt "field:sale.complaint.action,amount:"
+msgid "Amount"
+msgstr ""
+
+#, fuzzy
+msgctxt "field:sale.complaint.action,complaint:"
+msgid "Complaint"
+msgstr "Complaints"
+
+#, fuzzy
+msgctxt "field:sale.complaint.action,complaint_state:"
+msgid "Complaint State"
+msgstr "Complaints"
+
+msgctxt "field:sale.complaint.action,currency:"
+msgid "Currency"
+msgstr ""
+
+#, fuzzy
+msgctxt "field:sale.complaint.action,currency_digits:"
+msgid "Currency Digits"
+msgstr "Кол-во цифр после запятой"
+
+#, fuzzy
+msgctxt "field:sale.complaint.action,invoice_lines:"
+msgid "Invoice Lines"
+msgstr "Строки инвойса"
+
+#, fuzzy
+msgctxt "field:sale.complaint.action,quantity:"
+msgid "Quantity"
+msgstr "Кол-во"
+
+msgctxt "field:sale.complaint.action,result:"
+msgid "Result"
+msgstr ""
+
+#, fuzzy
+msgctxt "field:sale.complaint.action,sale_lines:"
+msgid "Sale Lines"
+msgstr "Строка продажи"
+
+#, fuzzy
+msgctxt "field:sale.complaint.action,unit:"
+msgid "Unit"
+msgstr "Штука"
+
+#, fuzzy
+msgctxt "field:sale.complaint.action,unit_digits:"
+msgid "Unit Digits"
+msgstr "Кол-во цифр после запятой"
+
+#, fuzzy
+msgctxt "field:sale.complaint.action,unit_price:"
+msgid "Unit Price"
+msgstr "Цена за единицу"
+
+#, fuzzy
+msgctxt "field:sale.complaint.action-account.invoice.line,action:"
+msgid "Action"
+msgstr "Действие"
+
+msgctxt "field:sale.complaint.action-account.invoice.line,amount:"
+msgid "Amount"
+msgstr ""
+
+#, fuzzy
+msgctxt ""
+"field:sale.complaint.action-account.invoice.line,complaint_origin_id:"
+msgid "Complaint Origin ID"
+msgstr "Complaints"
+
+#, fuzzy
+msgctxt "field:sale.complaint.action-account.invoice.line,complaint_state:"
+msgid "Complaint State"
+msgstr "Complaints"
+
+msgctxt "field:sale.complaint.action-account.invoice.line,currency:"
+msgid "Currency"
+msgstr ""
+
+#, fuzzy
+msgctxt "field:sale.complaint.action-account.invoice.line,currency_digits:"
+msgid "Currency Digits"
+msgstr "Кол-во цифр после запятой"
+
+#, fuzzy
+msgctxt "field:sale.complaint.action-account.invoice.line,line:"
+msgid "Invoice Line"
+msgstr "Строка инвойса"
+
+#, fuzzy
+msgctxt "field:sale.complaint.action-account.invoice.line,quantity:"
+msgid "Quantity"
+msgstr "Кол-во"
+
+#, fuzzy
+msgctxt "field:sale.complaint.action-account.invoice.line,unit:"
+msgid "Unit"
+msgstr "Штука"
+
+#, fuzzy
+msgctxt "field:sale.complaint.action-account.invoice.line,unit_digits:"
+msgid "Unit Digits"
+msgstr "Кол-во цифр после запятой"
+
+#, fuzzy
+msgctxt "field:sale.complaint.action-account.invoice.line,unit_price:"
+msgid "Unit Price"
+msgstr "Цена за единицу"
+
+#, fuzzy
+msgctxt "field:sale.complaint.action-sale.line,action:"
+msgid "Action"
+msgstr "Действие"
+
+msgctxt "field:sale.complaint.action-sale.line,amount:"
+msgid "Amount"
+msgstr ""
+
+#, fuzzy
+msgctxt "field:sale.complaint.action-sale.line,complaint_origin_id:"
+msgid "Complaint Origin ID"
+msgstr "Complaints"
+
+#, fuzzy
+msgctxt "field:sale.complaint.action-sale.line,complaint_state:"
+msgid "Complaint State"
+msgstr "Complaints"
+
+msgctxt "field:sale.complaint.action-sale.line,currency:"
+msgid "Currency"
+msgstr ""
+
+#, fuzzy
+msgctxt "field:sale.complaint.action-sale.line,currency_digits:"
+msgid "Currency Digits"
+msgstr "Кол-во цифр после запятой"
+
+#, fuzzy
+msgctxt "field:sale.complaint.action-sale.line,line:"
+msgid "Sale Line"
+msgstr "Строка продажи"
+
+#, fuzzy
+msgctxt "field:sale.complaint.action-sale.line,quantity:"
+msgid "Quantity"
+msgstr "Кол-во"
+
+#, fuzzy
+msgctxt "field:sale.complaint.action-sale.line,unit:"
+msgid "Unit"
+msgstr "Штука"
+
+#, fuzzy
+msgctxt "field:sale.complaint.action-sale.line,unit_digits:"
+msgid "Unit Digits"
+msgstr "Кол-во цифр после запятой"
+
+#, fuzzy
+msgctxt "field:sale.complaint.action-sale.line,unit_price:"
+msgid "Unit Price"
+msgstr "Цена за единицу"
+
+#, fuzzy
+msgctxt "field:sale.complaint.type,name:"
+msgid "Name"
+msgstr "Правило оплаты"
+
+#, fuzzy
+msgctxt "field:sale.complaint.type,origin:"
+msgid "Origin"
+msgstr "Первоисточник"
+
+msgctxt "field:sale.configuration,complaint_sequence:"
+msgid "Complaint Sequence"
+msgstr ""
+
+msgctxt "field:sale.configuration.sequence,complaint_sequence:"
+msgid "Complaint Sequence"
+msgstr ""
+
+msgctxt "help:sale.complaint.action,invoice_lines:"
+msgid "Leave empty for all lines."
+msgstr ""
+
+msgctxt "help:sale.complaint.action,quantity:"
+msgid "Leave empty for the same quantity."
+msgstr ""
+
+msgctxt "help:sale.complaint.action,sale_lines:"
+msgid "Leave empty for all lines."
+msgstr ""
+
+msgctxt "help:sale.complaint.action,unit_price:"
+msgid "Leave empty for the same price."
+msgstr ""
+
+msgctxt "help:sale.complaint.action-account.invoice.line,unit_price:"
+msgid "Leave empty for the same price."
+msgstr ""
+
+msgctxt "help:sale.complaint.action-sale.line,unit_price:"
+msgid "Leave empty for the same price."
+msgstr ""
+
+msgctxt "model:ir.action,name:act_complaint_form"
+msgid "Complaints"
+msgstr "Complaints"
+
+msgctxt "model:ir.action,name:act_complaint_relate_party"
+msgid "Customer Complaints"
+msgstr "Customer Complaints"
+
+msgctxt "model:ir.action,name:act_complaint_relate_sale"
+msgid "Complaints"
+msgstr "Complaints"
+
+#, fuzzy
+msgctxt "model:ir.action,name:act_type_form"
+msgid "Types"
+msgstr "Тип"
+
+#, fuzzy
+msgctxt "model:ir.action.act_window.domain,name:act_complaint_form_domain_all"
+msgid "All"
+msgstr "Все"
+
+#, fuzzy
+msgctxt ""
+"model:ir.action.act_window.domain,name:act_complaint_form_domain_approved"
+msgid "Approved"
+msgstr "Approved"
+
+#, fuzzy
+msgctxt ""
+"model:ir.action.act_window.domain,name:act_complaint_form_domain_draft"
+msgid "Draft"
+msgstr "Черновик"
+
+#, fuzzy
+msgctxt ""
+"model:ir.action.act_window.domain,name:act_complaint_form_domain_waiting"
+msgid "Waiting"
+msgstr "Ожидание"
+
+msgctxt "model:ir.message,text:msg_action_delete_result"
+msgid "You cannot delete action \"%(action)s\" because it has a result."
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_complaint_delete_draft"
+msgid "To delete complaint \"%(complaint)s\" you must reset it to draft state."
+msgstr ""
+
+msgctxt "model:ir.model.button,string:complaint_approve_button"
+msgid "Approve"
+msgstr "Approve"
+
+msgctxt "model:ir.model.button,string:complaint_cancel_button"
+msgid "Cancel"
+msgstr "Cancel"
+
+msgctxt "model:ir.model.button,string:complaint_do_button"
+msgid "Process"
+msgstr "Process"
+
+msgctxt "model:ir.model.button,string:complaint_draft_button"
+msgid "Draft"
+msgstr "Draft"
+
+msgctxt "model:ir.model.button,string:complaint_reject_button"
+msgid "Reject"
+msgstr "Reject"
+
+msgctxt "model:ir.model.button,string:complaint_wait_button"
+msgid "Wait"
+msgstr "Wait"
+
+#, fuzzy
+msgctxt "model:ir.rule.group,name:rule_group_complaint_companies"
+msgid "User in companies"
+msgstr "Customer Complaint"
+
+msgctxt "model:ir.sequence,name:sequence_complaint"
+msgid "Customer Complaint"
+msgstr "Customer Complaint"
+
+msgctxt "model:ir.sequence.type,name:sequence_type_complaint"
+msgid "Customer Complaint"
+msgstr "Customer Complaint"
+
+msgctxt "model:ir.ui.menu,name:menu_complaint"
+msgid "Complaints"
+msgstr "Complaints"
+
+msgctxt "model:ir.ui.menu,name:menu_configuration"
+msgid "Customer Complaint"
+msgstr "Customer Complaint"
+
+#, fuzzy
+msgctxt "model:ir.ui.menu,name:menu_type"
+msgid "Types"
+msgstr "Тип"
+
+#, fuzzy
+msgctxt "model:sale.complaint,name:"
+msgid "Customer Complaint"
+msgstr "Customer Complaint"
+
+#, fuzzy
+msgctxt "model:sale.complaint.action,name:"
+msgid "Customer Complaint Action"
+msgstr "Customer Complaint"
+
+msgctxt "model:sale.complaint.action-account.invoice.line,name:"
+msgid "Customer Complaint Action - Invoice Line"
+msgstr ""
+
+msgctxt "model:sale.complaint.action-sale.line,name:"
+msgid "Customer Complaint Action - Sale Line"
+msgstr ""
+
+#, fuzzy
+msgctxt "model:sale.complaint.type,name:"
+msgid "Customer Complaint Type"
+msgstr "Customer Complaint"
+
+#, fuzzy
+msgctxt "selection:sale.complaint,state:"
+msgid "Approved"
+msgstr "Approve"
+
+#, fuzzy
+msgctxt "selection:sale.complaint,state:"
+msgid "Cancelled"
+msgstr "Отмененно"
+
+#, fuzzy
+msgctxt "selection:sale.complaint,state:"
+msgid "Done"
+msgstr "Выполнено"
+
+#, fuzzy
+msgctxt "selection:sale.complaint,state:"
+msgid "Draft"
+msgstr "Черновик"
+
+#, fuzzy
+msgctxt "selection:sale.complaint,state:"
+msgid "Rejected"
+msgstr "Reject"
+
+#, fuzzy
+msgctxt "selection:sale.complaint,state:"
+msgid "Waiting"
+msgstr "Ожидание"
+
+msgctxt "selection:sale.complaint.action,action:"
+msgid "Create Credit Note"
+msgstr ""
+
+msgctxt "selection:sale.complaint.action,action:"
+msgid "Create Sale Return"
+msgstr ""
+
+msgctxt "view:sale.complaint.action:"
+msgid "Amount"
+msgstr ""
+
+#, fuzzy
+msgctxt "view:sale.complaint:"
+msgid "Complaint"
+msgstr "Complaints"
+
+#, fuzzy
+msgctxt "view:sale.complaint:"
+msgid "Process"
+msgstr "Обработка"
diff --git a/modules/sale_complaint/locale/sl.po b/modules/sale_complaint/locale/sl.po
new file mode 100644
index 0000000000..249798382c
--- /dev/null
+++ b/modules/sale_complaint/locale/sl.po
@@ -0,0 +1,431 @@
+#
+msgid ""
+msgstr "Content-Type: text/plain; charset=utf-8\n"
+
+msgctxt "field:sale.complaint,actions:"
+msgid "Actions"
+msgstr "Ukrepi"
+
+msgctxt "field:sale.complaint,address:"
+msgid "Address"
+msgstr "Naslov"
+
+msgctxt "field:sale.complaint,company:"
+msgid "Company"
+msgstr "Družba"
+
+msgctxt "field:sale.complaint,customer:"
+msgid "Customer"
+msgstr "Kupec"
+
+msgctxt "field:sale.complaint,date:"
+msgid "Date"
+msgstr "Datum"
+
+msgctxt "field:sale.complaint,description:"
+msgid "Description"
+msgstr "Opis"
+
+msgctxt "field:sale.complaint,employee:"
+msgid "Employee"
+msgstr "Zaposlenec"
+
+msgctxt "field:sale.complaint,number:"
+msgid "Number"
+msgstr "Številka"
+
+msgctxt "field:sale.complaint,origin:"
+msgid "Origin"
+msgstr "Poreklo"
+
+msgctxt "field:sale.complaint,origin_id:"
+msgid "Origin ID"
+msgstr "ID porekla"
+
+msgctxt "field:sale.complaint,origin_model:"
+msgid "Origin Model"
+msgstr "Model porekla"
+
+msgctxt "field:sale.complaint,reference:"
+msgid "Reference"
+msgstr "Sklic"
+
+msgctxt "field:sale.complaint,state:"
+msgid "State"
+msgstr "Stanje"
+
+msgctxt "field:sale.complaint,type:"
+msgid "Type"
+msgstr "Vrsta"
+
+msgctxt "field:sale.complaint.action,action:"
+msgid "Action"
+msgstr "Ukrep"
+
+msgctxt "field:sale.complaint.action,amount:"
+msgid "Amount"
+msgstr ""
+
+msgctxt "field:sale.complaint.action,complaint:"
+msgid "Complaint"
+msgstr "Reklamacija"
+
+#, fuzzy
+msgctxt "field:sale.complaint.action,complaint_state:"
+msgid "Complaint State"
+msgstr "Reklamacija"
+
+msgctxt "field:sale.complaint.action,currency:"
+msgid "Currency"
+msgstr ""
+
+#, fuzzy
+msgctxt "field:sale.complaint.action,currency_digits:"
+msgid "Currency Digits"
+msgstr "Decimalke"
+
+msgctxt "field:sale.complaint.action,invoice_lines:"
+msgid "Invoice Lines"
+msgstr "Postavke računov"
+
+msgctxt "field:sale.complaint.action,quantity:"
+msgid "Quantity"
+msgstr "Količina"
+
+msgctxt "field:sale.complaint.action,result:"
+msgid "Result"
+msgstr "Rezultat"
+
+msgctxt "field:sale.complaint.action,sale_lines:"
+msgid "Sale Lines"
+msgstr "Prodajne postavke"
+
+msgctxt "field:sale.complaint.action,unit:"
+msgid "Unit"
+msgstr "enota"
+
+msgctxt "field:sale.complaint.action,unit_digits:"
+msgid "Unit Digits"
+msgstr "Decimalke"
+
+msgctxt "field:sale.complaint.action,unit_price:"
+msgid "Unit Price"
+msgstr "Cena"
+
+msgctxt "field:sale.complaint.action-account.invoice.line,action:"
+msgid "Action"
+msgstr "Ukrep"
+
+msgctxt "field:sale.complaint.action-account.invoice.line,amount:"
+msgid "Amount"
+msgstr ""
+
+#, fuzzy
+msgctxt ""
+"field:sale.complaint.action-account.invoice.line,complaint_origin_id:"
+msgid "Complaint Origin ID"
+msgstr "ID porekla"
+
+#, fuzzy
+msgctxt "field:sale.complaint.action-account.invoice.line,complaint_state:"
+msgid "Complaint State"
+msgstr "Reklamacija"
+
+msgctxt "field:sale.complaint.action-account.invoice.line,currency:"
+msgid "Currency"
+msgstr ""
+
+#, fuzzy
+msgctxt "field:sale.complaint.action-account.invoice.line,currency_digits:"
+msgid "Currency Digits"
+msgstr "Decimalke"
+
+msgctxt "field:sale.complaint.action-account.invoice.line,line:"
+msgid "Invoice Line"
+msgstr "Postavka računa"
+
+#, fuzzy
+msgctxt "field:sale.complaint.action-account.invoice.line,quantity:"
+msgid "Quantity"
+msgstr "Količina"
+
+#, fuzzy
+msgctxt "field:sale.complaint.action-account.invoice.line,unit:"
+msgid "Unit"
+msgstr "enota"
+
+#, fuzzy
+msgctxt "field:sale.complaint.action-account.invoice.line,unit_digits:"
+msgid "Unit Digits"
+msgstr "Decimalke"
+
+#, fuzzy
+msgctxt "field:sale.complaint.action-account.invoice.line,unit_price:"
+msgid "Unit Price"
+msgstr "Cena"
+
+msgctxt "field:sale.complaint.action-sale.line,action:"
+msgid "Action"
+msgstr "Ukrep"
+
+msgctxt "field:sale.complaint.action-sale.line,amount:"
+msgid "Amount"
+msgstr ""
+
+#, fuzzy
+msgctxt "field:sale.complaint.action-sale.line,complaint_origin_id:"
+msgid "Complaint Origin ID"
+msgstr "ID porekla"
+
+#, fuzzy
+msgctxt "field:sale.complaint.action-sale.line,complaint_state:"
+msgid "Complaint State"
+msgstr "Reklamacija"
+
+msgctxt "field:sale.complaint.action-sale.line,currency:"
+msgid "Currency"
+msgstr ""
+
+#, fuzzy
+msgctxt "field:sale.complaint.action-sale.line,currency_digits:"
+msgid "Currency Digits"
+msgstr "Decimalke"
+
+msgctxt "field:sale.complaint.action-sale.line,line:"
+msgid "Sale Line"
+msgstr "Prodajna postavka"
+
+#, fuzzy
+msgctxt "field:sale.complaint.action-sale.line,quantity:"
+msgid "Quantity"
+msgstr "Količina"
+
+#, fuzzy
+msgctxt "field:sale.complaint.action-sale.line,unit:"
+msgid "Unit"
+msgstr "enota"
+
+#, fuzzy
+msgctxt "field:sale.complaint.action-sale.line,unit_digits:"
+msgid "Unit Digits"
+msgstr "Decimalke"
+
+#, fuzzy
+msgctxt "field:sale.complaint.action-sale.line,unit_price:"
+msgid "Unit Price"
+msgstr "Cena"
+
+msgctxt "field:sale.complaint.type,name:"
+msgid "Name"
+msgstr "Naziv"
+
+msgctxt "field:sale.complaint.type,origin:"
+msgid "Origin"
+msgstr "Poreklo"
+
+msgctxt "field:sale.configuration,complaint_sequence:"
+msgid "Complaint Sequence"
+msgstr "Štetje reklamacij"
+
+msgctxt "field:sale.configuration.sequence,complaint_sequence:"
+msgid "Complaint Sequence"
+msgstr "Štetje reklamacij"
+
+#, fuzzy
+msgctxt "help:sale.complaint.action,invoice_lines:"
+msgid "Leave empty for all lines."
+msgstr "Pusti prazno za vse postavke"
+
+#, fuzzy
+msgctxt "help:sale.complaint.action,quantity:"
+msgid "Leave empty for the same quantity."
+msgstr "Pusti prazno za isto količino"
+
+#, fuzzy
+msgctxt "help:sale.complaint.action,sale_lines:"
+msgid "Leave empty for all lines."
+msgstr "Pusti prazno za vse postavke"
+
+#, fuzzy
+msgctxt "help:sale.complaint.action,unit_price:"
+msgid "Leave empty for the same price."
+msgstr "Pusti prazno za isto ceno"
+
+#, fuzzy
+msgctxt "help:sale.complaint.action-account.invoice.line,unit_price:"
+msgid "Leave empty for the same price."
+msgstr "Pusti prazno za isto ceno"
+
+#, fuzzy
+msgctxt "help:sale.complaint.action-sale.line,unit_price:"
+msgid "Leave empty for the same price."
+msgstr "Pusti prazno za isto ceno"
+
+#, fuzzy
+msgctxt "model:ir.action,name:act_complaint_form"
+msgid "Complaints"
+msgstr "Complaints"
+
+#, fuzzy
+msgctxt "model:ir.action,name:act_complaint_relate_party"
+msgid "Customer Complaints"
+msgstr "Customer Complaints"
+
+#, fuzzy
+msgctxt "model:ir.action,name:act_complaint_relate_sale"
+msgid "Complaints"
+msgstr "Complaints"
+
+#, fuzzy
+msgctxt "model:ir.action,name:act_type_form"
+msgid "Types"
+msgstr "Types"
+
+#, fuzzy
+msgctxt "model:ir.action.act_window.domain,name:act_complaint_form_domain_all"
+msgid "All"
+msgstr "All"
+
+#, fuzzy
+msgctxt ""
+"model:ir.action.act_window.domain,name:act_complaint_form_domain_approved"
+msgid "Approved"
+msgstr "Approved"
+
+#, fuzzy
+msgctxt ""
+"model:ir.action.act_window.domain,name:act_complaint_form_domain_draft"
+msgid "Draft"
+msgstr "Draft"
+
+#, fuzzy
+msgctxt ""
+"model:ir.action.act_window.domain,name:act_complaint_form_domain_waiting"
+msgid "Waiting"
+msgstr "Waiting"
+
+msgctxt "model:ir.message,text:msg_action_delete_result"
+msgid "You cannot delete action \"%(action)s\" because it has a result."
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_complaint_delete_draft"
+msgid "To delete complaint \"%(complaint)s\" you must reset it to draft state."
+msgstr ""
+
+msgctxt "model:ir.model.button,string:complaint_approve_button"
+msgid "Approve"
+msgstr "Approve"
+
+msgctxt "model:ir.model.button,string:complaint_cancel_button"
+msgid "Cancel"
+msgstr "Cancel"
+
+msgctxt "model:ir.model.button,string:complaint_do_button"
+msgid "Process"
+msgstr "Process"
+
+msgctxt "model:ir.model.button,string:complaint_draft_button"
+msgid "Draft"
+msgstr "Draft"
+
+msgctxt "model:ir.model.button,string:complaint_reject_button"
+msgid "Reject"
+msgstr "Reject"
+
+msgctxt "model:ir.model.button,string:complaint_wait_button"
+msgid "Wait"
+msgstr "Wait"
+
+#, fuzzy
+msgctxt "model:ir.rule.group,name:rule_group_complaint_companies"
+msgid "User in companies"
+msgstr "Ukrep reklamacije kupca"
+
+#, fuzzy
+msgctxt "model:ir.sequence,name:sequence_complaint"
+msgid "Customer Complaint"
+msgstr "Customer Complaint"
+
+#, fuzzy
+msgctxt "model:ir.sequence.type,name:sequence_type_complaint"
+msgid "Customer Complaint"
+msgstr "Customer Complaint"
+
+#, fuzzy
+msgctxt "model:ir.ui.menu,name:menu_complaint"
+msgid "Complaints"
+msgstr "Complaints"
+
+#, fuzzy
+msgctxt "model:ir.ui.menu,name:menu_configuration"
+msgid "Customer Complaint"
+msgstr "Customer Complaint"
+
+#, fuzzy
+msgctxt "model:ir.ui.menu,name:menu_type"
+msgid "Types"
+msgstr "Types"
+
+msgctxt "model:sale.complaint,name:"
+msgid "Customer Complaint"
+msgstr "Reklamacija kupca"
+
+msgctxt "model:sale.complaint.action,name:"
+msgid "Customer Complaint Action"
+msgstr "Ukrep reklamacije kupca"
+
+msgctxt "model:sale.complaint.action-account.invoice.line,name:"
+msgid "Customer Complaint Action - Invoice Line"
+msgstr "Ukrep reklamacije kupca - Postavka računa"
+
+msgctxt "model:sale.complaint.action-sale.line,name:"
+msgid "Customer Complaint Action - Sale Line"
+msgstr "Ukrep reklamacije kupca - Prodajna postavka"
+
+msgctxt "model:sale.complaint.type,name:"
+msgid "Customer Complaint Type"
+msgstr "Vrsta reklamacije kupca"
+
+msgctxt "selection:sale.complaint,state:"
+msgid "Approved"
+msgstr "Odobreno"
+
+msgctxt "selection:sale.complaint,state:"
+msgid "Cancelled"
+msgstr "Preklicano"
+
+msgctxt "selection:sale.complaint,state:"
+msgid "Done"
+msgstr "Zaključeno"
+
+msgctxt "selection:sale.complaint,state:"
+msgid "Draft"
+msgstr "V pripravi"
+
+msgctxt "selection:sale.complaint,state:"
+msgid "Rejected"
+msgstr "Zavrnjeno"
+
+msgctxt "selection:sale.complaint,state:"
+msgid "Waiting"
+msgstr "Čakajoče"
+
+msgctxt "selection:sale.complaint.action,action:"
+msgid "Create Credit Note"
+msgstr "Izdelava dobropisa"
+
+msgctxt "selection:sale.complaint.action,action:"
+msgid "Create Sale Return"
+msgstr "Izdelava vračilnega naloga"
+
+msgctxt "view:sale.complaint.action:"
+msgid "Amount"
+msgstr ""
+
+msgctxt "view:sale.complaint:"
+msgid "Complaint"
+msgstr "Reklamacija"
+
+msgctxt "view:sale.complaint:"
+msgid "Process"
+msgstr "Obdelava"
diff --git a/modules/sale_complaint/locale/tr.po b/modules/sale_complaint/locale/tr.po
new file mode 100644
index 0000000000..9541df8e51
--- /dev/null
+++ b/modules/sale_complaint/locale/tr.po
@@ -0,0 +1,413 @@
+#
+msgid ""
+msgstr "Content-Type: text/plain; charset=utf-8\n"
+
+msgctxt "field:sale.complaint,actions:"
+msgid "Actions"
+msgstr ""
+
+msgctxt "field:sale.complaint,address:"
+msgid "Address"
+msgstr ""
+
+msgctxt "field:sale.complaint,company:"
+msgid "Company"
+msgstr ""
+
+msgctxt "field:sale.complaint,customer:"
+msgid "Customer"
+msgstr ""
+
+msgctxt "field:sale.complaint,date:"
+msgid "Date"
+msgstr ""
+
+msgctxt "field:sale.complaint,description:"
+msgid "Description"
+msgstr ""
+
+msgctxt "field:sale.complaint,employee:"
+msgid "Employee"
+msgstr ""
+
+msgctxt "field:sale.complaint,number:"
+msgid "Number"
+msgstr ""
+
+msgctxt "field:sale.complaint,origin:"
+msgid "Origin"
+msgstr ""
+
+msgctxt "field:sale.complaint,origin_id:"
+msgid "Origin ID"
+msgstr ""
+
+msgctxt "field:sale.complaint,origin_model:"
+msgid "Origin Model"
+msgstr ""
+
+msgctxt "field:sale.complaint,reference:"
+msgid "Reference"
+msgstr ""
+
+msgctxt "field:sale.complaint,state:"
+msgid "State"
+msgstr ""
+
+#, fuzzy
+msgctxt "field:sale.complaint,type:"
+msgid "Type"
+msgstr "Types"
+
+msgctxt "field:sale.complaint.action,action:"
+msgid "Action"
+msgstr ""
+
+msgctxt "field:sale.complaint.action,amount:"
+msgid "Amount"
+msgstr ""
+
+#, fuzzy
+msgctxt "field:sale.complaint.action,complaint:"
+msgid "Complaint"
+msgstr "Complaints"
+
+#, fuzzy
+msgctxt "field:sale.complaint.action,complaint_state:"
+msgid "Complaint State"
+msgstr "Complaints"
+
+msgctxt "field:sale.complaint.action,currency:"
+msgid "Currency"
+msgstr ""
+
+msgctxt "field:sale.complaint.action,currency_digits:"
+msgid "Currency Digits"
+msgstr ""
+
+msgctxt "field:sale.complaint.action,invoice_lines:"
+msgid "Invoice Lines"
+msgstr ""
+
+msgctxt "field:sale.complaint.action,quantity:"
+msgid "Quantity"
+msgstr ""
+
+msgctxt "field:sale.complaint.action,result:"
+msgid "Result"
+msgstr ""
+
+msgctxt "field:sale.complaint.action,sale_lines:"
+msgid "Sale Lines"
+msgstr ""
+
+msgctxt "field:sale.complaint.action,unit:"
+msgid "Unit"
+msgstr ""
+
+msgctxt "field:sale.complaint.action,unit_digits:"
+msgid "Unit Digits"
+msgstr ""
+
+msgctxt "field:sale.complaint.action,unit_price:"
+msgid "Unit Price"
+msgstr ""
+
+msgctxt "field:sale.complaint.action-account.invoice.line,action:"
+msgid "Action"
+msgstr ""
+
+msgctxt "field:sale.complaint.action-account.invoice.line,amount:"
+msgid "Amount"
+msgstr ""
+
+#, fuzzy
+msgctxt ""
+"field:sale.complaint.action-account.invoice.line,complaint_origin_id:"
+msgid "Complaint Origin ID"
+msgstr "Complaints"
+
+#, fuzzy
+msgctxt "field:sale.complaint.action-account.invoice.line,complaint_state:"
+msgid "Complaint State"
+msgstr "Complaints"
+
+msgctxt "field:sale.complaint.action-account.invoice.line,currency:"
+msgid "Currency"
+msgstr ""
+
+msgctxt "field:sale.complaint.action-account.invoice.line,currency_digits:"
+msgid "Currency Digits"
+msgstr ""
+
+msgctxt "field:sale.complaint.action-account.invoice.line,line:"
+msgid "Invoice Line"
+msgstr ""
+
+msgctxt "field:sale.complaint.action-account.invoice.line,quantity:"
+msgid "Quantity"
+msgstr ""
+
+msgctxt "field:sale.complaint.action-account.invoice.line,unit:"
+msgid "Unit"
+msgstr ""
+
+msgctxt "field:sale.complaint.action-account.invoice.line,unit_digits:"
+msgid "Unit Digits"
+msgstr ""
+
+msgctxt "field:sale.complaint.action-account.invoice.line,unit_price:"
+msgid "Unit Price"
+msgstr ""
+
+msgctxt "field:sale.complaint.action-sale.line,action:"
+msgid "Action"
+msgstr ""
+
+msgctxt "field:sale.complaint.action-sale.line,amount:"
+msgid "Amount"
+msgstr ""
+
+#, fuzzy
+msgctxt "field:sale.complaint.action-sale.line,complaint_origin_id:"
+msgid "Complaint Origin ID"
+msgstr "Complaints"
+
+#, fuzzy
+msgctxt "field:sale.complaint.action-sale.line,complaint_state:"
+msgid "Complaint State"
+msgstr "Complaints"
+
+msgctxt "field:sale.complaint.action-sale.line,currency:"
+msgid "Currency"
+msgstr ""
+
+msgctxt "field:sale.complaint.action-sale.line,currency_digits:"
+msgid "Currency Digits"
+msgstr ""
+
+msgctxt "field:sale.complaint.action-sale.line,line:"
+msgid "Sale Line"
+msgstr ""
+
+msgctxt "field:sale.complaint.action-sale.line,quantity:"
+msgid "Quantity"
+msgstr ""
+
+msgctxt "field:sale.complaint.action-sale.line,unit:"
+msgid "Unit"
+msgstr ""
+
+msgctxt "field:sale.complaint.action-sale.line,unit_digits:"
+msgid "Unit Digits"
+msgstr ""
+
+msgctxt "field:sale.complaint.action-sale.line,unit_price:"
+msgid "Unit Price"
+msgstr ""
+
+msgctxt "field:sale.complaint.type,name:"
+msgid "Name"
+msgstr ""
+
+msgctxt "field:sale.complaint.type,origin:"
+msgid "Origin"
+msgstr ""
+
+msgctxt "field:sale.configuration,complaint_sequence:"
+msgid "Complaint Sequence"
+msgstr ""
+
+msgctxt "field:sale.configuration.sequence,complaint_sequence:"
+msgid "Complaint Sequence"
+msgstr ""
+
+msgctxt "help:sale.complaint.action,invoice_lines:"
+msgid "Leave empty for all lines."
+msgstr ""
+
+msgctxt "help:sale.complaint.action,quantity:"
+msgid "Leave empty for the same quantity."
+msgstr ""
+
+msgctxt "help:sale.complaint.action,sale_lines:"
+msgid "Leave empty for all lines."
+msgstr ""
+
+msgctxt "help:sale.complaint.action,unit_price:"
+msgid "Leave empty for the same price."
+msgstr ""
+
+msgctxt "help:sale.complaint.action-account.invoice.line,unit_price:"
+msgid "Leave empty for the same price."
+msgstr ""
+
+msgctxt "help:sale.complaint.action-sale.line,unit_price:"
+msgid "Leave empty for the same price."
+msgstr ""
+
+msgctxt "model:ir.action,name:act_complaint_form"
+msgid "Complaints"
+msgstr "Complaints"
+
+msgctxt "model:ir.action,name:act_complaint_relate_party"
+msgid "Customer Complaints"
+msgstr "Customer Complaints"
+
+msgctxt "model:ir.action,name:act_complaint_relate_sale"
+msgid "Complaints"
+msgstr "Complaints"
+
+msgctxt "model:ir.action,name:act_type_form"
+msgid "Types"
+msgstr "Types"
+
+msgctxt "model:ir.action.act_window.domain,name:act_complaint_form_domain_all"
+msgid "All"
+msgstr "All"
+
+#, fuzzy
+msgctxt ""
+"model:ir.action.act_window.domain,name:act_complaint_form_domain_approved"
+msgid "Approved"
+msgstr "Approved"
+
+msgctxt ""
+"model:ir.action.act_window.domain,name:act_complaint_form_domain_draft"
+msgid "Draft"
+msgstr "Draft"
+
+msgctxt ""
+"model:ir.action.act_window.domain,name:act_complaint_form_domain_waiting"
+msgid "Waiting"
+msgstr "Waiting"
+
+msgctxt "model:ir.message,text:msg_action_delete_result"
+msgid "You cannot delete action \"%(action)s\" because it has a result."
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_complaint_delete_draft"
+msgid "To delete complaint \"%(complaint)s\" you must reset it to draft state."
+msgstr ""
+
+msgctxt "model:ir.model.button,string:complaint_approve_button"
+msgid "Approve"
+msgstr "Approve"
+
+msgctxt "model:ir.model.button,string:complaint_cancel_button"
+msgid "Cancel"
+msgstr "Cancel"
+
+msgctxt "model:ir.model.button,string:complaint_do_button"
+msgid "Process"
+msgstr "Process"
+
+msgctxt "model:ir.model.button,string:complaint_draft_button"
+msgid "Draft"
+msgstr "Draft"
+
+msgctxt "model:ir.model.button,string:complaint_reject_button"
+msgid "Reject"
+msgstr "Reject"
+
+msgctxt "model:ir.model.button,string:complaint_wait_button"
+msgid "Wait"
+msgstr "Wait"
+
+#, fuzzy
+msgctxt "model:ir.rule.group,name:rule_group_complaint_companies"
+msgid "User in companies"
+msgstr "Customer Complaint"
+
+msgctxt "model:ir.sequence,name:sequence_complaint"
+msgid "Customer Complaint"
+msgstr "Customer Complaint"
+
+msgctxt "model:ir.sequence.type,name:sequence_type_complaint"
+msgid "Customer Complaint"
+msgstr "Customer Complaint"
+
+msgctxt "model:ir.ui.menu,name:menu_complaint"
+msgid "Complaints"
+msgstr "Complaints"
+
+msgctxt "model:ir.ui.menu,name:menu_configuration"
+msgid "Customer Complaint"
+msgstr "Customer Complaint"
+
+msgctxt "model:ir.ui.menu,name:menu_type"
+msgid "Types"
+msgstr "Types"
+
+#, fuzzy
+msgctxt "model:sale.complaint,name:"
+msgid "Customer Complaint"
+msgstr "Customer Complaint"
+
+#, fuzzy
+msgctxt "model:sale.complaint.action,name:"
+msgid "Customer Complaint Action"
+msgstr "Customer Complaint"
+
+msgctxt "model:sale.complaint.action-account.invoice.line,name:"
+msgid "Customer Complaint Action - Invoice Line"
+msgstr ""
+
+msgctxt "model:sale.complaint.action-sale.line,name:"
+msgid "Customer Complaint Action - Sale Line"
+msgstr ""
+
+#, fuzzy
+msgctxt "model:sale.complaint.type,name:"
+msgid "Customer Complaint Type"
+msgstr "Customer Complaint"
+
+#, fuzzy
+msgctxt "selection:sale.complaint,state:"
+msgid "Approved"
+msgstr "Approve"
+
+msgctxt "selection:sale.complaint,state:"
+msgid "Cancelled"
+msgstr ""
+
+msgctxt "selection:sale.complaint,state:"
+msgid "Done"
+msgstr ""
+
+#, fuzzy
+msgctxt "selection:sale.complaint,state:"
+msgid "Draft"
+msgstr "Draft"
+
+#, fuzzy
+msgctxt "selection:sale.complaint,state:"
+msgid "Rejected"
+msgstr "Reject"
+
+#, fuzzy
+msgctxt "selection:sale.complaint,state:"
+msgid "Waiting"
+msgstr "Waiting"
+
+msgctxt "selection:sale.complaint.action,action:"
+msgid "Create Credit Note"
+msgstr ""
+
+msgctxt "selection:sale.complaint.action,action:"
+msgid "Create Sale Return"
+msgstr ""
+
+msgctxt "view:sale.complaint.action:"
+msgid "Amount"
+msgstr ""
+
+#, fuzzy
+msgctxt "view:sale.complaint:"
+msgid "Complaint"
+msgstr "Complaints"
+
+#, fuzzy
+msgctxt "view:sale.complaint:"
+msgid "Process"
+msgstr "Process"
diff --git a/modules/sale_complaint/locale/zh_CN.po b/modules/sale_complaint/locale/zh_CN.po
new file mode 100644
index 0000000000..fd386b2cd2
--- /dev/null
+++ b/modules/sale_complaint/locale/zh_CN.po
@@ -0,0 +1,425 @@
+#
+msgid ""
+msgstr "Content-Type: text/plain; charset=utf-8\n"
+
+#, fuzzy
+msgctxt "field:sale.complaint,actions:"
+msgid "Actions"
+msgstr "操作"
+
+msgctxt "field:sale.complaint,address:"
+msgid "Address"
+msgstr ""
+
+msgctxt "field:sale.complaint,company:"
+msgid "Company"
+msgstr ""
+
+msgctxt "field:sale.complaint,customer:"
+msgid "Customer"
+msgstr ""
+
+#, fuzzy
+msgctxt "field:sale.complaint,date:"
+msgid "Date"
+msgstr "日期格式"
+
+#, fuzzy
+msgctxt "field:sale.complaint,description:"
+msgid "Description"
+msgstr "描述"
+
+msgctxt "field:sale.complaint,employee:"
+msgid "Employee"
+msgstr ""
+
+msgctxt "field:sale.complaint,number:"
+msgid "Number"
+msgstr ""
+
+msgctxt "field:sale.complaint,origin:"
+msgid "Origin"
+msgstr ""
+
+msgctxt "field:sale.complaint,origin_id:"
+msgid "Origin ID"
+msgstr ""
+
+msgctxt "field:sale.complaint,origin_model:"
+msgid "Origin Model"
+msgstr ""
+
+msgctxt "field:sale.complaint,reference:"
+msgid "Reference"
+msgstr ""
+
+#, fuzzy
+msgctxt "field:sale.complaint,state:"
+msgid "State"
+msgstr "状态"
+
+#, fuzzy
+msgctxt "field:sale.complaint,type:"
+msgid "Type"
+msgstr "类型"
+
+#, fuzzy
+msgctxt "field:sale.complaint.action,action:"
+msgid "Action"
+msgstr "操作"
+
+msgctxt "field:sale.complaint.action,amount:"
+msgid "Amount"
+msgstr ""
+
+#, fuzzy
+msgctxt "field:sale.complaint.action,complaint:"
+msgid "Complaint"
+msgstr "Complaints"
+
+#, fuzzy
+msgctxt "field:sale.complaint.action,complaint_state:"
+msgid "Complaint State"
+msgstr "Complaints"
+
+msgctxt "field:sale.complaint.action,currency:"
+msgid "Currency"
+msgstr ""
+
+msgctxt "field:sale.complaint.action,currency_digits:"
+msgid "Currency Digits"
+msgstr ""
+
+msgctxt "field:sale.complaint.action,invoice_lines:"
+msgid "Invoice Lines"
+msgstr ""
+
+msgctxt "field:sale.complaint.action,quantity:"
+msgid "Quantity"
+msgstr ""
+
+msgctxt "field:sale.complaint.action,result:"
+msgid "Result"
+msgstr ""
+
+msgctxt "field:sale.complaint.action,sale_lines:"
+msgid "Sale Lines"
+msgstr ""
+
+msgctxt "field:sale.complaint.action,unit:"
+msgid "Unit"
+msgstr ""
+
+msgctxt "field:sale.complaint.action,unit_digits:"
+msgid "Unit Digits"
+msgstr ""
+
+msgctxt "field:sale.complaint.action,unit_price:"
+msgid "Unit Price"
+msgstr ""
+
+#, fuzzy
+msgctxt "field:sale.complaint.action-account.invoice.line,action:"
+msgid "Action"
+msgstr "操作"
+
+msgctxt "field:sale.complaint.action-account.invoice.line,amount:"
+msgid "Amount"
+msgstr ""
+
+#, fuzzy
+msgctxt ""
+"field:sale.complaint.action-account.invoice.line,complaint_origin_id:"
+msgid "Complaint Origin ID"
+msgstr "Complaints"
+
+#, fuzzy
+msgctxt "field:sale.complaint.action-account.invoice.line,complaint_state:"
+msgid "Complaint State"
+msgstr "Complaints"
+
+msgctxt "field:sale.complaint.action-account.invoice.line,currency:"
+msgid "Currency"
+msgstr ""
+
+msgctxt "field:sale.complaint.action-account.invoice.line,currency_digits:"
+msgid "Currency Digits"
+msgstr ""
+
+msgctxt "field:sale.complaint.action-account.invoice.line,line:"
+msgid "Invoice Line"
+msgstr ""
+
+msgctxt "field:sale.complaint.action-account.invoice.line,quantity:"
+msgid "Quantity"
+msgstr ""
+
+msgctxt "field:sale.complaint.action-account.invoice.line,unit:"
+msgid "Unit"
+msgstr ""
+
+msgctxt "field:sale.complaint.action-account.invoice.line,unit_digits:"
+msgid "Unit Digits"
+msgstr ""
+
+msgctxt "field:sale.complaint.action-account.invoice.line,unit_price:"
+msgid "Unit Price"
+msgstr ""
+
+#, fuzzy
+msgctxt "field:sale.complaint.action-sale.line,action:"
+msgid "Action"
+msgstr "操作"
+
+msgctxt "field:sale.complaint.action-sale.line,amount:"
+msgid "Amount"
+msgstr ""
+
+#, fuzzy
+msgctxt "field:sale.complaint.action-sale.line,complaint_origin_id:"
+msgid "Complaint Origin ID"
+msgstr "Complaints"
+
+#, fuzzy
+msgctxt "field:sale.complaint.action-sale.line,complaint_state:"
+msgid "Complaint State"
+msgstr "Complaints"
+
+msgctxt "field:sale.complaint.action-sale.line,currency:"
+msgid "Currency"
+msgstr ""
+
+msgctxt "field:sale.complaint.action-sale.line,currency_digits:"
+msgid "Currency Digits"
+msgstr ""
+
+msgctxt "field:sale.complaint.action-sale.line,line:"
+msgid "Sale Line"
+msgstr ""
+
+msgctxt "field:sale.complaint.action-sale.line,quantity:"
+msgid "Quantity"
+msgstr ""
+
+msgctxt "field:sale.complaint.action-sale.line,unit:"
+msgid "Unit"
+msgstr ""
+
+msgctxt "field:sale.complaint.action-sale.line,unit_digits:"
+msgid "Unit Digits"
+msgstr ""
+
+msgctxt "field:sale.complaint.action-sale.line,unit_price:"
+msgid "Unit Price"
+msgstr ""
+
+#, fuzzy
+msgctxt "field:sale.complaint.type,name:"
+msgid "Name"
+msgstr "纳木"
+
+msgctxt "field:sale.complaint.type,origin:"
+msgid "Origin"
+msgstr ""
+
+msgctxt "field:sale.configuration,complaint_sequence:"
+msgid "Complaint Sequence"
+msgstr ""
+
+msgctxt "field:sale.configuration.sequence,complaint_sequence:"
+msgid "Complaint Sequence"
+msgstr ""
+
+msgctxt "help:sale.complaint.action,invoice_lines:"
+msgid "Leave empty for all lines."
+msgstr ""
+
+msgctxt "help:sale.complaint.action,quantity:"
+msgid "Leave empty for the same quantity."
+msgstr ""
+
+msgctxt "help:sale.complaint.action,sale_lines:"
+msgid "Leave empty for all lines."
+msgstr ""
+
+msgctxt "help:sale.complaint.action,unit_price:"
+msgid "Leave empty for the same price."
+msgstr ""
+
+msgctxt "help:sale.complaint.action-account.invoice.line,unit_price:"
+msgid "Leave empty for the same price."
+msgstr ""
+
+msgctxt "help:sale.complaint.action-sale.line,unit_price:"
+msgid "Leave empty for the same price."
+msgstr ""
+
+msgctxt "model:ir.action,name:act_complaint_form"
+msgid "Complaints"
+msgstr "Complaints"
+
+msgctxt "model:ir.action,name:act_complaint_relate_party"
+msgid "Customer Complaints"
+msgstr "Customer Complaints"
+
+msgctxt "model:ir.action,name:act_complaint_relate_sale"
+msgid "Complaints"
+msgstr "Complaints"
+
+#, fuzzy
+msgctxt "model:ir.action,name:act_type_form"
+msgid "Types"
+msgstr "类型"
+
+#, fuzzy
+msgctxt "model:ir.action.act_window.domain,name:act_complaint_form_domain_all"
+msgid "All"
+msgstr "全部"
+
+#, fuzzy
+msgctxt ""
+"model:ir.action.act_window.domain,name:act_complaint_form_domain_approved"
+msgid "Approved"
+msgstr "Approved"
+
+msgctxt ""
+"model:ir.action.act_window.domain,name:act_complaint_form_domain_draft"
+msgid "Draft"
+msgstr "Draft"
+
+msgctxt ""
+"model:ir.action.act_window.domain,name:act_complaint_form_domain_waiting"
+msgid "Waiting"
+msgstr "Waiting"
+
+msgctxt "model:ir.message,text:msg_action_delete_result"
+msgid "You cannot delete action \"%(action)s\" because it has a result."
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_complaint_delete_draft"
+msgid "To delete complaint \"%(complaint)s\" you must reset it to draft state."
+msgstr ""
+
+msgctxt "model:ir.model.button,string:complaint_approve_button"
+msgid "Approve"
+msgstr "Approve"
+
+msgctxt "model:ir.model.button,string:complaint_cancel_button"
+msgid "Cancel"
+msgstr "Cancel"
+
+msgctxt "model:ir.model.button,string:complaint_do_button"
+msgid "Process"
+msgstr "Process"
+
+msgctxt "model:ir.model.button,string:complaint_draft_button"
+msgid "Draft"
+msgstr "Draft"
+
+msgctxt "model:ir.model.button,string:complaint_reject_button"
+msgid "Reject"
+msgstr "Reject"
+
+msgctxt "model:ir.model.button,string:complaint_wait_button"
+msgid "Wait"
+msgstr "Wait"
+
+#, fuzzy
+msgctxt "model:ir.rule.group,name:rule_group_complaint_companies"
+msgid "User in companies"
+msgstr "Customer Complaint"
+
+msgctxt "model:ir.sequence,name:sequence_complaint"
+msgid "Customer Complaint"
+msgstr "Customer Complaint"
+
+msgctxt "model:ir.sequence.type,name:sequence_type_complaint"
+msgid "Customer Complaint"
+msgstr "Customer Complaint"
+
+msgctxt "model:ir.ui.menu,name:menu_complaint"
+msgid "Complaints"
+msgstr "Complaints"
+
+msgctxt "model:ir.ui.menu,name:menu_configuration"
+msgid "Customer Complaint"
+msgstr "Customer Complaint"
+
+#, fuzzy
+msgctxt "model:ir.ui.menu,name:menu_type"
+msgid "Types"
+msgstr "类型"
+
+#, fuzzy
+msgctxt "model:sale.complaint,name:"
+msgid "Customer Complaint"
+msgstr "Customer Complaint"
+
+#, fuzzy
+msgctxt "model:sale.complaint.action,name:"
+msgid "Customer Complaint Action"
+msgstr "Customer Complaint"
+
+msgctxt "model:sale.complaint.action-account.invoice.line,name:"
+msgid "Customer Complaint Action - Invoice Line"
+msgstr ""
+
+msgctxt "model:sale.complaint.action-sale.line,name:"
+msgid "Customer Complaint Action - Sale Line"
+msgstr ""
+
+#, fuzzy
+msgctxt "model:sale.complaint.type,name:"
+msgid "Customer Complaint Type"
+msgstr "Customer Complaint"
+
+#, fuzzy
+msgctxt "selection:sale.complaint,state:"
+msgid "Approved"
+msgstr "Approve"
+
+msgctxt "selection:sale.complaint,state:"
+msgid "Cancelled"
+msgstr ""
+
+#, fuzzy
+msgctxt "selection:sale.complaint,state:"
+msgid "Done"
+msgstr "完成"
+
+#, fuzzy
+msgctxt "selection:sale.complaint,state:"
+msgid "Draft"
+msgstr "Draft"
+
+#, fuzzy
+msgctxt "selection:sale.complaint,state:"
+msgid "Rejected"
+msgstr "Reject"
+
+#, fuzzy
+msgctxt "selection:sale.complaint,state:"
+msgid "Waiting"
+msgstr "Waiting"
+
+msgctxt "selection:sale.complaint.action,action:"
+msgid "Create Credit Note"
+msgstr ""
+
+msgctxt "selection:sale.complaint.action,action:"
+msgid "Create Sale Return"
+msgstr ""
+
+msgctxt "view:sale.complaint.action:"
+msgid "Amount"
+msgstr ""
+
+#, fuzzy
+msgctxt "view:sale.complaint:"
+msgid "Complaint"
+msgstr "Complaints"
+
+#, fuzzy
+msgctxt "view:sale.complaint:"
+msgid "Process"
+msgstr "Process"
diff --git a/modules/sale_complaint/message.xml b/modules/sale_complaint/message.xml
new file mode 100644
index 0000000000..11a58a56c1
--- /dev/null
+++ b/modules/sale_complaint/message.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+ To delete complaint "%(complaint)s" you must reset it to draft state.
+
+
+ You cannot delete action "%(action)s" because it has a result.
+
+
+
diff --git a/modules/sale_complaint/party.xml b/modules/sale_complaint/party.xml
new file mode 100644
index 0000000000..e5c6732c93
--- /dev/null
+++ b/modules/sale_complaint/party.xml
@@ -0,0 +1,12 @@
+
+
+
+
+
+ party.party
+
+ party_form
+
+
+
diff --git a/modules/sale_complaint/sale.py b/modules/sale_complaint/sale.py
new file mode 100644
index 0000000000..1f66b7ba1e
--- /dev/null
+++ b/modules/sale_complaint/sale.py
@@ -0,0 +1,80 @@
+# This file is part of Tryton. The COPYRIGHT file at the top level of
+# this repository contains the full copyright notices and license terms.
+
+from trytond import backend
+from trytond.pool import PoolMeta, Pool
+from trytond.model import fields
+from trytond.pyson import Eval, Id
+
+
+class Configuration(metaclass=PoolMeta):
+ __name__ = 'sale.configuration'
+
+ complaint_sequence = fields.MultiValue(fields.Many2One(
+ 'ir.sequence', "Complaint Sequence",
+ domain=[
+ ('sequence_type', '=',
+ Id('sale_complaint', 'sequence_type_complaint')),
+ ('company', 'in', [
+ Eval('context', {}).get('company', -1), None]),
+ ]))
+
+ @classmethod
+ def multivalue_model(cls, field):
+ pool = Pool()
+ if field == 'complaint_sequence':
+ return pool.get('sale.configuration.sequence')
+ return super(Configuration, cls).multivalue_model(field)
+
+ @classmethod
+ def default_complaint_sequence(cls, **pattern):
+ return cls.multivalue_model(
+ 'complaint_sequence').default_complaint_sequence()
+
+
+class ConfigurationSequence(metaclass=PoolMeta):
+ __name__ = 'sale.configuration.sequence'
+ complaint_sequence = fields.Many2One(
+ 'ir.sequence', "Complaint Sequence",
+ domain=[
+ ('sequence_type', '=',
+ Id('sale_complaint', 'sequence_type_complaint')),
+ ('company', 'in', [Eval('company', -1), None]),
+ ],
+ depends=['company'])
+
+ @classmethod
+ def __register__(cls, module_name):
+ exist = backend.TableHandler.table_exist(cls._table)
+ if exist:
+ table = cls.__table_handler__(module_name)
+ exist &= table.column_exist('complaint_sequence')
+
+ super(ConfigurationSequence, cls).__register__(module_name)
+
+ if not exist:
+ cls._migrate_property([], [], [])
+
+ @classmethod
+ def _migrate_property(cls, field_names, value_names, fields):
+ field_names.append('complaint_sequence')
+ value_names.append('complaint_sequence')
+ super(ConfigurationSequence, cls)._migrate_property(
+ field_names, value_names, fields)
+
+ @classmethod
+ def default_complaint_sequence(cls):
+ pool = Pool()
+ ModelData = pool.get('ir.model.data')
+ try:
+ return ModelData.get_id('sale_complaint', 'sequence_complaint')
+ except KeyError:
+ return None
+
+
+class Sale(metaclass=PoolMeta):
+ __name__ = 'sale.sale'
+
+ @classmethod
+ def _get_origin(cls):
+ return super(Sale, cls)._get_origin() + ['sale.complaint']
diff --git a/modules/sale_complaint/sale.xml b/modules/sale_complaint/sale.xml
new file mode 100644
index 0000000000..3ad0f35f0d
--- /dev/null
+++ b/modules/sale_complaint/sale.xml
@@ -0,0 +1,42 @@
+
+
+
+
+
+ tryton-sale-complaint
+ icons/tryton-sale-complaint.svg
+
+
+
+ sale.configuration
+
+ configuration_form
+
+
+
+ Customer Complaint
+
+
+
+
+
+
+
+
+
+
+
+ Customer Complaint
+
+
+
+
+ sale.sale
+
+ sale_form
+
+
+
diff --git a/modules/sale_complaint/setup.py b/modules/sale_complaint/setup.py
new file mode 100755
index 0000000000..ded0dc9ab9
--- /dev/null
+++ b/modules/sale_complaint/setup.py
@@ -0,0 +1,150 @@
+#!/usr/bin/env python3
+# This file is part of Tryton. The COPYRIGHT file at the top level of
+# this repository contains the full copyright notices and license terms.
+
+import io
+import os
+import re
+from configparser import ConfigParser
+from setuptools import setup, find_packages
+
+
+def read(fname):
+ return io.open(
+ os.path.join(os.path.dirname(__file__), fname),
+ 'r', encoding='utf-8').read()
+
+
+def get_require_version(name):
+ if minor_version % 2:
+ require = '%s >= %s.%s.dev0, < %s.%s'
+ else:
+ require = '%s >= %s.%s, < %s.%s'
+ require %= (name, major_version, minor_version,
+ major_version, minor_version + 1)
+ return require
+
+
+config = ConfigParser()
+config.read_file(open(os.path.join(os.path.dirname(__file__), 'tryton.cfg')))
+info = dict(config.items('tryton'))
+for key in ('depends', 'extras_depend', 'xml'):
+ if key in info:
+ info[key] = info[key].strip().splitlines()
+version = info.get('version', '0.0.1')
+major_version, minor_version, _ = version.split('.', 2)
+major_version = int(major_version)
+minor_version = int(minor_version)
+name = 'trytond_sale_complaint'
+
+download_url = 'http://downloads.tryton.org/%s.%s/' % (
+ major_version, minor_version)
+if minor_version % 2:
+ version = '%s.%s.dev0' % (major_version, minor_version)
+ download_url = (
+ 'hg+http://hg.tryton.org/modules/%s#egg=%s-%s' % (
+ name[8:], name, version))
+local_version = []
+if os.environ.get('CI_JOB_ID'):
+ local_version.append(os.environ['CI_JOB_ID'])
+else:
+ for build in ['CI_BUILD_NUMBER', 'CI_JOB_NUMBER']:
+ if os.environ.get(build):
+ local_version.append(os.environ[build])
+ else:
+ local_version = []
+ break
+if local_version:
+ version += '+' + '.'.join(local_version)
+
+requires = []
+for dep in info.get('depends', []):
+ if not re.match(r'(ir|res)(\W|$)', dep):
+ requires.append(get_require_version('trytond_%s' % dep))
+requires.append(get_require_version('trytond'))
+
+tests_require = [get_require_version('proteus')]
+dependency_links = []
+if minor_version % 2:
+ dependency_links.append(
+ 'https://trydevpi.tryton.org/?local_version='
+ + '.'.join(local_version))
+
+setup(name=name,
+ version=version,
+ description='Tryton module for sale complaint',
+ long_description=read('README.rst'),
+ author='Tryton',
+ author_email='bugs@tryton.org',
+ url='http://www.tryton.org/',
+ download_url=download_url,
+ project_urls={
+ "Bug Tracker": 'https://bugs.tryton.org/',
+ "Documentation": 'https://docs.tryton.org/',
+ "Forum": 'https://www.tryton.org/forum',
+ "Source Code": 'https://hg.tryton.org/modules/sale_complaint',
+ },
+ keywords='tryton sale customer complaint',
+ package_dir={'trytond.modules.sale_complaint': '.'},
+ packages=(
+ ['trytond.modules.sale_complaint']
+ + ['trytond.modules.sale_complaint.%s' % p for p in find_packages()]
+ ),
+ package_data={
+ 'trytond.modules.sale_complaint': (info.get('xml', [])
+ + ['tryton.cfg', 'view/*.xml', 'locale/*.po', 'icons/*.svg',
+ 'tests/*.rst']),
+ },
+ classifiers=[
+ 'Development Status :: 5 - Production/Stable',
+ 'Environment :: Plugins',
+ 'Framework :: Tryton',
+ 'Intended Audience :: Developers',
+ 'Intended Audience :: Financial and Insurance Industry',
+ 'Intended Audience :: Legal Industry',
+ 'License :: OSI Approved :: '
+ 'GNU General Public License v3 or later (GPLv3+)',
+ 'Natural Language :: Bulgarian',
+ 'Natural Language :: Catalan',
+ 'Natural Language :: Chinese (Simplified)',
+ 'Natural Language :: Czech',
+ 'Natural Language :: Dutch',
+ 'Natural Language :: English',
+ 'Natural Language :: Finnish',
+ 'Natural Language :: French',
+ 'Natural Language :: German',
+ 'Natural Language :: Hungarian',
+ 'Natural Language :: Indonesian',
+ 'Natural Language :: Italian',
+ 'Natural Language :: Persian',
+ 'Natural Language :: Polish',
+ 'Natural Language :: Portuguese (Brazilian)',
+ 'Natural Language :: Romanian',
+ 'Natural Language :: Russian',
+ 'Natural Language :: Slovenian',
+ 'Natural Language :: Spanish',
+ 'Natural Language :: Turkish',
+ 'Operating System :: OS Independent',
+ 'Programming Language :: Python :: 3',
+ 'Programming Language :: Python :: 3.6',
+ 'Programming Language :: Python :: 3.7',
+ 'Programming Language :: Python :: 3.8',
+ 'Programming Language :: Python :: 3.9',
+ 'Programming Language :: Python :: Implementation :: CPython',
+ 'Programming Language :: Python :: Implementation :: PyPy',
+ 'Topic :: Office/Business',
+ 'Topic :: Office/Business :: Financial :: Accounting',
+ ],
+ license='GPL-3',
+ python_requires='>=3.6',
+ install_requires=requires,
+ dependency_links=dependency_links,
+ zip_safe=False,
+ entry_points="""
+ [trytond.modules]
+ sale_complaint = trytond.modules.sale_complaint
+ """,
+ test_suite='tests',
+ test_loader='trytond.test_loader:Loader',
+ tests_require=tests_require,
+ )
diff --git a/modules/sale_complaint/tests/__init__.py b/modules/sale_complaint/tests/__init__.py
new file mode 100644
index 0000000000..b493bc1ff4
--- /dev/null
+++ b/modules/sale_complaint/tests/__init__.py
@@ -0,0 +1,9 @@
+# This file is part of Tryton. The COPYRIGHT file at the top level of
+# this repository contains the full copyright notices and license terms.
+
+try:
+ from trytond.modules.sale_complaint.tests.test_sale_complaint import suite
+except ImportError:
+ from .test_sale_complaint import suite
+
+__all__ = ['suite']
diff --git a/modules/sale_complaint/tests/scenario_sale_complaint.rst b/modules/sale_complaint/tests/scenario_sale_complaint.rst
new file mode 100644
index 0000000000..eba11eb55f
--- /dev/null
+++ b/modules/sale_complaint/tests/scenario_sale_complaint.rst
@@ -0,0 +1,279 @@
+=======================
+Sale Complaint Scenario
+=======================
+
+Imports::
+
+ >>> from decimal import Decimal
+ >>> from proteus import Model, Wizard, Report
+ >>> from trytond.tests.tools import activate_modules
+ >>> from trytond.modules.company.tests.tools import create_company, \
+ ... get_company
+ >>> from trytond.modules.account.tests.tools import create_fiscalyear, \
+ ... create_chart, get_accounts
+ >>> from trytond.modules.account_invoice.tests.tools import \
+ ... set_fiscalyear_invoice_sequences, create_payment_term
+
+Activate modules::
+
+ >>> config = activate_modules('sale_complaint')
+
+Create company::
+
+ >>> _ = create_company()
+ >>> company = get_company()
+
+Create fiscal year::
+
+ >>> fiscalyear = set_fiscalyear_invoice_sequences(
+ ... create_fiscalyear(company))
+ >>> fiscalyear.click('create_period')
+
+Create chart of accounts::
+
+ >>> _ = create_chart(company)
+ >>> accounts = get_accounts(company)
+ >>> revenue = accounts['revenue']
+ >>> expense = accounts['expense']
+
+Create parties::
+
+ >>> Party = Model.get('party.party')
+ >>> customer = Party(name='Customer')
+ >>> customer.save()
+
+Create complaint type::
+
+ >>> Type = Model.get('sale.complaint.type')
+ >>> IrModel = Model.get('ir.model')
+ >>> sale_type = Type(name='Sale')
+ >>> sale_type.origin, = IrModel.find([('model', '=', 'sale.sale')])
+ >>> sale_type.save()
+ >>> sale_line_type = Type(name='Sale Line')
+ >>> sale_line_type.origin, = IrModel.find([('model', '=', 'sale.line')])
+ >>> sale_line_type.save()
+ >>> invoice_type = Type(name='Invoice')
+ >>> invoice_type.origin, = IrModel.find(
+ ... [('model', '=', 'account.invoice')])
+ >>> invoice_type.save()
+ >>> invoice_line_type = Type(name='Invoice Line')
+ >>> invoice_line_type.origin, = IrModel.find(
+ ... [('model', '=', 'account.invoice.line')])
+ >>> invoice_line_type.save()
+
+Create account category::
+
+ >>> ProductCategory = Model.get('product.category')
+ >>> account_category = ProductCategory(name="Account Category")
+ >>> account_category.accounting = True
+ >>> account_category.account_expense = expense
+ >>> account_category.account_revenue = revenue
+ >>> account_category.save()
+
+Create product::
+
+ >>> ProductUom = Model.get('product.uom')
+ >>> unit, = ProductUom.find([('name', '=', 'Unit')])
+ >>> ProductTemplate = Model.get('product.template')
+
+ >>> template = ProductTemplate()
+ >>> template.name = 'product'
+ >>> template.default_uom = unit
+ >>> template.type = 'goods'
+ >>> template.salable = True
+ >>> template.list_price = Decimal('10')
+ >>> template.account_category = account_category
+ >>> template.save()
+ >>> product, = template.products
+
+Create payment term::
+
+ >>> payment_term = create_payment_term()
+ >>> payment_term.save()
+
+Sale 5 products::
+
+ >>> Sale = Model.get('sale.sale')
+ >>> sale = Sale()
+ >>> sale.party = customer
+ >>> sale.payment_term = payment_term
+ >>> sale.invoice_method = 'order'
+ >>> sale_line = sale.lines.new()
+ >>> sale_line.product = product
+ >>> sale_line.quantity = 3
+ >>> sale_line = sale.lines.new()
+ >>> sale_line.product = product
+ >>> sale_line.quantity = 2
+ >>> sale.click('quote')
+ >>> sale.click('confirm')
+ >>> sale.untaxed_amount
+ Decimal('50.00')
+
+Post the invoice::
+
+ >>> invoice, = sale.invoices
+ >>> invoice.click('post')
+
+Create a complaint to return the sale::
+
+ >>> Complaint = Model.get('sale.complaint')
+ >>> complaint = Complaint()
+ >>> complaint.customer = customer
+ >>> complaint.type = sale_type
+ >>> complaint.origin = sale
+ >>> action = complaint.actions.new()
+ >>> action.action = 'sale_return'
+ >>> action.amount
+ Decimal('50.00')
+ >>> complaint.save()
+ >>> complaint.state
+ 'draft'
+ >>> complaint.click('wait')
+ >>> complaint.state
+ 'waiting'
+ >>> complaint.click('approve')
+ >>> complaint.state
+ 'done'
+ >>> action, = complaint.actions
+ >>> return_sale = action.result
+ >>> len(return_sale.lines)
+ 2
+ >>> sum(l.quantity for l in return_sale.lines)
+ -5.0
+
+Create a complaint to return partially the sale::
+
+ >>> Complaint = Model.get('sale.complaint')
+ >>> complaint = Complaint()
+ >>> complaint.customer = customer
+ >>> complaint.type = sale_type
+ >>> complaint.origin = sale
+ >>> action = complaint.actions.new()
+ >>> action.action = 'sale_return'
+ >>> sale_line = action.sale_lines.new()
+ >>> sale_line.line = sale.lines[0]
+ >>> sale_line.quantity = 1
+ >>> sale_line.unit_price = Decimal('5')
+ >>> sale_line = action.sale_lines.new()
+ >>> sale_line.line = sale.lines[1]
+ >>> action.amount
+ Decimal('25.00')
+ >>> complaint.save()
+ >>> complaint.state
+ 'draft'
+ >>> complaint.click('wait')
+ >>> complaint.state
+ 'waiting'
+ >>> complaint.click('approve')
+ >>> complaint.state
+ 'done'
+ >>> action, = complaint.actions
+ >>> return_sale = action.result
+ >>> len(return_sale.lines)
+ 2
+ >>> sum(l.quantity for l in return_sale.lines)
+ -3.0
+ >>> return_sale.total_amount
+ Decimal('-25.00')
+
+Create a complaint to return a sale line::
+
+ >>> complaint = Complaint()
+ >>> complaint.customer = customer
+ >>> complaint.type = sale_line_type
+ >>> complaint.origin = sale.lines[0]
+ >>> action = complaint.actions.new()
+ >>> action.action = 'sale_return'
+ >>> action.quantity = 1
+ >>> action.amount
+ Decimal('10.00')
+ >>> complaint.click('wait')
+ >>> complaint.click('approve')
+ >>> complaint.state
+ 'done'
+ >>> action, = complaint.actions
+ >>> return_sale = action.result
+ >>> return_line, = return_sale.lines
+ >>> return_line.quantity
+ -1.0
+
+Create a complaint to credit the invoice::
+
+ >>> complaint = Complaint()
+ >>> complaint.customer = customer
+ >>> complaint.type = invoice_type
+ >>> complaint.origin = invoice
+ >>> action = complaint.actions.new()
+ >>> action.action = 'credit_note'
+ >>> action.amount
+ Decimal('50.00')
+ >>> complaint.click('wait')
+ >>> complaint.click('approve')
+ >>> complaint.state
+ 'done'
+ >>> action, = complaint.actions
+ >>> credit_note = action.result
+ >>> credit_note.type
+ 'out'
+ >>> len(credit_note.lines)
+ 4
+ >>> sum(l.quantity for l in credit_note.lines)
+ 0.0
+ >>> credit_note.total_amount
+ Decimal('-50.00')
+
+Create a complaint to credit partially the invoice::
+
+ >>> complaint = Complaint()
+ >>> complaint.customer = customer
+ >>> complaint.type = invoice_type
+ >>> complaint.origin = invoice
+ >>> action = complaint.actions.new()
+ >>> action.action = 'credit_note'
+ >>> invoice_line = action.invoice_lines.new()
+ >>> invoice_line.line = invoice.lines[0]
+ >>> invoice_line.quantity = 1
+ >>> invoice_line.unit_price = Decimal('5')
+ >>> invoice_line = action.invoice_lines.new()
+ >>> invoice_line.line = invoice.lines[1]
+ >>> invoice_line.quantity = 1
+ >>> action.amount
+ Decimal('15.00')
+ >>> complaint.click('wait')
+ >>> complaint.click('approve')
+ >>> complaint.state
+ 'done'
+ >>> action, = complaint.actions
+ >>> credit_note = action.result
+ >>> credit_note.type
+ 'out'
+ >>> len(credit_note.lines)
+ 4
+ >>> sum(l.quantity for l in credit_note.lines)
+ 0.0
+ >>> credit_note.total_amount
+ Decimal('-15.00')
+
+Create a complaint to credit a invoice line::
+
+ >>> complaint = Complaint()
+ >>> complaint.customer = customer
+ >>> complaint.type = invoice_line_type
+ >>> complaint.origin = invoice.lines[0]
+ >>> action = complaint.actions.new()
+ >>> action.action = 'credit_note'
+ >>> action.quantity = 1
+ >>> action.amount
+ Decimal('10.00')
+ >>> complaint.click('wait')
+ >>> complaint.click('approve')
+ >>> complaint.state
+ 'done'
+ >>> action, = complaint.actions
+ >>> credit_note = action.result
+ >>> credit_note.type
+ 'out'
+ >>> len(credit_note.lines)
+ 2
+ >>> sum(l.quantity for l in credit_note.lines)
+ 0.0
diff --git a/modules/sale_complaint/tests/test_sale_complaint.py b/modules/sale_complaint/tests/test_sale_complaint.py
new file mode 100644
index 0000000000..d1f7c6ca34
--- /dev/null
+++ b/modules/sale_complaint/tests/test_sale_complaint.py
@@ -0,0 +1,26 @@
+# This file is part of Tryton. The COPYRIGHT file at the top level of
+# this repository contains the full copyright notices and license terms.
+import unittest
+import doctest
+import trytond.tests.test_tryton
+from trytond.tests.test_tryton import ModuleTestCase
+from trytond.tests.test_tryton import doctest_teardown
+from trytond.tests.test_tryton import doctest_checker
+
+from trytond.modules.company.tests import CompanyTestMixin
+
+
+class SaleComplaintTestCase(CompanyTestMixin, ModuleTestCase):
+ 'Test Sale Complaint module'
+ module = 'sale_complaint'
+
+
+def suite():
+ suite = trytond.tests.test_tryton.suite()
+ suite.addTests(
+ unittest.TestLoader().loadTestsFromTestCase(SaleComplaintTestCase))
+ suite.addTests(doctest.DocFileSuite('scenario_sale_complaint.rst',
+ tearDown=doctest_teardown, encoding='utf-8',
+ checker=doctest_checker,
+ optionflags=doctest.REPORT_ONLY_FIRST_FAILURE))
+ return suite
diff --git a/modules/sale_complaint/tox.ini b/modules/sale_complaint/tox.ini
new file mode 100644
index 0000000000..197496c0cb
--- /dev/null
+++ b/modules/sale_complaint/tox.ini
@@ -0,0 +1,15 @@
+[tox]
+envlist = {py36,py37,py38,py39}-{sqlite,postgresql},pypy3-{sqlite,postgresql}
+
+[testenv]
+commands = {envpython} setup.py test
+deps =
+ {py36,py37,py38,py39}-postgresql: psycopg2 >= 2.5
+ pypy3-postgresql: psycopg2cffi >= 2.5
+ py36-sqlite: sqlitebck
+setenv =
+ sqlite: TRYTOND_DATABASE_URI={env:SQLITE_URI:sqlite://}
+ postgresql: TRYTOND_DATABASE_URI={env:POSTGRESQL_URI:postgresql://}
+ sqlite: DB_NAME={env:SQLITE_NAME::memory:}
+ postgresql: DB_NAME={env:POSTGRESQL_NAME:test}
+install_command = pip install --pre --find-links https://trydevpi.tryton.org/?local_version={env:CI_JOB_ID:{env:CI_BUILD_NUMBER}.{env:CI_JOB_NUMBER}} {opts} {packages}
diff --git a/modules/sale_complaint/tryton.cfg b/modules/sale_complaint/tryton.cfg
new file mode 100644
index 0000000000..292629cd96
--- /dev/null
+++ b/modules/sale_complaint/tryton.cfg
@@ -0,0 +1,13 @@
+[tryton]
+version=6.0.3
+depends:
+ account_invoice
+ company
+ ir
+ party
+ sale
+xml:
+ complaint.xml
+ sale.xml
+ party.xml
+ message.xml
diff --git a/modules/sale_complaint/view/action_form.xml b/modules/sale_complaint/view/action_form.xml
new file mode 100644
index 0000000000..d22504cb61
--- /dev/null
+++ b/modules/sale_complaint/view/action_form.xml
@@ -0,0 +1,23 @@
+
+
+
diff --git a/modules/sale_complaint/view/action_line_form.xml b/modules/sale_complaint/view/action_line_form.xml
new file mode 100644
index 0000000000..91ac13ab43
--- /dev/null
+++ b/modules/sale_complaint/view/action_line_form.xml
@@ -0,0 +1,16 @@
+
+
+
diff --git a/modules/sale_complaint/view/action_line_list.xml b/modules/sale_complaint/view/action_line_list.xml
new file mode 100644
index 0000000000..8ab6709149
--- /dev/null
+++ b/modules/sale_complaint/view/action_line_list.xml
@@ -0,0 +1,10 @@
+
+
+
+
+
+
+
+
+
diff --git a/modules/sale_complaint/view/action_list.xml b/modules/sale_complaint/view/action_list.xml
new file mode 100644
index 0000000000..8d40cf1f7d
--- /dev/null
+++ b/modules/sale_complaint/view/action_list.xml
@@ -0,0 +1,9 @@
+
+
+
+
+
+
+
+
diff --git a/modules/sale_complaint/view/complaint_form.xml b/modules/sale_complaint/view/complaint_form.xml
new file mode 100644
index 0000000000..4886b5dd5f
--- /dev/null
+++ b/modules/sale_complaint/view/complaint_form.xml
@@ -0,0 +1,41 @@
+
+
+
diff --git a/modules/sale_complaint/view/complaint_list.xml b/modules/sale_complaint/view/complaint_list.xml
new file mode 100644
index 0000000000..9285b7c8b9
--- /dev/null
+++ b/modules/sale_complaint/view/complaint_list.xml
@@ -0,0 +1,12 @@
+
+
+
+
+
+
+
+
+
+
+
diff --git a/modules/sale_complaint/view/configuration_form.xml b/modules/sale_complaint/view/configuration_form.xml
new file mode 100644
index 0000000000..ce1961ae99
--- /dev/null
+++ b/modules/sale_complaint/view/configuration_form.xml
@@ -0,0 +1,9 @@
+
+
+
+
+
+
+
+
diff --git a/modules/sale_complaint/view/party_form.xml b/modules/sale_complaint/view/party_form.xml
new file mode 100644
index 0000000000..6b224ea84d
--- /dev/null
+++ b/modules/sale_complaint/view/party_form.xml
@@ -0,0 +1,8 @@
+
+
+
+
+
+
+
diff --git a/modules/sale_complaint/view/sale_form.xml b/modules/sale_complaint/view/sale_form.xml
new file mode 100644
index 0000000000..54d3d2f36e
--- /dev/null
+++ b/modules/sale_complaint/view/sale_form.xml
@@ -0,0 +1,8 @@
+
+
+
+
+
+
+
diff --git a/modules/sale_complaint/view/type_form.xml b/modules/sale_complaint/view/type_form.xml
new file mode 100644
index 0000000000..05837f25b1
--- /dev/null
+++ b/modules/sale_complaint/view/type_form.xml
@@ -0,0 +1,12 @@
+
+
+
diff --git a/modules/sale_complaint/view/type_list.xml b/modules/sale_complaint/view/type_list.xml
new file mode 100644
index 0000000000..78c5ce1d5f
--- /dev/null
+++ b/modules/sale_complaint/view/type_list.xml
@@ -0,0 +1,7 @@
+
+
+
+
+
+
diff --git a/modules/sale_credit_limit/.drone.yml b/modules/sale_credit_limit/.drone.yml
new file mode 100644
index 0000000000..2049d30a49
--- /dev/null
+++ b/modules/sale_credit_limit/.drone.yml
@@ -0,0 +1,68 @@
+clone:
+ hg:
+ image: plugins/hg
+ environment:
+ - HG_SHARE_POOL=/root/.cache/hg
+ volumes:
+ - cache:/root/.cache
+
+pipeline:
+ tox:
+ image: ${IMAGE}
+ environment:
+ - CFLAGS=-O0
+ - DB_CACHE=/cache
+ - TOX_TESTENV_PASSENV=CFLAGS DB_CACHE CI_BUILD_NUMBER CI_JOB_NUMBER CI_JOB_ID
+ - POSTGRESQL_URI=postgresql://postgres@postgresql:5432/
+ commands:
+ - echo "[extensions]" >> /root/.hgrc
+ - echo "hgext.share =" >> /root/.hgrc
+ - echo "[share]" >> /root/.hgrc
+ - echo "pool = /root/.cache/hg" >> /root/.hgrc
+ - pip install tox
+ - tox -e "${TOXENV}-${DATABASE}"
+ volumes:
+ - cache:/root/.cache
+ check_dist:
+ image: ${IMAGE}
+ commands:
+ - pip install twine
+ - python setup.py sdist
+ - twine check dist/*
+
+services:
+ postgresql:
+ image: postgres
+ environment:
+ - POSTGRES_HOST_AUTH_METHOD=trust
+ command: "-c fsync=off -c synchronous_commit=off -c full_page_writes=off"
+ when:
+ matrix:
+ DATABASE: postgresql
+
+matrix:
+ include:
+ - IMAGE: python:3.6
+ TOXENV: py36
+ DATABASE: sqlite
+ - IMAGE: python:3.6
+ TOXENV: py36
+ DATABASE: postgresql
+ - IMAGE: python:3.7
+ TOXENV: py37
+ DATABASE: sqlite
+ - IMAGE: python:3.7
+ TOXENV: py37
+ DATABASE: postgresql
+ - IMAGE: python:3.8
+ TOXENV: py38
+ DATABASE: sqlite
+ - IMAGE: python:3.8
+ TOXENV: py38
+ DATABASE: postgresql
+ - IMAGE: python:3.9
+ TOXENV: py39
+ DATABASE: sqlite
+ - IMAGE: python:3.9
+ TOXENV: py39
+ DATABASE: postgresql
diff --git a/modules/sale_credit_limit/.flake8 b/modules/sale_credit_limit/.flake8
new file mode 100644
index 0000000000..fa6b4f66d1
--- /dev/null
+++ b/modules/sale_credit_limit/.flake8
@@ -0,0 +1,2 @@
+[flake8]
+ignore=E123,E124,E126,E128,E741,W503
diff --git a/modules/sale_credit_limit/CHANGELOG b/modules/sale_credit_limit/CHANGELOG
new file mode 100644
index 0000000000..d2f2ad2c72
--- /dev/null
+++ b/modules/sale_credit_limit/CHANGELOG
@@ -0,0 +1,48 @@
+Version 6.0.0 - 2021-05-03
+* Bug fixes (see mercurial logs for details)
+
+Version 5.8.0 - 2020-11-02
+* Bug fixes (see mercurial logs for details)
+* Remove support for Python 3.5
+
+Version 5.6.0 - 2020-05-04
+* Bug fixes (see mercurial logs for details)
+
+Version 5.4.0 - 2019-11-04
+* Bug fixes (see mercurial logs for details)
+
+Version 5.2.0 - 2019-05-06
+* Bug fixes (see mercurial logs for details)
+
+Version 5.0.0 - 2018-10-01
+* Bug fixes (see mercurial logs for details)
+* Remove support for Python 2.7
+
+Version 4.8.0 - 2018-04-23
+* Bug fixes (see mercurial logs for details)
+* Base sale credit amount on quantity
+
+Version 4.6.0 - 2017-10-30
+* Bug fixes (see mercurial logs for details)
+
+Version 4.4.0 - 2017-05-01
+* Bug fixes (see mercurial logs for details)
+
+Version 4.2.0 - 2016-11-28
+* Bug fixes (see mercurial logs for details)
+
+Version 4.0.0 - 2016-05-02
+* Bug fixes (see mercurial logs for details)
+* Add Python3 support
+
+Version 3.8.0 - 2015-11-02
+* Bug fixes (see mercurial logs for details)
+
+Version 3.6.0 - 2015-04-20
+* Bug fixes (see mercurial logs for details)
+* Add support for PyPy
+Version 3.4.0 - 2014-10-20
+* Bug fixes (see mercurial logs for details)
+
+Version 3.2.0 - 2014-04-21
+* Initial release
diff --git a/modules/sale_credit_limit/COPYRIGHT b/modules/sale_credit_limit/COPYRIGHT
new file mode 100644
index 0000000000..0a72968a7c
--- /dev/null
+++ b/modules/sale_credit_limit/COPYRIGHT
@@ -0,0 +1,15 @@
+Copyright (C) 2011-2021 Cédric Krier.
+Copyright (C) 2011-2021 B2CK SPRL.
+
+This program is free software: you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation, either version 3 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program. If not, see .
diff --git a/modules/sale_credit_limit/LICENSE b/modules/sale_credit_limit/LICENSE
new file mode 100644
index 0000000000..94a9ed024d
--- /dev/null
+++ b/modules/sale_credit_limit/LICENSE
@@ -0,0 +1,674 @@
+ GNU GENERAL PUBLIC LICENSE
+ Version 3, 29 June 2007
+
+ Copyright (C) 2007 Free Software Foundation, Inc.
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+ Preamble
+
+ The GNU General Public License is a free, copyleft license for
+software and other kinds of works.
+
+ The licenses for most software and other practical works are designed
+to take away your freedom to share and change the works. By contrast,
+the GNU General Public License is intended to guarantee your freedom to
+share and change all versions of a program--to make sure it remains free
+software for all its users. We, the Free Software Foundation, use the
+GNU General Public License for most of our software; it applies also to
+any other work released this way by its authors. You can apply it to
+your programs, too.
+
+ When we speak of free software, we are referring to freedom, not
+price. Our General Public Licenses are designed to make sure that you
+have the freedom to distribute copies of free software (and charge for
+them if you wish), that you receive source code or can get it if you
+want it, that you can change the software or use pieces of it in new
+free programs, and that you know you can do these things.
+
+ To protect your rights, we need to prevent others from denying you
+these rights or asking you to surrender the rights. Therefore, you have
+certain responsibilities if you distribute copies of the software, or if
+you modify it: responsibilities to respect the freedom of others.
+
+ For example, if you distribute copies of such a program, whether
+gratis or for a fee, you must pass on to the recipients the same
+freedoms that you received. You must make sure that they, too, receive
+or can get the source code. And you must show them these terms so they
+know their rights.
+
+ Developers that use the GNU GPL protect your rights with two steps:
+(1) assert copyright on the software, and (2) offer you this License
+giving you legal permission to copy, distribute and/or modify it.
+
+ For the developers' and authors' protection, the GPL clearly explains
+that there is no warranty for this free software. For both users' and
+authors' sake, the GPL requires that modified versions be marked as
+changed, so that their problems will not be attributed erroneously to
+authors of previous versions.
+
+ Some devices are designed to deny users access to install or run
+modified versions of the software inside them, although the manufacturer
+can do so. This is fundamentally incompatible with the aim of
+protecting users' freedom to change the software. The systematic
+pattern of such abuse occurs in the area of products for individuals to
+use, which is precisely where it is most unacceptable. Therefore, we
+have designed this version of the GPL to prohibit the practice for those
+products. If such problems arise substantially in other domains, we
+stand ready to extend this provision to those domains in future versions
+of the GPL, as needed to protect the freedom of users.
+
+ Finally, every program is threatened constantly by software patents.
+States should not allow patents to restrict development and use of
+software on general-purpose computers, but in those that do, we wish to
+avoid the special danger that patents applied to a free program could
+make it effectively proprietary. To prevent this, the GPL assures that
+patents cannot be used to render the program non-free.
+
+ The precise terms and conditions for copying, distribution and
+modification follow.
+
+ TERMS AND CONDITIONS
+
+ 0. Definitions.
+
+ "This License" refers to version 3 of the GNU General Public License.
+
+ "Copyright" also means copyright-like laws that apply to other kinds of
+works, such as semiconductor masks.
+
+ "The Program" refers to any copyrightable work licensed under this
+License. Each licensee is addressed as "you". "Licensees" and
+"recipients" may be individuals or organizations.
+
+ To "modify" a work means to copy from or adapt all or part of the work
+in a fashion requiring copyright permission, other than the making of an
+exact copy. The resulting work is called a "modified version" of the
+earlier work or a work "based on" the earlier work.
+
+ A "covered work" means either the unmodified Program or a work based
+on the Program.
+
+ To "propagate" a work means to do anything with it that, without
+permission, would make you directly or secondarily liable for
+infringement under applicable copyright law, except executing it on a
+computer or modifying a private copy. Propagation includes copying,
+distribution (with or without modification), making available to the
+public, and in some countries other activities as well.
+
+ To "convey" a work means any kind of propagation that enables other
+parties to make or receive copies. Mere interaction with a user through
+a computer network, with no transfer of a copy, is not conveying.
+
+ An interactive user interface displays "Appropriate Legal Notices"
+to the extent that it includes a convenient and prominently visible
+feature that (1) displays an appropriate copyright notice, and (2)
+tells the user that there is no warranty for the work (except to the
+extent that warranties are provided), that licensees may convey the
+work under this License, and how to view a copy of this License. If
+the interface presents a list of user commands or options, such as a
+menu, a prominent item in the list meets this criterion.
+
+ 1. Source Code.
+
+ The "source code" for a work means the preferred form of the work
+for making modifications to it. "Object code" means any non-source
+form of a work.
+
+ A "Standard Interface" means an interface that either is an official
+standard defined by a recognized standards body, or, in the case of
+interfaces specified for a particular programming language, one that
+is widely used among developers working in that language.
+
+ The "System Libraries" of an executable work include anything, other
+than the work as a whole, that (a) is included in the normal form of
+packaging a Major Component, but which is not part of that Major
+Component, and (b) serves only to enable use of the work with that
+Major Component, or to implement a Standard Interface for which an
+implementation is available to the public in source code form. A
+"Major Component", in this context, means a major essential component
+(kernel, window system, and so on) of the specific operating system
+(if any) on which the executable work runs, or a compiler used to
+produce the work, or an object code interpreter used to run it.
+
+ The "Corresponding Source" for a work in object code form means all
+the source code needed to generate, install, and (for an executable
+work) run the object code and to modify the work, including scripts to
+control those activities. However, it does not include the work's
+System Libraries, or general-purpose tools or generally available free
+programs which are used unmodified in performing those activities but
+which are not part of the work. For example, Corresponding Source
+includes interface definition files associated with source files for
+the work, and the source code for shared libraries and dynamically
+linked subprograms that the work is specifically designed to require,
+such as by intimate data communication or control flow between those
+subprograms and other parts of the work.
+
+ The Corresponding Source need not include anything that users
+can regenerate automatically from other parts of the Corresponding
+Source.
+
+ The Corresponding Source for a work in source code form is that
+same work.
+
+ 2. Basic Permissions.
+
+ All rights granted under this License are granted for the term of
+copyright on the Program, and are irrevocable provided the stated
+conditions are met. This License explicitly affirms your unlimited
+permission to run the unmodified Program. The output from running a
+covered work is covered by this License only if the output, given its
+content, constitutes a covered work. This License acknowledges your
+rights of fair use or other equivalent, as provided by copyright law.
+
+ You may make, run and propagate covered works that you do not
+convey, without conditions so long as your license otherwise remains
+in force. You may convey covered works to others for the sole purpose
+of having them make modifications exclusively for you, or provide you
+with facilities for running those works, provided that you comply with
+the terms of this License in conveying all material for which you do
+not control copyright. Those thus making or running the covered works
+for you must do so exclusively on your behalf, under your direction
+and control, on terms that prohibit them from making any copies of
+your copyrighted material outside their relationship with you.
+
+ Conveying under any other circumstances is permitted solely under
+the conditions stated below. Sublicensing is not allowed; section 10
+makes it unnecessary.
+
+ 3. Protecting Users' Legal Rights From Anti-Circumvention Law.
+
+ No covered work shall be deemed part of an effective technological
+measure under any applicable law fulfilling obligations under article
+11 of the WIPO copyright treaty adopted on 20 December 1996, or
+similar laws prohibiting or restricting circumvention of such
+measures.
+
+ When you convey a covered work, you waive any legal power to forbid
+circumvention of technological measures to the extent such circumvention
+is effected by exercising rights under this License with respect to
+the covered work, and you disclaim any intention to limit operation or
+modification of the work as a means of enforcing, against the work's
+users, your or third parties' legal rights to forbid circumvention of
+technological measures.
+
+ 4. Conveying Verbatim Copies.
+
+ You may convey verbatim copies of the Program's source code as you
+receive it, in any medium, provided that you conspicuously and
+appropriately publish on each copy an appropriate copyright notice;
+keep intact all notices stating that this License and any
+non-permissive terms added in accord with section 7 apply to the code;
+keep intact all notices of the absence of any warranty; and give all
+recipients a copy of this License along with the Program.
+
+ You may charge any price or no price for each copy that you convey,
+and you may offer support or warranty protection for a fee.
+
+ 5. Conveying Modified Source Versions.
+
+ You may convey a work based on the Program, or the modifications to
+produce it from the Program, in the form of source code under the
+terms of section 4, provided that you also meet all of these conditions:
+
+ a) The work must carry prominent notices stating that you modified
+ it, and giving a relevant date.
+
+ b) The work must carry prominent notices stating that it is
+ released under this License and any conditions added under section
+ 7. This requirement modifies the requirement in section 4 to
+ "keep intact all notices".
+
+ c) You must license the entire work, as a whole, under this
+ License to anyone who comes into possession of a copy. This
+ License will therefore apply, along with any applicable section 7
+ additional terms, to the whole of the work, and all its parts,
+ regardless of how they are packaged. This License gives no
+ permission to license the work in any other way, but it does not
+ invalidate such permission if you have separately received it.
+
+ d) If the work has interactive user interfaces, each must display
+ Appropriate Legal Notices; however, if the Program has interactive
+ interfaces that do not display Appropriate Legal Notices, your
+ work need not make them do so.
+
+ A compilation of a covered work with other separate and independent
+works, which are not by their nature extensions of the covered work,
+and which are not combined with it such as to form a larger program,
+in or on a volume of a storage or distribution medium, is called an
+"aggregate" if the compilation and its resulting copyright are not
+used to limit the access or legal rights of the compilation's users
+beyond what the individual works permit. Inclusion of a covered work
+in an aggregate does not cause this License to apply to the other
+parts of the aggregate.
+
+ 6. Conveying Non-Source Forms.
+
+ You may convey a covered work in object code form under the terms
+of sections 4 and 5, provided that you also convey the
+machine-readable Corresponding Source under the terms of this License,
+in one of these ways:
+
+ a) Convey the object code in, or embodied in, a physical product
+ (including a physical distribution medium), accompanied by the
+ Corresponding Source fixed on a durable physical medium
+ customarily used for software interchange.
+
+ b) Convey the object code in, or embodied in, a physical product
+ (including a physical distribution medium), accompanied by a
+ written offer, valid for at least three years and valid for as
+ long as you offer spare parts or customer support for that product
+ model, to give anyone who possesses the object code either (1) a
+ copy of the Corresponding Source for all the software in the
+ product that is covered by this License, on a durable physical
+ medium customarily used for software interchange, for a price no
+ more than your reasonable cost of physically performing this
+ conveying of source, or (2) access to copy the
+ Corresponding Source from a network server at no charge.
+
+ c) Convey individual copies of the object code with a copy of the
+ written offer to provide the Corresponding Source. This
+ alternative is allowed only occasionally and noncommercially, and
+ only if you received the object code with such an offer, in accord
+ with subsection 6b.
+
+ d) Convey the object code by offering access from a designated
+ place (gratis or for a charge), and offer equivalent access to the
+ Corresponding Source in the same way through the same place at no
+ further charge. You need not require recipients to copy the
+ Corresponding Source along with the object code. If the place to
+ copy the object code is a network server, the Corresponding Source
+ may be on a different server (operated by you or a third party)
+ that supports equivalent copying facilities, provided you maintain
+ clear directions next to the object code saying where to find the
+ Corresponding Source. Regardless of what server hosts the
+ Corresponding Source, you remain obligated to ensure that it is
+ available for as long as needed to satisfy these requirements.
+
+ e) Convey the object code using peer-to-peer transmission, provided
+ you inform other peers where the object code and Corresponding
+ Source of the work are being offered to the general public at no
+ charge under subsection 6d.
+
+ A separable portion of the object code, whose source code is excluded
+from the Corresponding Source as a System Library, need not be
+included in conveying the object code work.
+
+ A "User Product" is either (1) a "consumer product", which means any
+tangible personal property which is normally used for personal, family,
+or household purposes, or (2) anything designed or sold for incorporation
+into a dwelling. In determining whether a product is a consumer product,
+doubtful cases shall be resolved in favor of coverage. For a particular
+product received by a particular user, "normally used" refers to a
+typical or common use of that class of product, regardless of the status
+of the particular user or of the way in which the particular user
+actually uses, or expects or is expected to use, the product. A product
+is a consumer product regardless of whether the product has substantial
+commercial, industrial or non-consumer uses, unless such uses represent
+the only significant mode of use of the product.
+
+ "Installation Information" for a User Product means any methods,
+procedures, authorization keys, or other information required to install
+and execute modified versions of a covered work in that User Product from
+a modified version of its Corresponding Source. The information must
+suffice to ensure that the continued functioning of the modified object
+code is in no case prevented or interfered with solely because
+modification has been made.
+
+ If you convey an object code work under this section in, or with, or
+specifically for use in, a User Product, and the conveying occurs as
+part of a transaction in which the right of possession and use of the
+User Product is transferred to the recipient in perpetuity or for a
+fixed term (regardless of how the transaction is characterized), the
+Corresponding Source conveyed under this section must be accompanied
+by the Installation Information. But this requirement does not apply
+if neither you nor any third party retains the ability to install
+modified object code on the User Product (for example, the work has
+been installed in ROM).
+
+ The requirement to provide Installation Information does not include a
+requirement to continue to provide support service, warranty, or updates
+for a work that has been modified or installed by the recipient, or for
+the User Product in which it has been modified or installed. Access to a
+network may be denied when the modification itself materially and
+adversely affects the operation of the network or violates the rules and
+protocols for communication across the network.
+
+ Corresponding Source conveyed, and Installation Information provided,
+in accord with this section must be in a format that is publicly
+documented (and with an implementation available to the public in
+source code form), and must require no special password or key for
+unpacking, reading or copying.
+
+ 7. Additional Terms.
+
+ "Additional permissions" are terms that supplement the terms of this
+License by making exceptions from one or more of its conditions.
+Additional permissions that are applicable to the entire Program shall
+be treated as though they were included in this License, to the extent
+that they are valid under applicable law. If additional permissions
+apply only to part of the Program, that part may be used separately
+under those permissions, but the entire Program remains governed by
+this License without regard to the additional permissions.
+
+ When you convey a copy of a covered work, you may at your option
+remove any additional permissions from that copy, or from any part of
+it. (Additional permissions may be written to require their own
+removal in certain cases when you modify the work.) You may place
+additional permissions on material, added by you to a covered work,
+for which you have or can give appropriate copyright permission.
+
+ Notwithstanding any other provision of this License, for material you
+add to a covered work, you may (if authorized by the copyright holders of
+that material) supplement the terms of this License with terms:
+
+ a) Disclaiming warranty or limiting liability differently from the
+ terms of sections 15 and 16 of this License; or
+
+ b) Requiring preservation of specified reasonable legal notices or
+ author attributions in that material or in the Appropriate Legal
+ Notices displayed by works containing it; or
+
+ c) Prohibiting misrepresentation of the origin of that material, or
+ requiring that modified versions of such material be marked in
+ reasonable ways as different from the original version; or
+
+ d) Limiting the use for publicity purposes of names of licensors or
+ authors of the material; or
+
+ e) Declining to grant rights under trademark law for use of some
+ trade names, trademarks, or service marks; or
+
+ f) Requiring indemnification of licensors and authors of that
+ material by anyone who conveys the material (or modified versions of
+ it) with contractual assumptions of liability to the recipient, for
+ any liability that these contractual assumptions directly impose on
+ those licensors and authors.
+
+ All other non-permissive additional terms are considered "further
+restrictions" within the meaning of section 10. If the Program as you
+received it, or any part of it, contains a notice stating that it is
+governed by this License along with a term that is a further
+restriction, you may remove that term. If a license document contains
+a further restriction but permits relicensing or conveying under this
+License, you may add to a covered work material governed by the terms
+of that license document, provided that the further restriction does
+not survive such relicensing or conveying.
+
+ If you add terms to a covered work in accord with this section, you
+must place, in the relevant source files, a statement of the
+additional terms that apply to those files, or a notice indicating
+where to find the applicable terms.
+
+ Additional terms, permissive or non-permissive, may be stated in the
+form of a separately written license, or stated as exceptions;
+the above requirements apply either way.
+
+ 8. Termination.
+
+ You may not propagate or modify a covered work except as expressly
+provided under this License. Any attempt otherwise to propagate or
+modify it is void, and will automatically terminate your rights under
+this License (including any patent licenses granted under the third
+paragraph of section 11).
+
+ However, if you cease all violation of this License, then your
+license from a particular copyright holder is reinstated (a)
+provisionally, unless and until the copyright holder explicitly and
+finally terminates your license, and (b) permanently, if the copyright
+holder fails to notify you of the violation by some reasonable means
+prior to 60 days after the cessation.
+
+ Moreover, your license from a particular copyright holder is
+reinstated permanently if the copyright holder notifies you of the
+violation by some reasonable means, this is the first time you have
+received notice of violation of this License (for any work) from that
+copyright holder, and you cure the violation prior to 30 days after
+your receipt of the notice.
+
+ Termination of your rights under this section does not terminate the
+licenses of parties who have received copies or rights from you under
+this License. If your rights have been terminated and not permanently
+reinstated, you do not qualify to receive new licenses for the same
+material under section 10.
+
+ 9. Acceptance Not Required for Having Copies.
+
+ You are not required to accept this License in order to receive or
+run a copy of the Program. Ancillary propagation of a covered work
+occurring solely as a consequence of using peer-to-peer transmission
+to receive a copy likewise does not require acceptance. However,
+nothing other than this License grants you permission to propagate or
+modify any covered work. These actions infringe copyright if you do
+not accept this License. Therefore, by modifying or propagating a
+covered work, you indicate your acceptance of this License to do so.
+
+ 10. Automatic Licensing of Downstream Recipients.
+
+ Each time you convey a covered work, the recipient automatically
+receives a license from the original licensors, to run, modify and
+propagate that work, subject to this License. You are not responsible
+for enforcing compliance by third parties with this License.
+
+ An "entity transaction" is a transaction transferring control of an
+organization, or substantially all assets of one, or subdividing an
+organization, or merging organizations. If propagation of a covered
+work results from an entity transaction, each party to that
+transaction who receives a copy of the work also receives whatever
+licenses to the work the party's predecessor in interest had or could
+give under the previous paragraph, plus a right to possession of the
+Corresponding Source of the work from the predecessor in interest, if
+the predecessor has it or can get it with reasonable efforts.
+
+ You may not impose any further restrictions on the exercise of the
+rights granted or affirmed under this License. For example, you may
+not impose a license fee, royalty, or other charge for exercise of
+rights granted under this License, and you may not initiate litigation
+(including a cross-claim or counterclaim in a lawsuit) alleging that
+any patent claim is infringed by making, using, selling, offering for
+sale, or importing the Program or any portion of it.
+
+ 11. Patents.
+
+ A "contributor" is a copyright holder who authorizes use under this
+License of the Program or a work on which the Program is based. The
+work thus licensed is called the contributor's "contributor version".
+
+ A contributor's "essential patent claims" are all patent claims
+owned or controlled by the contributor, whether already acquired or
+hereafter acquired, that would be infringed by some manner, permitted
+by this License, of making, using, or selling its contributor version,
+but do not include claims that would be infringed only as a
+consequence of further modification of the contributor version. For
+purposes of this definition, "control" includes the right to grant
+patent sublicenses in a manner consistent with the requirements of
+this License.
+
+ Each contributor grants you a non-exclusive, worldwide, royalty-free
+patent license under the contributor's essential patent claims, to
+make, use, sell, offer for sale, import and otherwise run, modify and
+propagate the contents of its contributor version.
+
+ In the following three paragraphs, a "patent license" is any express
+agreement or commitment, however denominated, not to enforce a patent
+(such as an express permission to practice a patent or covenant not to
+sue for patent infringement). To "grant" such a patent license to a
+party means to make such an agreement or commitment not to enforce a
+patent against the party.
+
+ If you convey a covered work, knowingly relying on a patent license,
+and the Corresponding Source of the work is not available for anyone
+to copy, free of charge and under the terms of this License, through a
+publicly available network server or other readily accessible means,
+then you must either (1) cause the Corresponding Source to be so
+available, or (2) arrange to deprive yourself of the benefit of the
+patent license for this particular work, or (3) arrange, in a manner
+consistent with the requirements of this License, to extend the patent
+license to downstream recipients. "Knowingly relying" means you have
+actual knowledge that, but for the patent license, your conveying the
+covered work in a country, or your recipient's use of the covered work
+in a country, would infringe one or more identifiable patents in that
+country that you have reason to believe are valid.
+
+ If, pursuant to or in connection with a single transaction or
+arrangement, you convey, or propagate by procuring conveyance of, a
+covered work, and grant a patent license to some of the parties
+receiving the covered work authorizing them to use, propagate, modify
+or convey a specific copy of the covered work, then the patent license
+you grant is automatically extended to all recipients of the covered
+work and works based on it.
+
+ A patent license is "discriminatory" if it does not include within
+the scope of its coverage, prohibits the exercise of, or is
+conditioned on the non-exercise of one or more of the rights that are
+specifically granted under this License. You may not convey a covered
+work if you are a party to an arrangement with a third party that is
+in the business of distributing software, under which you make payment
+to the third party based on the extent of your activity of conveying
+the work, and under which the third party grants, to any of the
+parties who would receive the covered work from you, a discriminatory
+patent license (a) in connection with copies of the covered work
+conveyed by you (or copies made from those copies), or (b) primarily
+for and in connection with specific products or compilations that
+contain the covered work, unless you entered into that arrangement,
+or that patent license was granted, prior to 28 March 2007.
+
+ Nothing in this License shall be construed as excluding or limiting
+any implied license or other defenses to infringement that may
+otherwise be available to you under applicable patent law.
+
+ 12. No Surrender of Others' Freedom.
+
+ If conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License. If you cannot convey a
+covered work so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you may
+not convey it at all. For example, if you agree to terms that obligate you
+to collect a royalty for further conveying from those to whom you convey
+the Program, the only way you could satisfy both those terms and this
+License would be to refrain entirely from conveying the Program.
+
+ 13. Use with the GNU Affero General Public License.
+
+ Notwithstanding any other provision of this License, you have
+permission to link or combine any covered work with a work licensed
+under version 3 of the GNU Affero General Public License into a single
+combined work, and to convey the resulting work. The terms of this
+License will continue to apply to the part which is the covered work,
+but the special requirements of the GNU Affero General Public License,
+section 13, concerning interaction through a network will apply to the
+combination as such.
+
+ 14. Revised Versions of this License.
+
+ The Free Software Foundation may publish revised and/or new versions of
+the GNU General Public License from time to time. Such new versions will
+be similar in spirit to the present version, but may differ in detail to
+address new problems or concerns.
+
+ Each version is given a distinguishing version number. If the
+Program specifies that a certain numbered version of the GNU General
+Public License "or any later version" applies to it, you have the
+option of following the terms and conditions either of that numbered
+version or of any later version published by the Free Software
+Foundation. If the Program does not specify a version number of the
+GNU General Public License, you may choose any version ever published
+by the Free Software Foundation.
+
+ If the Program specifies that a proxy can decide which future
+versions of the GNU General Public License can be used, that proxy's
+public statement of acceptance of a version permanently authorizes you
+to choose that version for the Program.
+
+ Later license versions may give you additional or different
+permissions. However, no additional obligations are imposed on any
+author or copyright holder as a result of your choosing to follow a
+later version.
+
+ 15. Disclaimer of Warranty.
+
+ THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY
+APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT
+HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY
+OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO,
+THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM
+IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF
+ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
+
+ 16. Limitation of Liability.
+
+ IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS
+THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY
+GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE
+USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF
+DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD
+PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS),
+EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF
+SUCH DAMAGES.
+
+ 17. Interpretation of Sections 15 and 16.
+
+ If the disclaimer of warranty and limitation of liability provided
+above cannot be given local legal effect according to their terms,
+reviewing courts shall apply local law that most closely approximates
+an absolute waiver of all civil liability in connection with the
+Program, unless a warranty or assumption of liability accompanies a
+copy of the Program in return for a fee.
+
+ END OF TERMS AND CONDITIONS
+
+ How to Apply These Terms to Your New Programs
+
+ If you develop a new program, and you want it to be of the greatest
+possible use to the public, the best way to achieve this is to make it
+free software which everyone can redistribute and change under these terms.
+
+ To do so, attach the following notices to the program. It is safest
+to attach them to the start of each source file to most effectively
+state the exclusion of warranty; and each file should have at least
+the "copyright" line and a pointer to where the full notice is found.
+
+
+ Copyright (C)
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see .
+
+Also add information on how to contact you by electronic and paper mail.
+
+ If the program does terminal interaction, make it output a short
+notice like this when it starts in an interactive mode:
+
+ Copyright (C)
+ This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
+ This is free software, and you are welcome to redistribute it
+ under certain conditions; type `show c' for details.
+
+The hypothetical commands `show w' and `show c' should show the appropriate
+parts of the General Public License. Of course, your program's commands
+might be different; for a GUI interface, you would use an "about box".
+
+ You should also get your employer (if you work as a programmer) or school,
+if any, to sign a "copyright disclaimer" for the program, if necessary.
+For more information on this, and how to apply and follow the GNU GPL, see
+.
+
+ The GNU General Public License does not permit incorporating your program
+into proprietary programs. If your program is a subroutine library, you
+may consider it more useful to permit linking proprietary applications with
+the library. If this is what you want to do, use the GNU Lesser General
+Public License instead of this License. But first, please read
+.
diff --git a/modules/sale_credit_limit/MANIFEST.in b/modules/sale_credit_limit/MANIFEST.in
new file mode 100644
index 0000000000..e88b2348a3
--- /dev/null
+++ b/modules/sale_credit_limit/MANIFEST.in
@@ -0,0 +1,5 @@
+include CHANGELOG
+include COPYRIGHT
+include LICENSE
+include README.rst
+include doc/*
diff --git a/modules/sale_credit_limit/README.rst b/modules/sale_credit_limit/README.rst
new file mode 120000
index 0000000000..176d9c2695
--- /dev/null
+++ b/modules/sale_credit_limit/README.rst
@@ -0,0 +1 @@
+doc/index.rst
\ No newline at end of file
diff --git a/modules/sale_credit_limit/__init__.py b/modules/sale_credit_limit/__init__.py
new file mode 100644
index 0000000000..bc56d55dd0
--- /dev/null
+++ b/modules/sale_credit_limit/__init__.py
@@ -0,0 +1,13 @@
+# This file is part of Tryton. The COPYRIGHT file at the top level of
+# this repository contains the full copyright notices and license terms.
+
+from trytond.pool import Pool
+from . import party
+from . import sale
+
+
+def register():
+ Pool.register(
+ party.Party,
+ sale.Sale,
+ module='sale_credit_limit', type_='model')
diff --git a/modules/sale_credit_limit/doc/index.rst b/modules/sale_credit_limit/doc/index.rst
new file mode 100644
index 0000000000..505a6919bf
--- /dev/null
+++ b/modules/sale_credit_limit/doc/index.rst
@@ -0,0 +1,6 @@
+Sale Credit Limit
+#################
+
+The sale_credit_limit module adds confirmed sale but not yet invoiced to the
+"Credit Amount" of the Party and check the credit limit of the party when
+confirming a sale.
diff --git a/modules/sale_credit_limit/party.py b/modules/sale_credit_limit/party.py
new file mode 100644
index 0000000000..3a5ef12315
--- /dev/null
+++ b/modules/sale_credit_limit/party.py
@@ -0,0 +1,54 @@
+# This file is part of Tryton. The COPYRIGHT file at the top level of
+# this repository contains the full copyright notices and license terms.
+from decimal import Decimal
+
+from trytond.pool import Pool, PoolMeta
+from trytond.transaction import Transaction
+
+
+class Party(metaclass=PoolMeta):
+ __name__ = 'party.party'
+
+ @classmethod
+ def get_credit_amount(cls, parties, name):
+ pool = Pool()
+ Currency = pool.get('currency.currency')
+ Sale = pool.get('sale.sale')
+ Uom = pool.get('product.uom')
+ User = pool.get('res.user')
+
+ amounts = super(Party, cls).get_credit_amount(parties, name)
+
+ user = User(Transaction().user)
+ if not user.company:
+ return amounts
+ currency = user.company.currency
+
+ sales = Sale.search([
+ ('party', 'in', [p.id for p in parties]),
+ ('state', 'in', ['confirmed', 'processing']),
+ ])
+ for sale in sales:
+ amount = 0
+ for line in sale.lines:
+ quantity = line.quantity
+ if not quantity:
+ continue
+ for invoice_line in line.invoice_lines:
+ invoice = invoice_line.invoice
+ if invoice and invoice.move:
+ quantity -= Uom.compute_qty(
+ invoice_line.unit, invoice_line.quantity,
+ line.unit, round=False)
+ amount += Currency.compute(
+ sale.currency,
+ Decimal(str(quantity)) * line.unit_price, currency,
+ round=False)
+ amounts[sale.party.id] = currency.round(
+ amounts[sale.party.id] + amount)
+ return amounts
+
+ @classmethod
+ def _credit_limit_to_lock(cls):
+ return super(Party, cls)._credit_limit_to_lock() + [
+ 'sale.sale', 'sale.line']
diff --git a/modules/sale_credit_limit/sale.py b/modules/sale_credit_limit/sale.py
new file mode 100644
index 0000000000..9a6099715e
--- /dev/null
+++ b/modules/sale_credit_limit/sale.py
@@ -0,0 +1,18 @@
+# This file is part of Tryton. The COPYRIGHT file at the top level of
+# this repository contains the full copyright notices and license terms.
+from trytond.model import ModelView, Workflow
+from trytond.pool import PoolMeta
+
+
+class Sale(metaclass=PoolMeta):
+ __name__ = 'sale.sale'
+
+ @classmethod
+ @ModelView.button
+ @Workflow.transition('confirmed')
+ def confirm(cls, sales):
+ for sale in sales:
+ if sale.shipment_method == 'order':
+ party = sale.invoice_party or sale.party
+ party.check_credit_limit(sale.untaxed_amount, origin=str(sale))
+ super(Sale, cls).confirm(sales)
diff --git a/modules/sale_credit_limit/setup.py b/modules/sale_credit_limit/setup.py
new file mode 100755
index 0000000000..fcae5e0be1
--- /dev/null
+++ b/modules/sale_credit_limit/setup.py
@@ -0,0 +1,147 @@
+#!/usr/bin/env python3
+# This file is part of Tryton. The COPYRIGHT file at the top level of
+# this repository contains the full copyright notices and license terms.
+
+import io
+import os
+import re
+from configparser import ConfigParser
+from setuptools import setup, find_packages
+
+
+def read(fname):
+ return io.open(
+ os.path.join(os.path.dirname(__file__), fname),
+ 'r', encoding='utf-8').read()
+
+
+def get_require_version(name):
+ if minor_version % 2:
+ require = '%s >= %s.%s.dev0, < %s.%s'
+ else:
+ require = '%s >= %s.%s, < %s.%s'
+ require %= (name, major_version, minor_version,
+ major_version, minor_version + 1)
+ return require
+
+
+config = ConfigParser()
+config.read_file(open(os.path.join(os.path.dirname(__file__), 'tryton.cfg')))
+info = dict(config.items('tryton'))
+for key in ('depends', 'extras_depend', 'xml'):
+ if key in info:
+ info[key] = info[key].strip().splitlines()
+version = info.get('version', '0.0.1')
+major_version, minor_version, _ = version.split('.', 2)
+major_version = int(major_version)
+minor_version = int(minor_version)
+name = 'trytond_sale_credit_limit'
+
+download_url = 'http://downloads.tryton.org/%s.%s/' % (
+ major_version, minor_version)
+if minor_version % 2:
+ version = '%s.%s.dev0' % (major_version, minor_version)
+ download_url = (
+ 'hg+http://hg.tryton.org/modules/%s#egg=%s-%s' % (
+ name[8:], name, version))
+local_version = []
+if os.environ.get('CI_JOB_ID'):
+ local_version.append(os.environ['CI_JOB_ID'])
+else:
+ for build in ['CI_BUILD_NUMBER', 'CI_JOB_NUMBER']:
+ if os.environ.get(build):
+ local_version.append(os.environ[build])
+ else:
+ local_version = []
+ break
+if local_version:
+ version += '+' + '.'.join(local_version)
+
+requires = []
+for dep in info.get('depends', []):
+ if not re.match(r'(ir|res)(\W|$)', dep):
+ requires.append(get_require_version('trytond_%s' % dep))
+requires.append(get_require_version('trytond'))
+
+dependency_links = []
+if minor_version % 2:
+ dependency_links.append(
+ 'https://trydevpi.tryton.org/?local_version='
+ + '.'.join(local_version))
+
+setup(name=name,
+ version=version,
+ description='Tryton module for sale credit limit',
+ long_description=read('README.rst'),
+ author='Tryton',
+ author_email='bugs@tryton.org',
+ url='http://www.tryton.org/',
+ download_url=download_url,
+ project_urls={
+ "Bug Tracker": 'https://bugs.tryton.org/',
+ "Documentation": 'https://docs.tryton.org/',
+ "Forum": 'https://www.tryton.org/forum',
+ "Source Code": 'https://hg.tryton.org/modules/sale_credit_limit',
+ },
+ keywords='tryton sale credit limit',
+ package_dir={'trytond.modules.sale_credit_limit': '.'},
+ packages=(
+ ['trytond.modules.sale_credit_limit']
+ + ['trytond.modules.sale_credit_limit.%s' % p for p in find_packages()]
+ ),
+ package_data={
+ 'trytond.modules.sale_credit_limit': (info.get('xml', [])
+ + ['tryton.cfg', 'locale/*.po']),
+ },
+ classifiers=[
+ 'Development Status :: 5 - Production/Stable',
+ 'Environment :: Plugins',
+ 'Framework :: Tryton',
+ 'Intended Audience :: Developers',
+ 'Intended Audience :: Financial and Insurance Industry',
+ 'Intended Audience :: Legal Industry',
+ 'License :: OSI Approved :: '
+ 'GNU General Public License v3 or later (GPLv3+)',
+ 'Natural Language :: Bulgarian',
+ 'Natural Language :: Catalan',
+ 'Natural Language :: Chinese (Simplified)',
+ 'Natural Language :: Czech',
+ 'Natural Language :: Dutch',
+ 'Natural Language :: English',
+ 'Natural Language :: Finnish',
+ 'Natural Language :: French',
+ 'Natural Language :: German',
+ 'Natural Language :: Hungarian',
+ 'Natural Language :: Indonesian',
+ 'Natural Language :: Italian',
+ 'Natural Language :: Persian',
+ 'Natural Language :: Polish',
+ 'Natural Language :: Portuguese (Brazilian)',
+ 'Natural Language :: Romanian',
+ 'Natural Language :: Russian',
+ 'Natural Language :: Slovenian',
+ 'Natural Language :: Spanish',
+ 'Natural Language :: Turkish',
+ 'Operating System :: OS Independent',
+ 'Programming Language :: Python :: 3',
+ 'Programming Language :: Python :: 3.6',
+ 'Programming Language :: Python :: 3.7',
+ 'Programming Language :: Python :: 3.8',
+ 'Programming Language :: Python :: 3.9',
+ 'Programming Language :: Python :: Implementation :: CPython',
+ 'Programming Language :: Python :: Implementation :: PyPy',
+ 'Topic :: Office/Business',
+ 'Topic :: Office/Business :: Financial :: Accounting',
+ ],
+ license='GPL-3',
+ python_requires='>=3.6',
+ install_requires=requires,
+ dependency_links=dependency_links,
+ zip_safe=False,
+ entry_points="""
+ [trytond.modules]
+ sale_credit_limit = trytond.modules.sale_credit_limit
+ """,
+ test_suite='tests',
+ test_loader='trytond.test_loader:Loader',
+ )
diff --git a/modules/sale_credit_limit/tests/__init__.py b/modules/sale_credit_limit/tests/__init__.py
new file mode 100644
index 0000000000..7cfaf1e3a4
--- /dev/null
+++ b/modules/sale_credit_limit/tests/__init__.py
@@ -0,0 +1,9 @@
+# This file is part of Tryton. The COPYRIGHT file at the top level of
+# this repository contains the full copyright notices and license terms.
+
+try:
+ from trytond.modules.sale_credit_limit.tests.test_sale_credit_limit import suite # noqa: E501
+except ImportError:
+ from .test_sale_credit_limit import suite
+
+__all__ = ['suite']
diff --git a/modules/sale_credit_limit/tests/test_sale_credit_limit.py b/modules/sale_credit_limit/tests/test_sale_credit_limit.py
new file mode 100644
index 0000000000..9f0b35baad
--- /dev/null
+++ b/modules/sale_credit_limit/tests/test_sale_credit_limit.py
@@ -0,0 +1,131 @@
+# This file is part of Tryton. The COPYRIGHT file at the top level of
+# this repository contains the full copyright notices and license terms.
+import unittest
+from decimal import Decimal
+import trytond.tests.test_tryton
+from trytond.tests.test_tryton import ModuleTestCase, with_transaction
+from trytond.pool import Pool
+from trytond.exceptions import UserWarning
+
+from trytond.modules.company.tests import (
+ create_company, set_company, CompanyTestMixin)
+from trytond.modules.account.tests import create_chart, get_fiscalyear
+from trytond.modules.account_invoice.tests import set_invoice_sequences
+
+
+class SaleCreditLimitTestCase(CompanyTestMixin, ModuleTestCase):
+ 'Test SaleCreditLimit module'
+ module = 'sale_credit_limit'
+
+ @with_transaction()
+ def test_check_credit_limit(self):
+ 'Test check_credit_limit'
+ pool = Pool()
+ Account = pool.get('account.account')
+ Move = pool.get('account.move')
+ Journal = pool.get('account.journal')
+ Party = pool.get('party.party')
+ Sale = pool.get('sale.sale')
+ PaymentTerm = pool.get('account.invoice.payment_term')
+ Configuration = pool.get('account.configuration')
+ FiscalYear = pool.get('account.fiscalyear')
+ Invoice = pool.get('account.invoice')
+
+ company = create_company()
+ with set_company(company):
+ create_chart(company)
+ fiscalyear = set_invoice_sequences(get_fiscalyear(company))
+ fiscalyear.save()
+ FiscalYear.create_period([fiscalyear])
+ period = fiscalyear.periods[0]
+
+ receivable, = Account.search([
+ ('type.receivable', '=', True),
+ ])
+ revenue, = Account.search([
+ ('type.revenue', '=', True),
+ ])
+ journal, = Journal.search([], limit=1)
+ party, = Party.create([{
+ 'name': 'Party',
+ 'addresses': [
+ ('create', [{}]),
+ ],
+ 'credit_limit_amount': Decimal('100'),
+ }])
+ Move.create([{
+ 'journal': journal.id,
+ 'period': period.id,
+ 'date': period.start_date,
+ 'lines': [
+ ('create', [{
+ 'debit': Decimal('100'),
+ 'account': receivable.id,
+ 'party': party.id,
+ }, {
+ 'credit': Decimal('100'),
+ 'account': revenue.id,
+ }]),
+ ],
+ }])
+ payment_term, = PaymentTerm.create([{
+ 'name': 'Test',
+ 'lines': [
+ ('create', [{
+ 'type': 'remainder',
+ }])
+ ],
+ }])
+ config = Configuration(1)
+ config.default_category_account_revenue = revenue
+ config.save()
+ sale, = Sale.create([{
+ 'party': party.id,
+ 'company': company.id,
+ 'payment_term': payment_term.id,
+ 'currency': company.currency.id,
+ 'invoice_address': party.addresses[0].id,
+ 'shipment_address': party.addresses[0].id,
+ 'lines': [
+ ('create', [{
+ 'description': 'Test',
+ 'quantity': 1,
+ 'unit_price': Decimal('50'),
+ }]),
+ ],
+ }])
+ self.assertEqual(party.credit_amount, Decimal('100'))
+ Sale.quote([sale])
+ # Test limit reaches
+ self.assertRaises(UserWarning, Sale.confirm, [sale])
+ self.assertEqual(party.credit_amount, Decimal('100'))
+ # Increase limit
+ party.credit_limit_amount = Decimal('200')
+ party.save()
+ # process should work
+ Sale.confirm([sale])
+ self.assertEqual(sale.state, 'confirmed')
+ self.assertEqual(party.credit_amount, Decimal('150'))
+
+ # Process
+ Sale.process([sale])
+ # Decrease limit
+ party.credit_limit_amount = Decimal('100')
+ party.save()
+ # process should still work as sale is already processing
+ Sale.process([sale])
+
+ # Increase quantity invoiced does not change the credit amount
+ invoice, = sale.invoices
+ invoice_line, = invoice.lines
+ invoice_line.quantity += 1
+ invoice_line.save()
+ Invoice.post([invoice])
+ self.assertEqual(party.credit_amount, Decimal('150'))
+
+
+def suite():
+ suite = trytond.tests.test_tryton.suite()
+ suite.addTests(unittest.TestLoader().loadTestsFromTestCase(
+ SaleCreditLimitTestCase))
+ return suite
diff --git a/modules/sale_credit_limit/tox.ini b/modules/sale_credit_limit/tox.ini
new file mode 100644
index 0000000000..197496c0cb
--- /dev/null
+++ b/modules/sale_credit_limit/tox.ini
@@ -0,0 +1,15 @@
+[tox]
+envlist = {py36,py37,py38,py39}-{sqlite,postgresql},pypy3-{sqlite,postgresql}
+
+[testenv]
+commands = {envpython} setup.py test
+deps =
+ {py36,py37,py38,py39}-postgresql: psycopg2 >= 2.5
+ pypy3-postgresql: psycopg2cffi >= 2.5
+ py36-sqlite: sqlitebck
+setenv =
+ sqlite: TRYTOND_DATABASE_URI={env:SQLITE_URI:sqlite://}
+ postgresql: TRYTOND_DATABASE_URI={env:POSTGRESQL_URI:postgresql://}
+ sqlite: DB_NAME={env:SQLITE_NAME::memory:}
+ postgresql: DB_NAME={env:POSTGRESQL_NAME:test}
+install_command = pip install --pre --find-links https://trydevpi.tryton.org/?local_version={env:CI_JOB_ID:{env:CI_BUILD_NUMBER}.{env:CI_JOB_NUMBER}} {opts} {packages}
diff --git a/modules/sale_credit_limit/tryton.cfg b/modules/sale_credit_limit/tryton.cfg
new file mode 100644
index 0000000000..8c7bbca910
--- /dev/null
+++ b/modules/sale_credit_limit/tryton.cfg
@@ -0,0 +1,9 @@
+[tryton]
+version=6.0.1
+depends:
+ ir
+ account_credit_limit
+ sale
+ currency
+ account_invoice
+ company
diff --git a/modules/sale_discount/.drone.yml b/modules/sale_discount/.drone.yml
new file mode 100644
index 0000000000..2049d30a49
--- /dev/null
+++ b/modules/sale_discount/.drone.yml
@@ -0,0 +1,68 @@
+clone:
+ hg:
+ image: plugins/hg
+ environment:
+ - HG_SHARE_POOL=/root/.cache/hg
+ volumes:
+ - cache:/root/.cache
+
+pipeline:
+ tox:
+ image: ${IMAGE}
+ environment:
+ - CFLAGS=-O0
+ - DB_CACHE=/cache
+ - TOX_TESTENV_PASSENV=CFLAGS DB_CACHE CI_BUILD_NUMBER CI_JOB_NUMBER CI_JOB_ID
+ - POSTGRESQL_URI=postgresql://postgres@postgresql:5432/
+ commands:
+ - echo "[extensions]" >> /root/.hgrc
+ - echo "hgext.share =" >> /root/.hgrc
+ - echo "[share]" >> /root/.hgrc
+ - echo "pool = /root/.cache/hg" >> /root/.hgrc
+ - pip install tox
+ - tox -e "${TOXENV}-${DATABASE}"
+ volumes:
+ - cache:/root/.cache
+ check_dist:
+ image: ${IMAGE}
+ commands:
+ - pip install twine
+ - python setup.py sdist
+ - twine check dist/*
+
+services:
+ postgresql:
+ image: postgres
+ environment:
+ - POSTGRES_HOST_AUTH_METHOD=trust
+ command: "-c fsync=off -c synchronous_commit=off -c full_page_writes=off"
+ when:
+ matrix:
+ DATABASE: postgresql
+
+matrix:
+ include:
+ - IMAGE: python:3.6
+ TOXENV: py36
+ DATABASE: sqlite
+ - IMAGE: python:3.6
+ TOXENV: py36
+ DATABASE: postgresql
+ - IMAGE: python:3.7
+ TOXENV: py37
+ DATABASE: sqlite
+ - IMAGE: python:3.7
+ TOXENV: py37
+ DATABASE: postgresql
+ - IMAGE: python:3.8
+ TOXENV: py38
+ DATABASE: sqlite
+ - IMAGE: python:3.8
+ TOXENV: py38
+ DATABASE: postgresql
+ - IMAGE: python:3.9
+ TOXENV: py39
+ DATABASE: sqlite
+ - IMAGE: python:3.9
+ TOXENV: py39
+ DATABASE: postgresql
diff --git a/modules/sale_discount/.flake8 b/modules/sale_discount/.flake8
new file mode 100644
index 0000000000..fa6b4f66d1
--- /dev/null
+++ b/modules/sale_discount/.flake8
@@ -0,0 +1,2 @@
+[flake8]
+ignore=E123,E124,E126,E128,E741,W503
diff --git a/modules/sale_discount/CHANGELOG b/modules/sale_discount/CHANGELOG
new file mode 100644
index 0000000000..3b19a12abd
--- /dev/null
+++ b/modules/sale_discount/CHANGELOG
@@ -0,0 +1,8 @@
+Version 6.0.1 - 2022-08-17
+* Bug fixes (see mercurial logs for details)
+
+Version 6.0.0 - 2021-05-03
+* Bug fixes (see mercurial logs for details)
+
+Version 5.8.0 - 2020-11-02
+* Initial release
\ No newline at end of file
diff --git a/modules/sale_discount/COPYRIGHT b/modules/sale_discount/COPYRIGHT
new file mode 100644
index 0000000000..d0b4a3655d
--- /dev/null
+++ b/modules/sale_discount/COPYRIGHT
@@ -0,0 +1,15 @@
+Copyright (C) 2020-2022 B2CK
+Copyright (C) 2020-2022 Cédric Krier
+
+This program is free software: you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation, either version 3 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program. If not, see .
diff --git a/modules/sale_discount/LICENSE b/modules/sale_discount/LICENSE
new file mode 100644
index 0000000000..94a9ed024d
--- /dev/null
+++ b/modules/sale_discount/LICENSE
@@ -0,0 +1,674 @@
+ GNU GENERAL PUBLIC LICENSE
+ Version 3, 29 June 2007
+
+ Copyright (C) 2007 Free Software Foundation, Inc.
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+ Preamble
+
+ The GNU General Public License is a free, copyleft license for
+software and other kinds of works.
+
+ The licenses for most software and other practical works are designed
+to take away your freedom to share and change the works. By contrast,
+the GNU General Public License is intended to guarantee your freedom to
+share and change all versions of a program--to make sure it remains free
+software for all its users. We, the Free Software Foundation, use the
+GNU General Public License for most of our software; it applies also to
+any other work released this way by its authors. You can apply it to
+your programs, too.
+
+ When we speak of free software, we are referring to freedom, not
+price. Our General Public Licenses are designed to make sure that you
+have the freedom to distribute copies of free software (and charge for
+them if you wish), that you receive source code or can get it if you
+want it, that you can change the software or use pieces of it in new
+free programs, and that you know you can do these things.
+
+ To protect your rights, we need to prevent others from denying you
+these rights or asking you to surrender the rights. Therefore, you have
+certain responsibilities if you distribute copies of the software, or if
+you modify it: responsibilities to respect the freedom of others.
+
+ For example, if you distribute copies of such a program, whether
+gratis or for a fee, you must pass on to the recipients the same
+freedoms that you received. You must make sure that they, too, receive
+or can get the source code. And you must show them these terms so they
+know their rights.
+
+ Developers that use the GNU GPL protect your rights with two steps:
+(1) assert copyright on the software, and (2) offer you this License
+giving you legal permission to copy, distribute and/or modify it.
+
+ For the developers' and authors' protection, the GPL clearly explains
+that there is no warranty for this free software. For both users' and
+authors' sake, the GPL requires that modified versions be marked as
+changed, so that their problems will not be attributed erroneously to
+authors of previous versions.
+
+ Some devices are designed to deny users access to install or run
+modified versions of the software inside them, although the manufacturer
+can do so. This is fundamentally incompatible with the aim of
+protecting users' freedom to change the software. The systematic
+pattern of such abuse occurs in the area of products for individuals to
+use, which is precisely where it is most unacceptable. Therefore, we
+have designed this version of the GPL to prohibit the practice for those
+products. If such problems arise substantially in other domains, we
+stand ready to extend this provision to those domains in future versions
+of the GPL, as needed to protect the freedom of users.
+
+ Finally, every program is threatened constantly by software patents.
+States should not allow patents to restrict development and use of
+software on general-purpose computers, but in those that do, we wish to
+avoid the special danger that patents applied to a free program could
+make it effectively proprietary. To prevent this, the GPL assures that
+patents cannot be used to render the program non-free.
+
+ The precise terms and conditions for copying, distribution and
+modification follow.
+
+ TERMS AND CONDITIONS
+
+ 0. Definitions.
+
+ "This License" refers to version 3 of the GNU General Public License.
+
+ "Copyright" also means copyright-like laws that apply to other kinds of
+works, such as semiconductor masks.
+
+ "The Program" refers to any copyrightable work licensed under this
+License. Each licensee is addressed as "you". "Licensees" and
+"recipients" may be individuals or organizations.
+
+ To "modify" a work means to copy from or adapt all or part of the work
+in a fashion requiring copyright permission, other than the making of an
+exact copy. The resulting work is called a "modified version" of the
+earlier work or a work "based on" the earlier work.
+
+ A "covered work" means either the unmodified Program or a work based
+on the Program.
+
+ To "propagate" a work means to do anything with it that, without
+permission, would make you directly or secondarily liable for
+infringement under applicable copyright law, except executing it on a
+computer or modifying a private copy. Propagation includes copying,
+distribution (with or without modification), making available to the
+public, and in some countries other activities as well.
+
+ To "convey" a work means any kind of propagation that enables other
+parties to make or receive copies. Mere interaction with a user through
+a computer network, with no transfer of a copy, is not conveying.
+
+ An interactive user interface displays "Appropriate Legal Notices"
+to the extent that it includes a convenient and prominently visible
+feature that (1) displays an appropriate copyright notice, and (2)
+tells the user that there is no warranty for the work (except to the
+extent that warranties are provided), that licensees may convey the
+work under this License, and how to view a copy of this License. If
+the interface presents a list of user commands or options, such as a
+menu, a prominent item in the list meets this criterion.
+
+ 1. Source Code.
+
+ The "source code" for a work means the preferred form of the work
+for making modifications to it. "Object code" means any non-source
+form of a work.
+
+ A "Standard Interface" means an interface that either is an official
+standard defined by a recognized standards body, or, in the case of
+interfaces specified for a particular programming language, one that
+is widely used among developers working in that language.
+
+ The "System Libraries" of an executable work include anything, other
+than the work as a whole, that (a) is included in the normal form of
+packaging a Major Component, but which is not part of that Major
+Component, and (b) serves only to enable use of the work with that
+Major Component, or to implement a Standard Interface for which an
+implementation is available to the public in source code form. A
+"Major Component", in this context, means a major essential component
+(kernel, window system, and so on) of the specific operating system
+(if any) on which the executable work runs, or a compiler used to
+produce the work, or an object code interpreter used to run it.
+
+ The "Corresponding Source" for a work in object code form means all
+the source code needed to generate, install, and (for an executable
+work) run the object code and to modify the work, including scripts to
+control those activities. However, it does not include the work's
+System Libraries, or general-purpose tools or generally available free
+programs which are used unmodified in performing those activities but
+which are not part of the work. For example, Corresponding Source
+includes interface definition files associated with source files for
+the work, and the source code for shared libraries and dynamically
+linked subprograms that the work is specifically designed to require,
+such as by intimate data communication or control flow between those
+subprograms and other parts of the work.
+
+ The Corresponding Source need not include anything that users
+can regenerate automatically from other parts of the Corresponding
+Source.
+
+ The Corresponding Source for a work in source code form is that
+same work.
+
+ 2. Basic Permissions.
+
+ All rights granted under this License are granted for the term of
+copyright on the Program, and are irrevocable provided the stated
+conditions are met. This License explicitly affirms your unlimited
+permission to run the unmodified Program. The output from running a
+covered work is covered by this License only if the output, given its
+content, constitutes a covered work. This License acknowledges your
+rights of fair use or other equivalent, as provided by copyright law.
+
+ You may make, run and propagate covered works that you do not
+convey, without conditions so long as your license otherwise remains
+in force. You may convey covered works to others for the sole purpose
+of having them make modifications exclusively for you, or provide you
+with facilities for running those works, provided that you comply with
+the terms of this License in conveying all material for which you do
+not control copyright. Those thus making or running the covered works
+for you must do so exclusively on your behalf, under your direction
+and control, on terms that prohibit them from making any copies of
+your copyrighted material outside their relationship with you.
+
+ Conveying under any other circumstances is permitted solely under
+the conditions stated below. Sublicensing is not allowed; section 10
+makes it unnecessary.
+
+ 3. Protecting Users' Legal Rights From Anti-Circumvention Law.
+
+ No covered work shall be deemed part of an effective technological
+measure under any applicable law fulfilling obligations under article
+11 of the WIPO copyright treaty adopted on 20 December 1996, or
+similar laws prohibiting or restricting circumvention of such
+measures.
+
+ When you convey a covered work, you waive any legal power to forbid
+circumvention of technological measures to the extent such circumvention
+is effected by exercising rights under this License with respect to
+the covered work, and you disclaim any intention to limit operation or
+modification of the work as a means of enforcing, against the work's
+users, your or third parties' legal rights to forbid circumvention of
+technological measures.
+
+ 4. Conveying Verbatim Copies.
+
+ You may convey verbatim copies of the Program's source code as you
+receive it, in any medium, provided that you conspicuously and
+appropriately publish on each copy an appropriate copyright notice;
+keep intact all notices stating that this License and any
+non-permissive terms added in accord with section 7 apply to the code;
+keep intact all notices of the absence of any warranty; and give all
+recipients a copy of this License along with the Program.
+
+ You may charge any price or no price for each copy that you convey,
+and you may offer support or warranty protection for a fee.
+
+ 5. Conveying Modified Source Versions.
+
+ You may convey a work based on the Program, or the modifications to
+produce it from the Program, in the form of source code under the
+terms of section 4, provided that you also meet all of these conditions:
+
+ a) The work must carry prominent notices stating that you modified
+ it, and giving a relevant date.
+
+ b) The work must carry prominent notices stating that it is
+ released under this License and any conditions added under section
+ 7. This requirement modifies the requirement in section 4 to
+ "keep intact all notices".
+
+ c) You must license the entire work, as a whole, under this
+ License to anyone who comes into possession of a copy. This
+ License will therefore apply, along with any applicable section 7
+ additional terms, to the whole of the work, and all its parts,
+ regardless of how they are packaged. This License gives no
+ permission to license the work in any other way, but it does not
+ invalidate such permission if you have separately received it.
+
+ d) If the work has interactive user interfaces, each must display
+ Appropriate Legal Notices; however, if the Program has interactive
+ interfaces that do not display Appropriate Legal Notices, your
+ work need not make them do so.
+
+ A compilation of a covered work with other separate and independent
+works, which are not by their nature extensions of the covered work,
+and which are not combined with it such as to form a larger program,
+in or on a volume of a storage or distribution medium, is called an
+"aggregate" if the compilation and its resulting copyright are not
+used to limit the access or legal rights of the compilation's users
+beyond what the individual works permit. Inclusion of a covered work
+in an aggregate does not cause this License to apply to the other
+parts of the aggregate.
+
+ 6. Conveying Non-Source Forms.
+
+ You may convey a covered work in object code form under the terms
+of sections 4 and 5, provided that you also convey the
+machine-readable Corresponding Source under the terms of this License,
+in one of these ways:
+
+ a) Convey the object code in, or embodied in, a physical product
+ (including a physical distribution medium), accompanied by the
+ Corresponding Source fixed on a durable physical medium
+ customarily used for software interchange.
+
+ b) Convey the object code in, or embodied in, a physical product
+ (including a physical distribution medium), accompanied by a
+ written offer, valid for at least three years and valid for as
+ long as you offer spare parts or customer support for that product
+ model, to give anyone who possesses the object code either (1) a
+ copy of the Corresponding Source for all the software in the
+ product that is covered by this License, on a durable physical
+ medium customarily used for software interchange, for a price no
+ more than your reasonable cost of physically performing this
+ conveying of source, or (2) access to copy the
+ Corresponding Source from a network server at no charge.
+
+ c) Convey individual copies of the object code with a copy of the
+ written offer to provide the Corresponding Source. This
+ alternative is allowed only occasionally and noncommercially, and
+ only if you received the object code with such an offer, in accord
+ with subsection 6b.
+
+ d) Convey the object code by offering access from a designated
+ place (gratis or for a charge), and offer equivalent access to the
+ Corresponding Source in the same way through the same place at no
+ further charge. You need not require recipients to copy the
+ Corresponding Source along with the object code. If the place to
+ copy the object code is a network server, the Corresponding Source
+ may be on a different server (operated by you or a third party)
+ that supports equivalent copying facilities, provided you maintain
+ clear directions next to the object code saying where to find the
+ Corresponding Source. Regardless of what server hosts the
+ Corresponding Source, you remain obligated to ensure that it is
+ available for as long as needed to satisfy these requirements.
+
+ e) Convey the object code using peer-to-peer transmission, provided
+ you inform other peers where the object code and Corresponding
+ Source of the work are being offered to the general public at no
+ charge under subsection 6d.
+
+ A separable portion of the object code, whose source code is excluded
+from the Corresponding Source as a System Library, need not be
+included in conveying the object code work.
+
+ A "User Product" is either (1) a "consumer product", which means any
+tangible personal property which is normally used for personal, family,
+or household purposes, or (2) anything designed or sold for incorporation
+into a dwelling. In determining whether a product is a consumer product,
+doubtful cases shall be resolved in favor of coverage. For a particular
+product received by a particular user, "normally used" refers to a
+typical or common use of that class of product, regardless of the status
+of the particular user or of the way in which the particular user
+actually uses, or expects or is expected to use, the product. A product
+is a consumer product regardless of whether the product has substantial
+commercial, industrial or non-consumer uses, unless such uses represent
+the only significant mode of use of the product.
+
+ "Installation Information" for a User Product means any methods,
+procedures, authorization keys, or other information required to install
+and execute modified versions of a covered work in that User Product from
+a modified version of its Corresponding Source. The information must
+suffice to ensure that the continued functioning of the modified object
+code is in no case prevented or interfered with solely because
+modification has been made.
+
+ If you convey an object code work under this section in, or with, or
+specifically for use in, a User Product, and the conveying occurs as
+part of a transaction in which the right of possession and use of the
+User Product is transferred to the recipient in perpetuity or for a
+fixed term (regardless of how the transaction is characterized), the
+Corresponding Source conveyed under this section must be accompanied
+by the Installation Information. But this requirement does not apply
+if neither you nor any third party retains the ability to install
+modified object code on the User Product (for example, the work has
+been installed in ROM).
+
+ The requirement to provide Installation Information does not include a
+requirement to continue to provide support service, warranty, or updates
+for a work that has been modified or installed by the recipient, or for
+the User Product in which it has been modified or installed. Access to a
+network may be denied when the modification itself materially and
+adversely affects the operation of the network or violates the rules and
+protocols for communication across the network.
+
+ Corresponding Source conveyed, and Installation Information provided,
+in accord with this section must be in a format that is publicly
+documented (and with an implementation available to the public in
+source code form), and must require no special password or key for
+unpacking, reading or copying.
+
+ 7. Additional Terms.
+
+ "Additional permissions" are terms that supplement the terms of this
+License by making exceptions from one or more of its conditions.
+Additional permissions that are applicable to the entire Program shall
+be treated as though they were included in this License, to the extent
+that they are valid under applicable law. If additional permissions
+apply only to part of the Program, that part may be used separately
+under those permissions, but the entire Program remains governed by
+this License without regard to the additional permissions.
+
+ When you convey a copy of a covered work, you may at your option
+remove any additional permissions from that copy, or from any part of
+it. (Additional permissions may be written to require their own
+removal in certain cases when you modify the work.) You may place
+additional permissions on material, added by you to a covered work,
+for which you have or can give appropriate copyright permission.
+
+ Notwithstanding any other provision of this License, for material you
+add to a covered work, you may (if authorized by the copyright holders of
+that material) supplement the terms of this License with terms:
+
+ a) Disclaiming warranty or limiting liability differently from the
+ terms of sections 15 and 16 of this License; or
+
+ b) Requiring preservation of specified reasonable legal notices or
+ author attributions in that material or in the Appropriate Legal
+ Notices displayed by works containing it; or
+
+ c) Prohibiting misrepresentation of the origin of that material, or
+ requiring that modified versions of such material be marked in
+ reasonable ways as different from the original version; or
+
+ d) Limiting the use for publicity purposes of names of licensors or
+ authors of the material; or
+
+ e) Declining to grant rights under trademark law for use of some
+ trade names, trademarks, or service marks; or
+
+ f) Requiring indemnification of licensors and authors of that
+ material by anyone who conveys the material (or modified versions of
+ it) with contractual assumptions of liability to the recipient, for
+ any liability that these contractual assumptions directly impose on
+ those licensors and authors.
+
+ All other non-permissive additional terms are considered "further
+restrictions" within the meaning of section 10. If the Program as you
+received it, or any part of it, contains a notice stating that it is
+governed by this License along with a term that is a further
+restriction, you may remove that term. If a license document contains
+a further restriction but permits relicensing or conveying under this
+License, you may add to a covered work material governed by the terms
+of that license document, provided that the further restriction does
+not survive such relicensing or conveying.
+
+ If you add terms to a covered work in accord with this section, you
+must place, in the relevant source files, a statement of the
+additional terms that apply to those files, or a notice indicating
+where to find the applicable terms.
+
+ Additional terms, permissive or non-permissive, may be stated in the
+form of a separately written license, or stated as exceptions;
+the above requirements apply either way.
+
+ 8. Termination.
+
+ You may not propagate or modify a covered work except as expressly
+provided under this License. Any attempt otherwise to propagate or
+modify it is void, and will automatically terminate your rights under
+this License (including any patent licenses granted under the third
+paragraph of section 11).
+
+ However, if you cease all violation of this License, then your
+license from a particular copyright holder is reinstated (a)
+provisionally, unless and until the copyright holder explicitly and
+finally terminates your license, and (b) permanently, if the copyright
+holder fails to notify you of the violation by some reasonable means
+prior to 60 days after the cessation.
+
+ Moreover, your license from a particular copyright holder is
+reinstated permanently if the copyright holder notifies you of the
+violation by some reasonable means, this is the first time you have
+received notice of violation of this License (for any work) from that
+copyright holder, and you cure the violation prior to 30 days after
+your receipt of the notice.
+
+ Termination of your rights under this section does not terminate the
+licenses of parties who have received copies or rights from you under
+this License. If your rights have been terminated and not permanently
+reinstated, you do not qualify to receive new licenses for the same
+material under section 10.
+
+ 9. Acceptance Not Required for Having Copies.
+
+ You are not required to accept this License in order to receive or
+run a copy of the Program. Ancillary propagation of a covered work
+occurring solely as a consequence of using peer-to-peer transmission
+to receive a copy likewise does not require acceptance. However,
+nothing other than this License grants you permission to propagate or
+modify any covered work. These actions infringe copyright if you do
+not accept this License. Therefore, by modifying or propagating a
+covered work, you indicate your acceptance of this License to do so.
+
+ 10. Automatic Licensing of Downstream Recipients.
+
+ Each time you convey a covered work, the recipient automatically
+receives a license from the original licensors, to run, modify and
+propagate that work, subject to this License. You are not responsible
+for enforcing compliance by third parties with this License.
+
+ An "entity transaction" is a transaction transferring control of an
+organization, or substantially all assets of one, or subdividing an
+organization, or merging organizations. If propagation of a covered
+work results from an entity transaction, each party to that
+transaction who receives a copy of the work also receives whatever
+licenses to the work the party's predecessor in interest had or could
+give under the previous paragraph, plus a right to possession of the
+Corresponding Source of the work from the predecessor in interest, if
+the predecessor has it or can get it with reasonable efforts.
+
+ You may not impose any further restrictions on the exercise of the
+rights granted or affirmed under this License. For example, you may
+not impose a license fee, royalty, or other charge for exercise of
+rights granted under this License, and you may not initiate litigation
+(including a cross-claim or counterclaim in a lawsuit) alleging that
+any patent claim is infringed by making, using, selling, offering for
+sale, or importing the Program or any portion of it.
+
+ 11. Patents.
+
+ A "contributor" is a copyright holder who authorizes use under this
+License of the Program or a work on which the Program is based. The
+work thus licensed is called the contributor's "contributor version".
+
+ A contributor's "essential patent claims" are all patent claims
+owned or controlled by the contributor, whether already acquired or
+hereafter acquired, that would be infringed by some manner, permitted
+by this License, of making, using, or selling its contributor version,
+but do not include claims that would be infringed only as a
+consequence of further modification of the contributor version. For
+purposes of this definition, "control" includes the right to grant
+patent sublicenses in a manner consistent with the requirements of
+this License.
+
+ Each contributor grants you a non-exclusive, worldwide, royalty-free
+patent license under the contributor's essential patent claims, to
+make, use, sell, offer for sale, import and otherwise run, modify and
+propagate the contents of its contributor version.
+
+ In the following three paragraphs, a "patent license" is any express
+agreement or commitment, however denominated, not to enforce a patent
+(such as an express permission to practice a patent or covenant not to
+sue for patent infringement). To "grant" such a patent license to a
+party means to make such an agreement or commitment not to enforce a
+patent against the party.
+
+ If you convey a covered work, knowingly relying on a patent license,
+and the Corresponding Source of the work is not available for anyone
+to copy, free of charge and under the terms of this License, through a
+publicly available network server or other readily accessible means,
+then you must either (1) cause the Corresponding Source to be so
+available, or (2) arrange to deprive yourself of the benefit of the
+patent license for this particular work, or (3) arrange, in a manner
+consistent with the requirements of this License, to extend the patent
+license to downstream recipients. "Knowingly relying" means you have
+actual knowledge that, but for the patent license, your conveying the
+covered work in a country, or your recipient's use of the covered work
+in a country, would infringe one or more identifiable patents in that
+country that you have reason to believe are valid.
+
+ If, pursuant to or in connection with a single transaction or
+arrangement, you convey, or propagate by procuring conveyance of, a
+covered work, and grant a patent license to some of the parties
+receiving the covered work authorizing them to use, propagate, modify
+or convey a specific copy of the covered work, then the patent license
+you grant is automatically extended to all recipients of the covered
+work and works based on it.
+
+ A patent license is "discriminatory" if it does not include within
+the scope of its coverage, prohibits the exercise of, or is
+conditioned on the non-exercise of one or more of the rights that are
+specifically granted under this License. You may not convey a covered
+work if you are a party to an arrangement with a third party that is
+in the business of distributing software, under which you make payment
+to the third party based on the extent of your activity of conveying
+the work, and under which the third party grants, to any of the
+parties who would receive the covered work from you, a discriminatory
+patent license (a) in connection with copies of the covered work
+conveyed by you (or copies made from those copies), or (b) primarily
+for and in connection with specific products or compilations that
+contain the covered work, unless you entered into that arrangement,
+or that patent license was granted, prior to 28 March 2007.
+
+ Nothing in this License shall be construed as excluding or limiting
+any implied license or other defenses to infringement that may
+otherwise be available to you under applicable patent law.
+
+ 12. No Surrender of Others' Freedom.
+
+ If conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License. If you cannot convey a
+covered work so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you may
+not convey it at all. For example, if you agree to terms that obligate you
+to collect a royalty for further conveying from those to whom you convey
+the Program, the only way you could satisfy both those terms and this
+License would be to refrain entirely from conveying the Program.
+
+ 13. Use with the GNU Affero General Public License.
+
+ Notwithstanding any other provision of this License, you have
+permission to link or combine any covered work with a work licensed
+under version 3 of the GNU Affero General Public License into a single
+combined work, and to convey the resulting work. The terms of this
+License will continue to apply to the part which is the covered work,
+but the special requirements of the GNU Affero General Public License,
+section 13, concerning interaction through a network will apply to the
+combination as such.
+
+ 14. Revised Versions of this License.
+
+ The Free Software Foundation may publish revised and/or new versions of
+the GNU General Public License from time to time. Such new versions will
+be similar in spirit to the present version, but may differ in detail to
+address new problems or concerns.
+
+ Each version is given a distinguishing version number. If the
+Program specifies that a certain numbered version of the GNU General
+Public License "or any later version" applies to it, you have the
+option of following the terms and conditions either of that numbered
+version or of any later version published by the Free Software
+Foundation. If the Program does not specify a version number of the
+GNU General Public License, you may choose any version ever published
+by the Free Software Foundation.
+
+ If the Program specifies that a proxy can decide which future
+versions of the GNU General Public License can be used, that proxy's
+public statement of acceptance of a version permanently authorizes you
+to choose that version for the Program.
+
+ Later license versions may give you additional or different
+permissions. However, no additional obligations are imposed on any
+author or copyright holder as a result of your choosing to follow a
+later version.
+
+ 15. Disclaimer of Warranty.
+
+ THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY
+APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT
+HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY
+OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO,
+THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM
+IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF
+ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
+
+ 16. Limitation of Liability.
+
+ IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS
+THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY
+GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE
+USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF
+DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD
+PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS),
+EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF
+SUCH DAMAGES.
+
+ 17. Interpretation of Sections 15 and 16.
+
+ If the disclaimer of warranty and limitation of liability provided
+above cannot be given local legal effect according to their terms,
+reviewing courts shall apply local law that most closely approximates
+an absolute waiver of all civil liability in connection with the
+Program, unless a warranty or assumption of liability accompanies a
+copy of the Program in return for a fee.
+
+ END OF TERMS AND CONDITIONS
+
+ How to Apply These Terms to Your New Programs
+
+ If you develop a new program, and you want it to be of the greatest
+possible use to the public, the best way to achieve this is to make it
+free software which everyone can redistribute and change under these terms.
+
+ To do so, attach the following notices to the program. It is safest
+to attach them to the start of each source file to most effectively
+state the exclusion of warranty; and each file should have at least
+the "copyright" line and a pointer to where the full notice is found.
+
+
+ Copyright (C)
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see .
+
+Also add information on how to contact you by electronic and paper mail.
+
+ If the program does terminal interaction, make it output a short
+notice like this when it starts in an interactive mode:
+
+ Copyright (C)
+ This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
+ This is free software, and you are welcome to redistribute it
+ under certain conditions; type `show c' for details.
+
+The hypothetical commands `show w' and `show c' should show the appropriate
+parts of the General Public License. Of course, your program's commands
+might be different; for a GUI interface, you would use an "about box".
+
+ You should also get your employer (if you work as a programmer) or school,
+if any, to sign a "copyright disclaimer" for the program, if necessary.
+For more information on this, and how to apply and follow the GNU GPL, see
+.
+
+ The GNU General Public License does not permit incorporating your program
+into proprietary programs. If your program is a subroutine library, you
+may consider it more useful to permit linking proprietary applications with
+the library. If this is what you want to do, use the GNU Lesser General
+Public License instead of this License. But first, please read
+.
diff --git a/modules/sale_discount/MANIFEST.in b/modules/sale_discount/MANIFEST.in
new file mode 100644
index 0000000000..e88b2348a3
--- /dev/null
+++ b/modules/sale_discount/MANIFEST.in
@@ -0,0 +1,5 @@
+include CHANGELOG
+include COPYRIGHT
+include LICENSE
+include README.rst
+include doc/*
diff --git a/modules/sale_discount/README.rst b/modules/sale_discount/README.rst
new file mode 120000
index 0000000000..176d9c2695
--- /dev/null
+++ b/modules/sale_discount/README.rst
@@ -0,0 +1 @@
+doc/index.rst
\ No newline at end of file
diff --git a/modules/sale_discount/__init__.py b/modules/sale_discount/__init__.py
new file mode 100644
index 0000000000..31fb0fd597
--- /dev/null
+++ b/modules/sale_discount/__init__.py
@@ -0,0 +1,18 @@
+# This file is part of Tryton. The COPYRIGHT file at the top level of
+# this repository contains the full copyright notices and license terms.
+
+from trytond.pool import Pool
+
+from . import sale
+
+__all__ = ['register']
+
+
+def register():
+ Pool.register(
+ sale.Line,
+ module='sale_discount', type_='model')
+ Pool.register(
+ module='sale_discount', type_='wizard')
+ Pool.register(
+ module='sale_discount', type_='report')
diff --git a/modules/sale_discount/doc/index.rst b/modules/sale_discount/doc/index.rst
new file mode 100644
index 0000000000..84d56a3282
--- /dev/null
+++ b/modules/sale_discount/doc/index.rst
@@ -0,0 +1,8 @@
+Sale Discount Module
+####################
+
+The sale_discount module adds discount on sale line.
+
+Two discount fields are added to the sale line to define a discount as rate and
+as amount between a base price and the unit price.
+The base price is filled automatically with the list price of the product.
diff --git a/modules/sale_discount/locale/bg.po b/modules/sale_discount/locale/bg.po
new file mode 100644
index 0000000000..c18f45b463
--- /dev/null
+++ b/modules/sale_discount/locale/bg.po
@@ -0,0 +1,27 @@
+#
+msgid ""
+msgstr "Content-Type: text/plain; charset=utf-8\n"
+
+msgctxt "field:sale.line,base_price:"
+msgid "Base Price"
+msgstr ""
+
+msgctxt "field:sale.line,discount:"
+msgid "Discount"
+msgstr ""
+
+msgctxt "field:sale.line,discount_amount:"
+msgid "Discount Amount"
+msgstr ""
+
+msgctxt "field:sale.line,discount_rate:"
+msgid "Discount Rate"
+msgstr ""
+
+msgctxt "view:sale.line:"
+msgid "%"
+msgstr ""
+
+msgctxt "view:sale.line:"
+msgid "Discount"
+msgstr ""
diff --git a/modules/sale_discount/locale/ca.po b/modules/sale_discount/locale/ca.po
new file mode 100644
index 0000000000..42a047f5b1
--- /dev/null
+++ b/modules/sale_discount/locale/ca.po
@@ -0,0 +1,27 @@
+#
+msgid ""
+msgstr "Content-Type: text/plain; charset=utf-8\n"
+
+msgctxt "field:sale.line,base_price:"
+msgid "Base Price"
+msgstr "Preu base"
+
+msgctxt "field:sale.line,discount:"
+msgid "Discount"
+msgstr "Descompte"
+
+msgctxt "field:sale.line,discount_amount:"
+msgid "Discount Amount"
+msgstr "Import descompte"
+
+msgctxt "field:sale.line,discount_rate:"
+msgid "Discount Rate"
+msgstr "% Descompte"
+
+msgctxt "view:sale.line:"
+msgid "%"
+msgstr "%"
+
+msgctxt "view:sale.line:"
+msgid "Discount"
+msgstr "Descompte"
diff --git a/modules/sale_discount/locale/cs.po b/modules/sale_discount/locale/cs.po
new file mode 100644
index 0000000000..c18f45b463
--- /dev/null
+++ b/modules/sale_discount/locale/cs.po
@@ -0,0 +1,27 @@
+#
+msgid ""
+msgstr "Content-Type: text/plain; charset=utf-8\n"
+
+msgctxt "field:sale.line,base_price:"
+msgid "Base Price"
+msgstr ""
+
+msgctxt "field:sale.line,discount:"
+msgid "Discount"
+msgstr ""
+
+msgctxt "field:sale.line,discount_amount:"
+msgid "Discount Amount"
+msgstr ""
+
+msgctxt "field:sale.line,discount_rate:"
+msgid "Discount Rate"
+msgstr ""
+
+msgctxt "view:sale.line:"
+msgid "%"
+msgstr ""
+
+msgctxt "view:sale.line:"
+msgid "Discount"
+msgstr ""
diff --git a/modules/sale_discount/locale/de.po b/modules/sale_discount/locale/de.po
new file mode 100644
index 0000000000..c10cfa0f54
--- /dev/null
+++ b/modules/sale_discount/locale/de.po
@@ -0,0 +1,27 @@
+#
+msgid ""
+msgstr "Content-Type: text/plain; charset=utf-8\n"
+
+msgctxt "field:sale.line,base_price:"
+msgid "Base Price"
+msgstr "Basispreis"
+
+msgctxt "field:sale.line,discount:"
+msgid "Discount"
+msgstr "Rabatt"
+
+msgctxt "field:sale.line,discount_amount:"
+msgid "Discount Amount"
+msgstr "Rabattbetrag"
+
+msgctxt "field:sale.line,discount_rate:"
+msgid "Discount Rate"
+msgstr "Rabattsatz"
+
+msgctxt "view:sale.line:"
+msgid "%"
+msgstr "%"
+
+msgctxt "view:sale.line:"
+msgid "Discount"
+msgstr "Rabatt"
diff --git a/modules/sale_discount/locale/es.po b/modules/sale_discount/locale/es.po
new file mode 100644
index 0000000000..c315cadb9a
--- /dev/null
+++ b/modules/sale_discount/locale/es.po
@@ -0,0 +1,27 @@
+#
+msgid ""
+msgstr "Content-Type: text/plain; charset=utf-8\n"
+
+msgctxt "field:sale.line,base_price:"
+msgid "Base Price"
+msgstr "Precio base"
+
+msgctxt "field:sale.line,discount:"
+msgid "Discount"
+msgstr "Descuento"
+
+msgctxt "field:sale.line,discount_amount:"
+msgid "Discount Amount"
+msgstr "Importe descuento"
+
+msgctxt "field:sale.line,discount_rate:"
+msgid "Discount Rate"
+msgstr "% Descuento"
+
+msgctxt "view:sale.line:"
+msgid "%"
+msgstr "%"
+
+msgctxt "view:sale.line:"
+msgid "Discount"
+msgstr "Descuento"
diff --git a/modules/sale_discount/locale/es_419.po b/modules/sale_discount/locale/es_419.po
new file mode 100644
index 0000000000..c18f45b463
--- /dev/null
+++ b/modules/sale_discount/locale/es_419.po
@@ -0,0 +1,27 @@
+#
+msgid ""
+msgstr "Content-Type: text/plain; charset=utf-8\n"
+
+msgctxt "field:sale.line,base_price:"
+msgid "Base Price"
+msgstr ""
+
+msgctxt "field:sale.line,discount:"
+msgid "Discount"
+msgstr ""
+
+msgctxt "field:sale.line,discount_amount:"
+msgid "Discount Amount"
+msgstr ""
+
+msgctxt "field:sale.line,discount_rate:"
+msgid "Discount Rate"
+msgstr ""
+
+msgctxt "view:sale.line:"
+msgid "%"
+msgstr ""
+
+msgctxt "view:sale.line:"
+msgid "Discount"
+msgstr ""
diff --git a/modules/sale_discount/locale/et.po b/modules/sale_discount/locale/et.po
new file mode 100644
index 0000000000..c18f45b463
--- /dev/null
+++ b/modules/sale_discount/locale/et.po
@@ -0,0 +1,27 @@
+#
+msgid ""
+msgstr "Content-Type: text/plain; charset=utf-8\n"
+
+msgctxt "field:sale.line,base_price:"
+msgid "Base Price"
+msgstr ""
+
+msgctxt "field:sale.line,discount:"
+msgid "Discount"
+msgstr ""
+
+msgctxt "field:sale.line,discount_amount:"
+msgid "Discount Amount"
+msgstr ""
+
+msgctxt "field:sale.line,discount_rate:"
+msgid "Discount Rate"
+msgstr ""
+
+msgctxt "view:sale.line:"
+msgid "%"
+msgstr ""
+
+msgctxt "view:sale.line:"
+msgid "Discount"
+msgstr ""
diff --git a/modules/sale_discount/locale/fa.po b/modules/sale_discount/locale/fa.po
new file mode 100644
index 0000000000..c18f45b463
--- /dev/null
+++ b/modules/sale_discount/locale/fa.po
@@ -0,0 +1,27 @@
+#
+msgid ""
+msgstr "Content-Type: text/plain; charset=utf-8\n"
+
+msgctxt "field:sale.line,base_price:"
+msgid "Base Price"
+msgstr ""
+
+msgctxt "field:sale.line,discount:"
+msgid "Discount"
+msgstr ""
+
+msgctxt "field:sale.line,discount_amount:"
+msgid "Discount Amount"
+msgstr ""
+
+msgctxt "field:sale.line,discount_rate:"
+msgid "Discount Rate"
+msgstr ""
+
+msgctxt "view:sale.line:"
+msgid "%"
+msgstr ""
+
+msgctxt "view:sale.line:"
+msgid "Discount"
+msgstr ""
diff --git a/modules/sale_discount/locale/fi.po b/modules/sale_discount/locale/fi.po
new file mode 100644
index 0000000000..c18f45b463
--- /dev/null
+++ b/modules/sale_discount/locale/fi.po
@@ -0,0 +1,27 @@
+#
+msgid ""
+msgstr "Content-Type: text/plain; charset=utf-8\n"
+
+msgctxt "field:sale.line,base_price:"
+msgid "Base Price"
+msgstr ""
+
+msgctxt "field:sale.line,discount:"
+msgid "Discount"
+msgstr ""
+
+msgctxt "field:sale.line,discount_amount:"
+msgid "Discount Amount"
+msgstr ""
+
+msgctxt "field:sale.line,discount_rate:"
+msgid "Discount Rate"
+msgstr ""
+
+msgctxt "view:sale.line:"
+msgid "%"
+msgstr ""
+
+msgctxt "view:sale.line:"
+msgid "Discount"
+msgstr ""
diff --git a/modules/sale_discount/locale/fr.po b/modules/sale_discount/locale/fr.po
new file mode 100644
index 0000000000..facaea7c37
--- /dev/null
+++ b/modules/sale_discount/locale/fr.po
@@ -0,0 +1,27 @@
+#
+msgid ""
+msgstr "Content-Type: text/plain; charset=utf-8\n"
+
+msgctxt "field:sale.line,base_price:"
+msgid "Base Price"
+msgstr "Prix de base"
+
+msgctxt "field:sale.line,discount:"
+msgid "Discount"
+msgstr "Remise"
+
+msgctxt "field:sale.line,discount_amount:"
+msgid "Discount Amount"
+msgstr "Montant de la remise"
+
+msgctxt "field:sale.line,discount_rate:"
+msgid "Discount Rate"
+msgstr "Taux de remise"
+
+msgctxt "view:sale.line:"
+msgid "%"
+msgstr "%"
+
+msgctxt "view:sale.line:"
+msgid "Discount"
+msgstr "Remise"
diff --git a/modules/sale_discount/locale/hu.po b/modules/sale_discount/locale/hu.po
new file mode 100644
index 0000000000..873b5c6c55
--- /dev/null
+++ b/modules/sale_discount/locale/hu.po
@@ -0,0 +1,27 @@
+#
+msgid ""
+msgstr "Content-Type: text/plain; charset=utf-8\n"
+
+msgctxt "field:sale.line,base_price:"
+msgid "Base Price"
+msgstr "Alapár"
+
+msgctxt "field:sale.line,discount:"
+msgid "Discount"
+msgstr "Engedmény"
+
+msgctxt "field:sale.line,discount_amount:"
+msgid "Discount Amount"
+msgstr "Engedmény (összeg)"
+
+msgctxt "field:sale.line,discount_rate:"
+msgid "Discount Rate"
+msgstr "Engedmény (%)"
+
+msgctxt "view:sale.line:"
+msgid "%"
+msgstr "%"
+
+msgctxt "view:sale.line:"
+msgid "Discount"
+msgstr "Engedmény"
diff --git a/modules/sale_discount/locale/id.po b/modules/sale_discount/locale/id.po
new file mode 100644
index 0000000000..c18f45b463
--- /dev/null
+++ b/modules/sale_discount/locale/id.po
@@ -0,0 +1,27 @@
+#
+msgid ""
+msgstr "Content-Type: text/plain; charset=utf-8\n"
+
+msgctxt "field:sale.line,base_price:"
+msgid "Base Price"
+msgstr ""
+
+msgctxt "field:sale.line,discount:"
+msgid "Discount"
+msgstr ""
+
+msgctxt "field:sale.line,discount_amount:"
+msgid "Discount Amount"
+msgstr ""
+
+msgctxt "field:sale.line,discount_rate:"
+msgid "Discount Rate"
+msgstr ""
+
+msgctxt "view:sale.line:"
+msgid "%"
+msgstr ""
+
+msgctxt "view:sale.line:"
+msgid "Discount"
+msgstr ""
diff --git a/modules/sale_discount/locale/it.po b/modules/sale_discount/locale/it.po
new file mode 100644
index 0000000000..c18f45b463
--- /dev/null
+++ b/modules/sale_discount/locale/it.po
@@ -0,0 +1,27 @@
+#
+msgid ""
+msgstr "Content-Type: text/plain; charset=utf-8\n"
+
+msgctxt "field:sale.line,base_price:"
+msgid "Base Price"
+msgstr ""
+
+msgctxt "field:sale.line,discount:"
+msgid "Discount"
+msgstr ""
+
+msgctxt "field:sale.line,discount_amount:"
+msgid "Discount Amount"
+msgstr ""
+
+msgctxt "field:sale.line,discount_rate:"
+msgid "Discount Rate"
+msgstr ""
+
+msgctxt "view:sale.line:"
+msgid "%"
+msgstr ""
+
+msgctxt "view:sale.line:"
+msgid "Discount"
+msgstr ""
diff --git a/modules/sale_discount/locale/lo.po b/modules/sale_discount/locale/lo.po
new file mode 100644
index 0000000000..c18f45b463
--- /dev/null
+++ b/modules/sale_discount/locale/lo.po
@@ -0,0 +1,27 @@
+#
+msgid ""
+msgstr "Content-Type: text/plain; charset=utf-8\n"
+
+msgctxt "field:sale.line,base_price:"
+msgid "Base Price"
+msgstr ""
+
+msgctxt "field:sale.line,discount:"
+msgid "Discount"
+msgstr ""
+
+msgctxt "field:sale.line,discount_amount:"
+msgid "Discount Amount"
+msgstr ""
+
+msgctxt "field:sale.line,discount_rate:"
+msgid "Discount Rate"
+msgstr ""
+
+msgctxt "view:sale.line:"
+msgid "%"
+msgstr ""
+
+msgctxt "view:sale.line:"
+msgid "Discount"
+msgstr ""
diff --git a/modules/sale_discount/locale/lt.po b/modules/sale_discount/locale/lt.po
new file mode 100644
index 0000000000..c18f45b463
--- /dev/null
+++ b/modules/sale_discount/locale/lt.po
@@ -0,0 +1,27 @@
+#
+msgid ""
+msgstr "Content-Type: text/plain; charset=utf-8\n"
+
+msgctxt "field:sale.line,base_price:"
+msgid "Base Price"
+msgstr ""
+
+msgctxt "field:sale.line,discount:"
+msgid "Discount"
+msgstr ""
+
+msgctxt "field:sale.line,discount_amount:"
+msgid "Discount Amount"
+msgstr ""
+
+msgctxt "field:sale.line,discount_rate:"
+msgid "Discount Rate"
+msgstr ""
+
+msgctxt "view:sale.line:"
+msgid "%"
+msgstr ""
+
+msgctxt "view:sale.line:"
+msgid "Discount"
+msgstr ""
diff --git a/modules/sale_discount/locale/nl.po b/modules/sale_discount/locale/nl.po
new file mode 100644
index 0000000000..2e111c34ae
--- /dev/null
+++ b/modules/sale_discount/locale/nl.po
@@ -0,0 +1,27 @@
+#
+msgid ""
+msgstr "Content-Type: text/plain; charset=utf-8\n"
+
+msgctxt "field:sale.line,base_price:"
+msgid "Base Price"
+msgstr "Basisprijs"
+
+msgctxt "field:sale.line,discount:"
+msgid "Discount"
+msgstr "Korting"
+
+msgctxt "field:sale.line,discount_amount:"
+msgid "Discount Amount"
+msgstr "Korting hoeveelheid"
+
+msgctxt "field:sale.line,discount_rate:"
+msgid "Discount Rate"
+msgstr "Kortingspercentage"
+
+msgctxt "view:sale.line:"
+msgid "%"
+msgstr "%"
+
+msgctxt "view:sale.line:"
+msgid "Discount"
+msgstr "Korting"
diff --git a/modules/sale_discount/locale/pl.po b/modules/sale_discount/locale/pl.po
new file mode 100644
index 0000000000..b9f2e04070
--- /dev/null
+++ b/modules/sale_discount/locale/pl.po
@@ -0,0 +1,27 @@
+#
+msgid ""
+msgstr "Content-Type: text/plain; charset=utf-8\n"
+
+msgctxt "field:sale.line,base_price:"
+msgid "Base Price"
+msgstr "Cena podstawowa"
+
+msgctxt "field:sale.line,discount:"
+msgid "Discount"
+msgstr "Rabat"
+
+msgctxt "field:sale.line,discount_amount:"
+msgid "Discount Amount"
+msgstr "Wartość rabatu"
+
+msgctxt "field:sale.line,discount_rate:"
+msgid "Discount Rate"
+msgstr "Wysokość rabatu"
+
+msgctxt "view:sale.line:"
+msgid "%"
+msgstr "%"
+
+msgctxt "view:sale.line:"
+msgid "Discount"
+msgstr "Rabat"
diff --git a/modules/sale_discount/locale/pt.po b/modules/sale_discount/locale/pt.po
new file mode 100644
index 0000000000..c18f45b463
--- /dev/null
+++ b/modules/sale_discount/locale/pt.po
@@ -0,0 +1,27 @@
+#
+msgid ""
+msgstr "Content-Type: text/plain; charset=utf-8\n"
+
+msgctxt "field:sale.line,base_price:"
+msgid "Base Price"
+msgstr ""
+
+msgctxt "field:sale.line,discount:"
+msgid "Discount"
+msgstr ""
+
+msgctxt "field:sale.line,discount_amount:"
+msgid "Discount Amount"
+msgstr ""
+
+msgctxt "field:sale.line,discount_rate:"
+msgid "Discount Rate"
+msgstr ""
+
+msgctxt "view:sale.line:"
+msgid "%"
+msgstr ""
+
+msgctxt "view:sale.line:"
+msgid "Discount"
+msgstr ""
diff --git a/modules/sale_discount/locale/ro.po b/modules/sale_discount/locale/ro.po
new file mode 100644
index 0000000000..c18f45b463
--- /dev/null
+++ b/modules/sale_discount/locale/ro.po
@@ -0,0 +1,27 @@
+#
+msgid ""
+msgstr "Content-Type: text/plain; charset=utf-8\n"
+
+msgctxt "field:sale.line,base_price:"
+msgid "Base Price"
+msgstr ""
+
+msgctxt "field:sale.line,discount:"
+msgid "Discount"
+msgstr ""
+
+msgctxt "field:sale.line,discount_amount:"
+msgid "Discount Amount"
+msgstr ""
+
+msgctxt "field:sale.line,discount_rate:"
+msgid "Discount Rate"
+msgstr ""
+
+msgctxt "view:sale.line:"
+msgid "%"
+msgstr ""
+
+msgctxt "view:sale.line:"
+msgid "Discount"
+msgstr ""
diff --git a/modules/sale_discount/locale/ru.po b/modules/sale_discount/locale/ru.po
new file mode 100644
index 0000000000..c18f45b463
--- /dev/null
+++ b/modules/sale_discount/locale/ru.po
@@ -0,0 +1,27 @@
+#
+msgid ""
+msgstr "Content-Type: text/plain; charset=utf-8\n"
+
+msgctxt "field:sale.line,base_price:"
+msgid "Base Price"
+msgstr ""
+
+msgctxt "field:sale.line,discount:"
+msgid "Discount"
+msgstr ""
+
+msgctxt "field:sale.line,discount_amount:"
+msgid "Discount Amount"
+msgstr ""
+
+msgctxt "field:sale.line,discount_rate:"
+msgid "Discount Rate"
+msgstr ""
+
+msgctxt "view:sale.line:"
+msgid "%"
+msgstr ""
+
+msgctxt "view:sale.line:"
+msgid "Discount"
+msgstr ""
diff --git a/modules/sale_discount/locale/sl.po b/modules/sale_discount/locale/sl.po
new file mode 100644
index 0000000000..c18f45b463
--- /dev/null
+++ b/modules/sale_discount/locale/sl.po
@@ -0,0 +1,27 @@
+#
+msgid ""
+msgstr "Content-Type: text/plain; charset=utf-8\n"
+
+msgctxt "field:sale.line,base_price:"
+msgid "Base Price"
+msgstr ""
+
+msgctxt "field:sale.line,discount:"
+msgid "Discount"
+msgstr ""
+
+msgctxt "field:sale.line,discount_amount:"
+msgid "Discount Amount"
+msgstr ""
+
+msgctxt "field:sale.line,discount_rate:"
+msgid "Discount Rate"
+msgstr ""
+
+msgctxt "view:sale.line:"
+msgid "%"
+msgstr ""
+
+msgctxt "view:sale.line:"
+msgid "Discount"
+msgstr ""
diff --git a/modules/sale_discount/locale/tr.po b/modules/sale_discount/locale/tr.po
new file mode 100644
index 0000000000..c18f45b463
--- /dev/null
+++ b/modules/sale_discount/locale/tr.po
@@ -0,0 +1,27 @@
+#
+msgid ""
+msgstr "Content-Type: text/plain; charset=utf-8\n"
+
+msgctxt "field:sale.line,base_price:"
+msgid "Base Price"
+msgstr ""
+
+msgctxt "field:sale.line,discount:"
+msgid "Discount"
+msgstr ""
+
+msgctxt "field:sale.line,discount_amount:"
+msgid "Discount Amount"
+msgstr ""
+
+msgctxt "field:sale.line,discount_rate:"
+msgid "Discount Rate"
+msgstr ""
+
+msgctxt "view:sale.line:"
+msgid "%"
+msgstr ""
+
+msgctxt "view:sale.line:"
+msgid "Discount"
+msgstr ""
diff --git a/modules/sale_discount/locale/zh_CN.po b/modules/sale_discount/locale/zh_CN.po
new file mode 100644
index 0000000000..c18f45b463
--- /dev/null
+++ b/modules/sale_discount/locale/zh_CN.po
@@ -0,0 +1,27 @@
+#
+msgid ""
+msgstr "Content-Type: text/plain; charset=utf-8\n"
+
+msgctxt "field:sale.line,base_price:"
+msgid "Base Price"
+msgstr ""
+
+msgctxt "field:sale.line,discount:"
+msgid "Discount"
+msgstr ""
+
+msgctxt "field:sale.line,discount_amount:"
+msgid "Discount Amount"
+msgstr ""
+
+msgctxt "field:sale.line,discount_rate:"
+msgid "Discount Rate"
+msgstr ""
+
+msgctxt "view:sale.line:"
+msgid "%"
+msgstr ""
+
+msgctxt "view:sale.line:"
+msgid "Discount"
+msgstr ""
diff --git a/modules/sale_discount/sale.py b/modules/sale_discount/sale.py
new file mode 100644
index 0000000000..16da631e18
--- /dev/null
+++ b/modules/sale_discount/sale.py
@@ -0,0 +1,150 @@
+# This file is part of Tryton. The COPYRIGHT file at the top level of
+# this repository contains the full copyright notices and license terms.
+from decimal import Decimal
+
+from trytond.model import fields
+from trytond.pool import PoolMeta, Pool
+from trytond.pyson import Eval
+
+from trytond.modules.product import price_digits, round_price
+
+
+class Line(metaclass=PoolMeta):
+ __name__ = 'sale.line'
+
+ base_price = fields.Numeric(
+ "Base Price", digits=price_digits,
+ states={
+ 'invisible': Eval('type') != 'line',
+ 'readonly': Eval('sale_state') != 'draft',
+ },
+ depends=['type', 'sale_state'])
+
+ discount_rate = fields.Function(fields.Numeric(
+ "Discount Rate", digits=(16, 4),
+ states={
+ 'invisible': Eval('type') != 'line',
+ 'readonly': Eval('sale_state') != 'draft',
+ },
+ depends=['type', 'sale_state']),
+ 'on_change_with_discount_rate', setter='set_discount_rate')
+ discount_amount = fields.Function(fields.Numeric(
+ "Discount Amount", digits=price_digits,
+ states={
+ 'invisible': Eval('type') != 'line',
+ 'readonly': Eval('sale_state') != 'draft',
+ },
+ depends=['type', 'sale_state']),
+ 'on_change_with_discount_amount', setter='set_discount_amount')
+
+ discount = fields.Function(fields.Char(
+ "Discount",
+ states={
+ 'invisible': ~Eval('discount'),
+ }),
+ 'on_change_with_discount')
+
+ @fields.depends(
+ methods=[
+ 'compute_base_price', 'on_change_with_discount_rate',
+ 'on_change_with_discount_amount', 'on_change_with_discount'])
+ def on_change_product(self):
+ super().on_change_product()
+ if self.product:
+ self.base_price = self.compute_base_price()
+ self.discount_rate = self.on_change_with_discount_rate()
+ self.discount_amount = self.on_change_with_discount_amount()
+ self.discount = self.on_change_with_discount()
+
+ @fields.depends('product', 'unit')
+ def compute_base_price(self):
+ pool = Pool()
+ Uom = pool.get('product.uom')
+ if self.product:
+ price = self.product.list_price
+ if self.unit:
+ price = Uom.compute_price(
+ self.product.default_uom, price, self.unit)
+ return round_price(price)
+
+ @fields.depends(
+ methods=[
+ 'compute_base_price', 'on_change_with_discount_rate',
+ 'on_change_with_discount_amount', 'on_change_with_discount'])
+ def on_change_quantity(self):
+ super().on_change_quantity()
+ self.base_price = self.compute_base_price()
+ self.discount_rate = self.on_change_with_discount_rate()
+ self.discount_amount = self.on_change_with_discount_amount()
+ self.discount = self.on_change_with_discount()
+
+ @fields.depends('unit_price', 'base_price')
+ def on_change_with_discount_rate(self, name=None):
+ if self.unit_price is None or not self.base_price:
+ return
+ rate = 1 - self.unit_price / self.base_price
+ return rate.quantize(
+ Decimal(1) / 10 ** self.__class__.discount_rate.digits[1])
+
+ @fields.depends(
+ 'base_price', 'discount_rate',
+ methods=['on_change_with_discount_amount', 'on_change_with_discount',
+ 'on_change_with_amount'])
+ def on_change_discount_rate(self):
+ if self.base_price is not None and self.discount_rate is not None:
+ self.unit_price = round_price(
+ self.base_price * (1 - self.discount_rate))
+ self.discount_amount = self.on_change_with_discount_amount()
+ self.discount = self.on_change_with_discount()
+ self.amount = self.on_change_with_amount()
+
+ @classmethod
+ def set_discount_rate(cls, lines, name, value):
+ pass
+
+ @fields.depends('unit_price', 'base_price')
+ def on_change_with_discount_amount(self, name=None):
+ if self.unit_price is None or self.base_price is None:
+ return
+ return round_price(self.base_price - self.unit_price)
+
+ @fields.depends(
+ 'base_price', 'discount_amount',
+ methods=['on_change_with_discount_rate', 'on_change_with_discount',
+ 'on_change_with_amount'])
+ def on_change_discount_amount(self):
+ if self.base_price is not None and self.discount_amount is not None:
+ self.unit_price = round_price(
+ self.base_price - self.discount_amount)
+ self.discount_rate = self.on_change_with_discount_rate()
+ self.discount = self.on_change_with_discount()
+ self.amount = self.on_change_with_amount()
+
+ @classmethod
+ def set_discount_amount(cls, lines, name, value):
+ pass
+
+ @fields.depends(
+ 'sale', '_parent_sale.currency',
+ methods=[
+ 'on_change_with_discount_rate', 'on_change_with_discount_amount'])
+ def on_change_with_discount(self, name=None):
+ pool = Pool()
+ Lang = pool.get('ir.lang')
+ lang = Lang.get()
+ rate = self.on_change_with_discount_rate()
+ if not rate or rate % Decimal('0.01'):
+ amount = self.on_change_with_discount_amount()
+ if amount:
+ return lang.currency(
+ amount, self.sale.currency, digits=price_digits[1])
+ else:
+ return lang.format('%i', rate * 100) + '%'
+
+ @classmethod
+ def view_attributes(cls):
+ return super().view_attributes() + [
+ ('/form//label[@id="discount"]', 'states', {
+ 'invisible': Eval('type') != 'line',
+ }, ['type']),
+ ]
diff --git a/modules/sale_discount/sale.xml b/modules/sale_discount/sale.xml
new file mode 100644
index 0000000000..94d358912d
--- /dev/null
+++ b/modules/sale_discount/sale.xml
@@ -0,0 +1,24 @@
+
+
+
+
+
+ sale.line
+
+ sale_line_form
+
+
+
+ sale.line
+
+ sale_line_list
+
+
+
+ sale.line
+
+ sale_line_list
+
+
+
diff --git a/modules/sale_discount/setup.py b/modules/sale_discount/setup.py
new file mode 100755
index 0000000000..60c1ff46d7
--- /dev/null
+++ b/modules/sale_discount/setup.py
@@ -0,0 +1,153 @@
+#!/usr/bin/env python3
+# This file is part of Tryton. The COPYRIGHT file at the top level of
+# this repository contains the full copyright notices and license terms.
+
+import io
+import os
+import re
+from configparser import ConfigParser
+from setuptools import setup, find_packages
+
+
+def read(fname, slice=None):
+ content = io.open(
+ os.path.join(os.path.dirname(__file__), fname),
+ 'r', encoding='utf-8').read()
+ if slice:
+ content = '\n'.join(content.splitlines()[slice])
+ return content
+
+
+def get_require_version(name):
+ if minor_version % 2:
+ require = '%s >= %s.%s.dev0, < %s.%s'
+ else:
+ require = '%s >= %s.%s, < %s.%s'
+ require %= (name, major_version, minor_version,
+ major_version, minor_version + 1)
+ return require
+
+
+config = ConfigParser()
+config.read_file(open(os.path.join(os.path.dirname(__file__), 'tryton.cfg')))
+info = dict(config.items('tryton'))
+for key in ('depends', 'extras_depend', 'xml'):
+ if key in info:
+ info[key] = info[key].strip().splitlines()
+version = info.get('version', '0.0.1')
+major_version, minor_version, _ = version.split('.', 2)
+major_version = int(major_version)
+minor_version = int(minor_version)
+name = 'trytond_sale_discount'
+
+download_url = 'http://downloads.tryton.org/%s.%s/' % (
+ major_version, minor_version)
+if minor_version % 2:
+ version = '%s.%s.dev0' % (major_version, minor_version)
+ download_url = (
+ 'hg+http://hg.tryton.org/modules/%s#egg=%s-%s' % (
+ name[8:], name, version))
+local_version = []
+if os.environ.get('CI_JOB_ID'):
+ local_version.append(os.environ['CI_JOB_ID'])
+else:
+ for build in ['CI_BUILD_NUMBER', 'CI_JOB_NUMBER']:
+ if os.environ.get(build):
+ local_version.append(os.environ[build])
+ else:
+ local_version = []
+ break
+if local_version:
+ version += '+' + '.'.join(local_version)
+
+requires = []
+for dep in info.get('depends', []):
+ if not re.match(r'(ir|res)(\W|$)', dep):
+ requires.append(get_require_version('trytond_%s' % dep))
+requires.append(get_require_version('trytond'))
+
+tests_require = [get_require_version('proteus')]
+dependency_links = []
+if minor_version % 2:
+ dependency_links.append(
+ 'https://trydevpi.tryton.org/?local_version='
+ + '.'.join(local_version))
+
+setup(name=name,
+ version=version,
+ description='Tryton module that manages discount on sale',
+ long_description=read('README.rst'),
+ author='Tryton',
+ author_email='bugs@tryton.org',
+ url='http://www.tryton.org/',
+ download_url=download_url,
+ project_urls={
+ "Bug Tracker": 'https://bugs.tryton.org/',
+ "Documentation": 'https://docs.tryton.org/',
+ "Forum": 'https://www.tryton.org/forum',
+ "Source Code": 'https://hg.tryton.org/modules/sale_discount',
+ },
+ keywords='tryton sale discount',
+ package_dir={'trytond.modules.sale_discount': '.'},
+ packages=(
+ ['trytond.modules.sale_discount']
+ + ['trytond.modules.sale_discount.%s' % p
+ for p in find_packages()]
+ ),
+ package_data={
+ 'trytond.modules.sale_discount': (info.get('xml', [])
+ + ['tryton.cfg', 'view/*.xml', 'locale/*.po', '*.fodt',
+ 'icons/*.svg', 'tests/*.rst']),
+ },
+ classifiers=[
+ 'Development Status :: 5 - Production/Stable',
+ 'Environment :: Plugins',
+ 'Framework :: Tryton',
+ 'Intended Audience :: Developers',
+ 'Intended Audience :: Financial and Insurance Industry',
+ 'Intended Audience :: Legal Industry',
+ 'License :: OSI Approved :: '
+ 'GNU General Public License v3 or later (GPLv3+)',
+ 'Natural Language :: Bulgarian',
+ 'Natural Language :: Catalan',
+ 'Natural Language :: Chinese (Simplified)',
+ 'Natural Language :: Czech',
+ 'Natural Language :: Dutch',
+ 'Natural Language :: English',
+ 'Natural Language :: Finnish',
+ 'Natural Language :: French',
+ 'Natural Language :: German',
+ 'Natural Language :: Hungarian',
+ 'Natural Language :: Indonesian',
+ 'Natural Language :: Italian',
+ 'Natural Language :: Persian',
+ 'Natural Language :: Polish',
+ 'Natural Language :: Portuguese (Brazilian)',
+ 'Natural Language :: Romanian',
+ 'Natural Language :: Russian',
+ 'Natural Language :: Slovenian',
+ 'Natural Language :: Spanish',
+ 'Natural Language :: Turkish',
+ 'Operating System :: OS Independent',
+ 'Programming Language :: Python :: 3',
+ 'Programming Language :: Python :: 3.6',
+ 'Programming Language :: Python :: 3.7',
+ 'Programming Language :: Python :: 3.8',
+ 'Programming Language :: Python :: 3.9',
+ 'Programming Language :: Python :: Implementation :: CPython',
+ 'Programming Language :: Python :: Implementation :: PyPy',
+ 'Topic :: Office/Business',
+ ],
+ license='GPL-3',
+ python_requires='>=3.6',
+ install_requires=requires,
+ dependency_links=dependency_links,
+ zip_safe=False,
+ entry_points="""
+ [trytond.modules]
+ sale_discount = trytond.modules.sale_discount
+ """, # noqa: E501
+ test_suite='tests',
+ test_loader='trytond.test_loader:Loader',
+ tests_require=tests_require,
+ )
diff --git a/modules/sale_discount/tests/__init__.py b/modules/sale_discount/tests/__init__.py
new file mode 100644
index 0000000000..de1d175254
--- /dev/null
+++ b/modules/sale_discount/tests/__init__.py
@@ -0,0 +1,9 @@
+# This file is part of Tryton. The COPYRIGHT file at the top level of
+# this repository contains the full copyright notices and license terms.
+
+try:
+ from trytond.modules.sale_discount.tests.test_sale_discount import suite # noqa: E501
+except ImportError:
+ from .test_sale_discount import suite
+
+__all__ = ['suite']
diff --git a/modules/sale_discount/tests/scenario_sale_discount.rst b/modules/sale_discount/tests/scenario_sale_discount.rst
new file mode 100644
index 0000000000..19fcc64fbd
--- /dev/null
+++ b/modules/sale_discount/tests/scenario_sale_discount.rst
@@ -0,0 +1,83 @@
+======================
+Sale Discount Scenario
+======================
+
+Imports::
+
+ >>> from decimal import Decimal
+ >>> from proteus import Model, Wizard
+ >>> from trytond.tests.tools import activate_modules
+ >>> from trytond.modules.company.tests.tools import (
+ ... create_company, get_company)
+
+Activate modules::
+
+ >>> config = activate_modules('sale_discount')
+
+Create company::
+
+ >>> _ = create_company()
+ >>> company = get_company()
+
+Create parties::
+
+ >>> Party = Model.get('party.party')
+ >>> customer = Party(name="Customer")
+ >>> customer.save()
+
+Create product::
+
+ >>> ProductUom = Model.get('product.uom')
+ >>> unit, = ProductUom.find([('name', '=', 'Unit')])
+ >>> ProductTemplate = Model.get('product.template')
+
+ >>> template = ProductTemplate()
+ >>> template.name = 'product'
+ >>> template.default_uom = unit
+ >>> template.type = 'goods'
+ >>> template.salable = True
+ >>> template.list_price = Decimal('10')
+ >>> template.save()
+ >>> product, = template.products
+
+Create a sale::
+
+ >>> Sale = Model.get('sale.sale')
+ >>> sale = Sale()
+ >>> sale.party = customer
+ >>> line = sale.lines.new()
+ >>> line.product = product
+ >>> line.quantity = 1
+ >>> line.base_price
+ Decimal('10.0000')
+ >>> line.unit_price
+ Decimal('10.0000')
+
+Set a discount of 10%::
+
+ >>> line.discount_rate = Decimal('0.1')
+ >>> line.unit_price
+ Decimal('9.0000')
+ >>> line.discount_amount
+ Decimal('1.0000')
+ >>> line.discount
+ '10%'
+
+ >>> sale.save()
+ >>> line, = sale.lines
+ >>> line.unit_price
+ Decimal('9.0000')
+ >>> line.discount_amount
+ Decimal('1.0000')
+ >>> line.discount
+ '10%'
+
+Set a discount amount::
+
+ >>> line.discount_amount = Decimal('3.3333')
+ >>> line.unit_price
+ Decimal('6.6667')
+ >>> line.discount_rate
+ Decimal('0.3333')
+ >>> line.discount
+ '$3.3333'
diff --git a/modules/sale_discount/tests/test_sale_discount.py b/modules/sale_discount/tests/test_sale_discount.py
new file mode 100644
index 0000000000..dfa6f0bcd1
--- /dev/null
+++ b/modules/sale_discount/tests/test_sale_discount.py
@@ -0,0 +1,28 @@
+# This file is part of Tryton. The COPYRIGHT file at the top level of
+# this repository contains the full copyright notices and license terms.
+
+import unittest
+
+import doctest
+
+from trytond.tests.test_tryton import ModuleTestCase
+from trytond.tests.test_tryton import suite as test_suite
+from trytond.tests.test_tryton import doctest_teardown
+from trytond.tests.test_tryton import doctest_checker
+
+
+class SaleDiscountTestCase(ModuleTestCase):
+ 'Test Sale Discount module'
+ module = 'sale_discount'
+
+
+def suite():
+ suite = test_suite()
+ suite.addTests(unittest.TestLoader().loadTestsFromTestCase(
+ SaleDiscountTestCase))
+ suite.addTests(doctest.DocFileSuite(
+ 'scenario_sale_discount.rst',
+ tearDown=doctest_teardown, encoding='utf-8',
+ checker=doctest_checker,
+ optionflags=doctest.REPORT_ONLY_FIRST_FAILURE))
+ return suite
diff --git a/modules/sale_discount/tox.ini b/modules/sale_discount/tox.ini
new file mode 100644
index 0000000000..197496c0cb
--- /dev/null
+++ b/modules/sale_discount/tox.ini
@@ -0,0 +1,15 @@
+[tox]
+envlist = {py36,py37,py38,py39}-{sqlite,postgresql},pypy3-{sqlite,postgresql}
+
+[testenv]
+commands = {envpython} setup.py test
+deps =
+ {py36,py37,py38,py39}-postgresql: psycopg2 >= 2.5
+ pypy3-postgresql: psycopg2cffi >= 2.5
+ py36-sqlite: sqlitebck
+setenv =
+ sqlite: TRYTOND_DATABASE_URI={env:SQLITE_URI:sqlite://}
+ postgresql: TRYTOND_DATABASE_URI={env:POSTGRESQL_URI:postgresql://}
+ sqlite: DB_NAME={env:SQLITE_NAME::memory:}
+ postgresql: DB_NAME={env:POSTGRESQL_NAME:test}
+install_command = pip install --pre --find-links https://trydevpi.tryton.org/?local_version={env:CI_JOB_ID:{env:CI_BUILD_NUMBER}.{env:CI_JOB_NUMBER}} {opts} {packages}
diff --git a/modules/sale_discount/tryton.cfg b/modules/sale_discount/tryton.cfg
new file mode 100644
index 0000000000..8b30d6b8ee
--- /dev/null
+++ b/modules/sale_discount/tryton.cfg
@@ -0,0 +1,8 @@
+[tryton]
+version=6.0.2
+depends:
+ ir
+ product
+ sale
+xml:
+ sale.xml
diff --git a/modules/sale_discount/view/sale_line_form.xml b/modules/sale_discount/view/sale_line_form.xml
new file mode 100644
index 0000000000..54226d3116
--- /dev/null
+++ b/modules/sale_discount/view/sale_line_form.xml
@@ -0,0 +1,17 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/modules/sale_discount/view/sale_line_list.xml b/modules/sale_discount/view/sale_line_list.xml
new file mode 100644
index 0000000000..1e6ef2008d
--- /dev/null
+++ b/modules/sale_discount/view/sale_line_list.xml
@@ -0,0 +1,12 @@
+
+
+
+
+
+
+
+
+
+
+
diff --git a/modules/sale_extra/.drone.yml b/modules/sale_extra/.drone.yml
new file mode 100644
index 0000000000..2049d30a49
--- /dev/null
+++ b/modules/sale_extra/.drone.yml
@@ -0,0 +1,68 @@
+clone:
+ hg:
+ image: plugins/hg
+ environment:
+ - HG_SHARE_POOL=/root/.cache/hg
+ volumes:
+ - cache:/root/.cache
+
+pipeline:
+ tox:
+ image: ${IMAGE}
+ environment:
+ - CFLAGS=-O0
+ - DB_CACHE=/cache
+ - TOX_TESTENV_PASSENV=CFLAGS DB_CACHE CI_BUILD_NUMBER CI_JOB_NUMBER CI_JOB_ID
+ - POSTGRESQL_URI=postgresql://postgres@postgresql:5432/
+ commands:
+ - echo "[extensions]" >> /root/.hgrc
+ - echo "hgext.share =" >> /root/.hgrc
+ - echo "[share]" >> /root/.hgrc
+ - echo "pool = /root/.cache/hg" >> /root/.hgrc
+ - pip install tox
+ - tox -e "${TOXENV}-${DATABASE}"
+ volumes:
+ - cache:/root/.cache
+ check_dist:
+ image: ${IMAGE}
+ commands:
+ - pip install twine
+ - python setup.py sdist
+ - twine check dist/*
+
+services:
+ postgresql:
+ image: postgres
+ environment:
+ - POSTGRES_HOST_AUTH_METHOD=trust
+ command: "-c fsync=off -c synchronous_commit=off -c full_page_writes=off"
+ when:
+ matrix:
+ DATABASE: postgresql
+
+matrix:
+ include:
+ - IMAGE: python:3.6
+ TOXENV: py36
+ DATABASE: sqlite
+ - IMAGE: python:3.6
+ TOXENV: py36
+ DATABASE: postgresql
+ - IMAGE: python:3.7
+ TOXENV: py37
+ DATABASE: sqlite
+ - IMAGE: python:3.7
+ TOXENV: py37
+ DATABASE: postgresql
+ - IMAGE: python:3.8
+ TOXENV: py38
+ DATABASE: sqlite
+ - IMAGE: python:3.8
+ TOXENV: py38
+ DATABASE: postgresql
+ - IMAGE: python:3.9
+ TOXENV: py39
+ DATABASE: sqlite
+ - IMAGE: python:3.9
+ TOXENV: py39
+ DATABASE: postgresql
diff --git a/modules/sale_extra/.flake8 b/modules/sale_extra/.flake8
new file mode 100644
index 0000000000..fa6b4f66d1
--- /dev/null
+++ b/modules/sale_extra/.flake8
@@ -0,0 +1,2 @@
+[flake8]
+ignore=E123,E124,E126,E128,E741,W503
diff --git a/modules/sale_extra/CHANGELOG b/modules/sale_extra/CHANGELOG
new file mode 100644
index 0000000000..6ae9dab2bb
--- /dev/null
+++ b/modules/sale_extra/CHANGELOG
@@ -0,0 +1,44 @@
+Version 6.0.0 - 2021-05-03
+* Bug fixes (see mercurial logs for details)
+
+Version 5.8.0 - 2020-11-02
+* Bug fixes (see mercurial logs for details)
+* Remove support for Python 3.5
+
+Version 5.6.0 - 2020-05-04
+* Bug fixes (see mercurial logs for details)
+
+Version 5.4.0 - 2019-11-04
+* Bug fixes (see mercurial logs for details)
+
+Version 5.2.0 - 2019-05-06
+* Bug fixes (see mercurial logs for details)
+
+Version 5.0.0 - 2018-10-01
+* Bug fixes (see mercurial logs for details)
+* Remove support for Python 2.7
+
+Version 4.8.0 - 2018-04-23
+* Bug fixes (see mercurial logs for details)
+
+Version 4.6.0 - 2017-10-30
+* Bug fixes (see mercurial logs for details)
+
+Version 4.4.0 - 2017-05-01
+* Bug fixes (see mercurial logs for details)
+
+Version 4.2.0 - 2016-11-28
+* Bug fixes (see mercurial logs for details)
+
+Version 4.0.0 - 2016-05-02
+* Bug fixes (see mercurial logs for details)
+* Add Python3 support
+
+Version 3.8.0 - 2015-11-02
+* Bug fixes (see mercurial logs for details)
+* Add start/end date criteria
+* Remove required on price list
+* Change modification right to sale administrator group
+
+Version 3.6.0 - 2015-04-20
+* Initial release
diff --git a/modules/sale_extra/COPYRIGHT b/modules/sale_extra/COPYRIGHT
new file mode 100644
index 0000000000..3f6095d527
--- /dev/null
+++ b/modules/sale_extra/COPYRIGHT
@@ -0,0 +1,15 @@
+Copyright (C) 2015-2021 Cédric Krier.
+Copyright (C) 2015-2021 B2CK SPRL.
+
+This program is free software: you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation, either version 3 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program. If not, see .
diff --git a/modules/sale_extra/LICENSE b/modules/sale_extra/LICENSE
new file mode 100644
index 0000000000..94a9ed024d
--- /dev/null
+++ b/modules/sale_extra/LICENSE
@@ -0,0 +1,674 @@
+ GNU GENERAL PUBLIC LICENSE
+ Version 3, 29 June 2007
+
+ Copyright (C) 2007 Free Software Foundation, Inc.
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+ Preamble
+
+ The GNU General Public License is a free, copyleft license for
+software and other kinds of works.
+
+ The licenses for most software and other practical works are designed
+to take away your freedom to share and change the works. By contrast,
+the GNU General Public License is intended to guarantee your freedom to
+share and change all versions of a program--to make sure it remains free
+software for all its users. We, the Free Software Foundation, use the
+GNU General Public License for most of our software; it applies also to
+any other work released this way by its authors. You can apply it to
+your programs, too.
+
+ When we speak of free software, we are referring to freedom, not
+price. Our General Public Licenses are designed to make sure that you
+have the freedom to distribute copies of free software (and charge for
+them if you wish), that you receive source code or can get it if you
+want it, that you can change the software or use pieces of it in new
+free programs, and that you know you can do these things.
+
+ To protect your rights, we need to prevent others from denying you
+these rights or asking you to surrender the rights. Therefore, you have
+certain responsibilities if you distribute copies of the software, or if
+you modify it: responsibilities to respect the freedom of others.
+
+ For example, if you distribute copies of such a program, whether
+gratis or for a fee, you must pass on to the recipients the same
+freedoms that you received. You must make sure that they, too, receive
+or can get the source code. And you must show them these terms so they
+know their rights.
+
+ Developers that use the GNU GPL protect your rights with two steps:
+(1) assert copyright on the software, and (2) offer you this License
+giving you legal permission to copy, distribute and/or modify it.
+
+ For the developers' and authors' protection, the GPL clearly explains
+that there is no warranty for this free software. For both users' and
+authors' sake, the GPL requires that modified versions be marked as
+changed, so that their problems will not be attributed erroneously to
+authors of previous versions.
+
+ Some devices are designed to deny users access to install or run
+modified versions of the software inside them, although the manufacturer
+can do so. This is fundamentally incompatible with the aim of
+protecting users' freedom to change the software. The systematic
+pattern of such abuse occurs in the area of products for individuals to
+use, which is precisely where it is most unacceptable. Therefore, we
+have designed this version of the GPL to prohibit the practice for those
+products. If such problems arise substantially in other domains, we
+stand ready to extend this provision to those domains in future versions
+of the GPL, as needed to protect the freedom of users.
+
+ Finally, every program is threatened constantly by software patents.
+States should not allow patents to restrict development and use of
+software on general-purpose computers, but in those that do, we wish to
+avoid the special danger that patents applied to a free program could
+make it effectively proprietary. To prevent this, the GPL assures that
+patents cannot be used to render the program non-free.
+
+ The precise terms and conditions for copying, distribution and
+modification follow.
+
+ TERMS AND CONDITIONS
+
+ 0. Definitions.
+
+ "This License" refers to version 3 of the GNU General Public License.
+
+ "Copyright" also means copyright-like laws that apply to other kinds of
+works, such as semiconductor masks.
+
+ "The Program" refers to any copyrightable work licensed under this
+License. Each licensee is addressed as "you". "Licensees" and
+"recipients" may be individuals or organizations.
+
+ To "modify" a work means to copy from or adapt all or part of the work
+in a fashion requiring copyright permission, other than the making of an
+exact copy. The resulting work is called a "modified version" of the
+earlier work or a work "based on" the earlier work.
+
+ A "covered work" means either the unmodified Program or a work based
+on the Program.
+
+ To "propagate" a work means to do anything with it that, without
+permission, would make you directly or secondarily liable for
+infringement under applicable copyright law, except executing it on a
+computer or modifying a private copy. Propagation includes copying,
+distribution (with or without modification), making available to the
+public, and in some countries other activities as well.
+
+ To "convey" a work means any kind of propagation that enables other
+parties to make or receive copies. Mere interaction with a user through
+a computer network, with no transfer of a copy, is not conveying.
+
+ An interactive user interface displays "Appropriate Legal Notices"
+to the extent that it includes a convenient and prominently visible
+feature that (1) displays an appropriate copyright notice, and (2)
+tells the user that there is no warranty for the work (except to the
+extent that warranties are provided), that licensees may convey the
+work under this License, and how to view a copy of this License. If
+the interface presents a list of user commands or options, such as a
+menu, a prominent item in the list meets this criterion.
+
+ 1. Source Code.
+
+ The "source code" for a work means the preferred form of the work
+for making modifications to it. "Object code" means any non-source
+form of a work.
+
+ A "Standard Interface" means an interface that either is an official
+standard defined by a recognized standards body, or, in the case of
+interfaces specified for a particular programming language, one that
+is widely used among developers working in that language.
+
+ The "System Libraries" of an executable work include anything, other
+than the work as a whole, that (a) is included in the normal form of
+packaging a Major Component, but which is not part of that Major
+Component, and (b) serves only to enable use of the work with that
+Major Component, or to implement a Standard Interface for which an
+implementation is available to the public in source code form. A
+"Major Component", in this context, means a major essential component
+(kernel, window system, and so on) of the specific operating system
+(if any) on which the executable work runs, or a compiler used to
+produce the work, or an object code interpreter used to run it.
+
+ The "Corresponding Source" for a work in object code form means all
+the source code needed to generate, install, and (for an executable
+work) run the object code and to modify the work, including scripts to
+control those activities. However, it does not include the work's
+System Libraries, or general-purpose tools or generally available free
+programs which are used unmodified in performing those activities but
+which are not part of the work. For example, Corresponding Source
+includes interface definition files associated with source files for
+the work, and the source code for shared libraries and dynamically
+linked subprograms that the work is specifically designed to require,
+such as by intimate data communication or control flow between those
+subprograms and other parts of the work.
+
+ The Corresponding Source need not include anything that users
+can regenerate automatically from other parts of the Corresponding
+Source.
+
+ The Corresponding Source for a work in source code form is that
+same work.
+
+ 2. Basic Permissions.
+
+ All rights granted under this License are granted for the term of
+copyright on the Program, and are irrevocable provided the stated
+conditions are met. This License explicitly affirms your unlimited
+permission to run the unmodified Program. The output from running a
+covered work is covered by this License only if the output, given its
+content, constitutes a covered work. This License acknowledges your
+rights of fair use or other equivalent, as provided by copyright law.
+
+ You may make, run and propagate covered works that you do not
+convey, without conditions so long as your license otherwise remains
+in force. You may convey covered works to others for the sole purpose
+of having them make modifications exclusively for you, or provide you
+with facilities for running those works, provided that you comply with
+the terms of this License in conveying all material for which you do
+not control copyright. Those thus making or running the covered works
+for you must do so exclusively on your behalf, under your direction
+and control, on terms that prohibit them from making any copies of
+your copyrighted material outside their relationship with you.
+
+ Conveying under any other circumstances is permitted solely under
+the conditions stated below. Sublicensing is not allowed; section 10
+makes it unnecessary.
+
+ 3. Protecting Users' Legal Rights From Anti-Circumvention Law.
+
+ No covered work shall be deemed part of an effective technological
+measure under any applicable law fulfilling obligations under article
+11 of the WIPO copyright treaty adopted on 20 December 1996, or
+similar laws prohibiting or restricting circumvention of such
+measures.
+
+ When you convey a covered work, you waive any legal power to forbid
+circumvention of technological measures to the extent such circumvention
+is effected by exercising rights under this License with respect to
+the covered work, and you disclaim any intention to limit operation or
+modification of the work as a means of enforcing, against the work's
+users, your or third parties' legal rights to forbid circumvention of
+technological measures.
+
+ 4. Conveying Verbatim Copies.
+
+ You may convey verbatim copies of the Program's source code as you
+receive it, in any medium, provided that you conspicuously and
+appropriately publish on each copy an appropriate copyright notice;
+keep intact all notices stating that this License and any
+non-permissive terms added in accord with section 7 apply to the code;
+keep intact all notices of the absence of any warranty; and give all
+recipients a copy of this License along with the Program.
+
+ You may charge any price or no price for each copy that you convey,
+and you may offer support or warranty protection for a fee.
+
+ 5. Conveying Modified Source Versions.
+
+ You may convey a work based on the Program, or the modifications to
+produce it from the Program, in the form of source code under the
+terms of section 4, provided that you also meet all of these conditions:
+
+ a) The work must carry prominent notices stating that you modified
+ it, and giving a relevant date.
+
+ b) The work must carry prominent notices stating that it is
+ released under this License and any conditions added under section
+ 7. This requirement modifies the requirement in section 4 to
+ "keep intact all notices".
+
+ c) You must license the entire work, as a whole, under this
+ License to anyone who comes into possession of a copy. This
+ License will therefore apply, along with any applicable section 7
+ additional terms, to the whole of the work, and all its parts,
+ regardless of how they are packaged. This License gives no
+ permission to license the work in any other way, but it does not
+ invalidate such permission if you have separately received it.
+
+ d) If the work has interactive user interfaces, each must display
+ Appropriate Legal Notices; however, if the Program has interactive
+ interfaces that do not display Appropriate Legal Notices, your
+ work need not make them do so.
+
+ A compilation of a covered work with other separate and independent
+works, which are not by their nature extensions of the covered work,
+and which are not combined with it such as to form a larger program,
+in or on a volume of a storage or distribution medium, is called an
+"aggregate" if the compilation and its resulting copyright are not
+used to limit the access or legal rights of the compilation's users
+beyond what the individual works permit. Inclusion of a covered work
+in an aggregate does not cause this License to apply to the other
+parts of the aggregate.
+
+ 6. Conveying Non-Source Forms.
+
+ You may convey a covered work in object code form under the terms
+of sections 4 and 5, provided that you also convey the
+machine-readable Corresponding Source under the terms of this License,
+in one of these ways:
+
+ a) Convey the object code in, or embodied in, a physical product
+ (including a physical distribution medium), accompanied by the
+ Corresponding Source fixed on a durable physical medium
+ customarily used for software interchange.
+
+ b) Convey the object code in, or embodied in, a physical product
+ (including a physical distribution medium), accompanied by a
+ written offer, valid for at least three years and valid for as
+ long as you offer spare parts or customer support for that product
+ model, to give anyone who possesses the object code either (1) a
+ copy of the Corresponding Source for all the software in the
+ product that is covered by this License, on a durable physical
+ medium customarily used for software interchange, for a price no
+ more than your reasonable cost of physically performing this
+ conveying of source, or (2) access to copy the
+ Corresponding Source from a network server at no charge.
+
+ c) Convey individual copies of the object code with a copy of the
+ written offer to provide the Corresponding Source. This
+ alternative is allowed only occasionally and noncommercially, and
+ only if you received the object code with such an offer, in accord
+ with subsection 6b.
+
+ d) Convey the object code by offering access from a designated
+ place (gratis or for a charge), and offer equivalent access to the
+ Corresponding Source in the same way through the same place at no
+ further charge. You need not require recipients to copy the
+ Corresponding Source along with the object code. If the place to
+ copy the object code is a network server, the Corresponding Source
+ may be on a different server (operated by you or a third party)
+ that supports equivalent copying facilities, provided you maintain
+ clear directions next to the object code saying where to find the
+ Corresponding Source. Regardless of what server hosts the
+ Corresponding Source, you remain obligated to ensure that it is
+ available for as long as needed to satisfy these requirements.
+
+ e) Convey the object code using peer-to-peer transmission, provided
+ you inform other peers where the object code and Corresponding
+ Source of the work are being offered to the general public at no
+ charge under subsection 6d.
+
+ A separable portion of the object code, whose source code is excluded
+from the Corresponding Source as a System Library, need not be
+included in conveying the object code work.
+
+ A "User Product" is either (1) a "consumer product", which means any
+tangible personal property which is normally used for personal, family,
+or household purposes, or (2) anything designed or sold for incorporation
+into a dwelling. In determining whether a product is a consumer product,
+doubtful cases shall be resolved in favor of coverage. For a particular
+product received by a particular user, "normally used" refers to a
+typical or common use of that class of product, regardless of the status
+of the particular user or of the way in which the particular user
+actually uses, or expects or is expected to use, the product. A product
+is a consumer product regardless of whether the product has substantial
+commercial, industrial or non-consumer uses, unless such uses represent
+the only significant mode of use of the product.
+
+ "Installation Information" for a User Product means any methods,
+procedures, authorization keys, or other information required to install
+and execute modified versions of a covered work in that User Product from
+a modified version of its Corresponding Source. The information must
+suffice to ensure that the continued functioning of the modified object
+code is in no case prevented or interfered with solely because
+modification has been made.
+
+ If you convey an object code work under this section in, or with, or
+specifically for use in, a User Product, and the conveying occurs as
+part of a transaction in which the right of possession and use of the
+User Product is transferred to the recipient in perpetuity or for a
+fixed term (regardless of how the transaction is characterized), the
+Corresponding Source conveyed under this section must be accompanied
+by the Installation Information. But this requirement does not apply
+if neither you nor any third party retains the ability to install
+modified object code on the User Product (for example, the work has
+been installed in ROM).
+
+ The requirement to provide Installation Information does not include a
+requirement to continue to provide support service, warranty, or updates
+for a work that has been modified or installed by the recipient, or for
+the User Product in which it has been modified or installed. Access to a
+network may be denied when the modification itself materially and
+adversely affects the operation of the network or violates the rules and
+protocols for communication across the network.
+
+ Corresponding Source conveyed, and Installation Information provided,
+in accord with this section must be in a format that is publicly
+documented (and with an implementation available to the public in
+source code form), and must require no special password or key for
+unpacking, reading or copying.
+
+ 7. Additional Terms.
+
+ "Additional permissions" are terms that supplement the terms of this
+License by making exceptions from one or more of its conditions.
+Additional permissions that are applicable to the entire Program shall
+be treated as though they were included in this License, to the extent
+that they are valid under applicable law. If additional permissions
+apply only to part of the Program, that part may be used separately
+under those permissions, but the entire Program remains governed by
+this License without regard to the additional permissions.
+
+ When you convey a copy of a covered work, you may at your option
+remove any additional permissions from that copy, or from any part of
+it. (Additional permissions may be written to require their own
+removal in certain cases when you modify the work.) You may place
+additional permissions on material, added by you to a covered work,
+for which you have or can give appropriate copyright permission.
+
+ Notwithstanding any other provision of this License, for material you
+add to a covered work, you may (if authorized by the copyright holders of
+that material) supplement the terms of this License with terms:
+
+ a) Disclaiming warranty or limiting liability differently from the
+ terms of sections 15 and 16 of this License; or
+
+ b) Requiring preservation of specified reasonable legal notices or
+ author attributions in that material or in the Appropriate Legal
+ Notices displayed by works containing it; or
+
+ c) Prohibiting misrepresentation of the origin of that material, or
+ requiring that modified versions of such material be marked in
+ reasonable ways as different from the original version; or
+
+ d) Limiting the use for publicity purposes of names of licensors or
+ authors of the material; or
+
+ e) Declining to grant rights under trademark law for use of some
+ trade names, trademarks, or service marks; or
+
+ f) Requiring indemnification of licensors and authors of that
+ material by anyone who conveys the material (or modified versions of
+ it) with contractual assumptions of liability to the recipient, for
+ any liability that these contractual assumptions directly impose on
+ those licensors and authors.
+
+ All other non-permissive additional terms are considered "further
+restrictions" within the meaning of section 10. If the Program as you
+received it, or any part of it, contains a notice stating that it is
+governed by this License along with a term that is a further
+restriction, you may remove that term. If a license document contains
+a further restriction but permits relicensing or conveying under this
+License, you may add to a covered work material governed by the terms
+of that license document, provided that the further restriction does
+not survive such relicensing or conveying.
+
+ If you add terms to a covered work in accord with this section, you
+must place, in the relevant source files, a statement of the
+additional terms that apply to those files, or a notice indicating
+where to find the applicable terms.
+
+ Additional terms, permissive or non-permissive, may be stated in the
+form of a separately written license, or stated as exceptions;
+the above requirements apply either way.
+
+ 8. Termination.
+
+ You may not propagate or modify a covered work except as expressly
+provided under this License. Any attempt otherwise to propagate or
+modify it is void, and will automatically terminate your rights under
+this License (including any patent licenses granted under the third
+paragraph of section 11).
+
+ However, if you cease all violation of this License, then your
+license from a particular copyright holder is reinstated (a)
+provisionally, unless and until the copyright holder explicitly and
+finally terminates your license, and (b) permanently, if the copyright
+holder fails to notify you of the violation by some reasonable means
+prior to 60 days after the cessation.
+
+ Moreover, your license from a particular copyright holder is
+reinstated permanently if the copyright holder notifies you of the
+violation by some reasonable means, this is the first time you have
+received notice of violation of this License (for any work) from that
+copyright holder, and you cure the violation prior to 30 days after
+your receipt of the notice.
+
+ Termination of your rights under this section does not terminate the
+licenses of parties who have received copies or rights from you under
+this License. If your rights have been terminated and not permanently
+reinstated, you do not qualify to receive new licenses for the same
+material under section 10.
+
+ 9. Acceptance Not Required for Having Copies.
+
+ You are not required to accept this License in order to receive or
+run a copy of the Program. Ancillary propagation of a covered work
+occurring solely as a consequence of using peer-to-peer transmission
+to receive a copy likewise does not require acceptance. However,
+nothing other than this License grants you permission to propagate or
+modify any covered work. These actions infringe copyright if you do
+not accept this License. Therefore, by modifying or propagating a
+covered work, you indicate your acceptance of this License to do so.
+
+ 10. Automatic Licensing of Downstream Recipients.
+
+ Each time you convey a covered work, the recipient automatically
+receives a license from the original licensors, to run, modify and
+propagate that work, subject to this License. You are not responsible
+for enforcing compliance by third parties with this License.
+
+ An "entity transaction" is a transaction transferring control of an
+organization, or substantially all assets of one, or subdividing an
+organization, or merging organizations. If propagation of a covered
+work results from an entity transaction, each party to that
+transaction who receives a copy of the work also receives whatever
+licenses to the work the party's predecessor in interest had or could
+give under the previous paragraph, plus a right to possession of the
+Corresponding Source of the work from the predecessor in interest, if
+the predecessor has it or can get it with reasonable efforts.
+
+ You may not impose any further restrictions on the exercise of the
+rights granted or affirmed under this License. For example, you may
+not impose a license fee, royalty, or other charge for exercise of
+rights granted under this License, and you may not initiate litigation
+(including a cross-claim or counterclaim in a lawsuit) alleging that
+any patent claim is infringed by making, using, selling, offering for
+sale, or importing the Program or any portion of it.
+
+ 11. Patents.
+
+ A "contributor" is a copyright holder who authorizes use under this
+License of the Program or a work on which the Program is based. The
+work thus licensed is called the contributor's "contributor version".
+
+ A contributor's "essential patent claims" are all patent claims
+owned or controlled by the contributor, whether already acquired or
+hereafter acquired, that would be infringed by some manner, permitted
+by this License, of making, using, or selling its contributor version,
+but do not include claims that would be infringed only as a
+consequence of further modification of the contributor version. For
+purposes of this definition, "control" includes the right to grant
+patent sublicenses in a manner consistent with the requirements of
+this License.
+
+ Each contributor grants you a non-exclusive, worldwide, royalty-free
+patent license under the contributor's essential patent claims, to
+make, use, sell, offer for sale, import and otherwise run, modify and
+propagate the contents of its contributor version.
+
+ In the following three paragraphs, a "patent license" is any express
+agreement or commitment, however denominated, not to enforce a patent
+(such as an express permission to practice a patent or covenant not to
+sue for patent infringement). To "grant" such a patent license to a
+party means to make such an agreement or commitment not to enforce a
+patent against the party.
+
+ If you convey a covered work, knowingly relying on a patent license,
+and the Corresponding Source of the work is not available for anyone
+to copy, free of charge and under the terms of this License, through a
+publicly available network server or other readily accessible means,
+then you must either (1) cause the Corresponding Source to be so
+available, or (2) arrange to deprive yourself of the benefit of the
+patent license for this particular work, or (3) arrange, in a manner
+consistent with the requirements of this License, to extend the patent
+license to downstream recipients. "Knowingly relying" means you have
+actual knowledge that, but for the patent license, your conveying the
+covered work in a country, or your recipient's use of the covered work
+in a country, would infringe one or more identifiable patents in that
+country that you have reason to believe are valid.
+
+ If, pursuant to or in connection with a single transaction or
+arrangement, you convey, or propagate by procuring conveyance of, a
+covered work, and grant a patent license to some of the parties
+receiving the covered work authorizing them to use, propagate, modify
+or convey a specific copy of the covered work, then the patent license
+you grant is automatically extended to all recipients of the covered
+work and works based on it.
+
+ A patent license is "discriminatory" if it does not include within
+the scope of its coverage, prohibits the exercise of, or is
+conditioned on the non-exercise of one or more of the rights that are
+specifically granted under this License. You may not convey a covered
+work if you are a party to an arrangement with a third party that is
+in the business of distributing software, under which you make payment
+to the third party based on the extent of your activity of conveying
+the work, and under which the third party grants, to any of the
+parties who would receive the covered work from you, a discriminatory
+patent license (a) in connection with copies of the covered work
+conveyed by you (or copies made from those copies), or (b) primarily
+for and in connection with specific products or compilations that
+contain the covered work, unless you entered into that arrangement,
+or that patent license was granted, prior to 28 March 2007.
+
+ Nothing in this License shall be construed as excluding or limiting
+any implied license or other defenses to infringement that may
+otherwise be available to you under applicable patent law.
+
+ 12. No Surrender of Others' Freedom.
+
+ If conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License. If you cannot convey a
+covered work so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you may
+not convey it at all. For example, if you agree to terms that obligate you
+to collect a royalty for further conveying from those to whom you convey
+the Program, the only way you could satisfy both those terms and this
+License would be to refrain entirely from conveying the Program.
+
+ 13. Use with the GNU Affero General Public License.
+
+ Notwithstanding any other provision of this License, you have
+permission to link or combine any covered work with a work licensed
+under version 3 of the GNU Affero General Public License into a single
+combined work, and to convey the resulting work. The terms of this
+License will continue to apply to the part which is the covered work,
+but the special requirements of the GNU Affero General Public License,
+section 13, concerning interaction through a network will apply to the
+combination as such.
+
+ 14. Revised Versions of this License.
+
+ The Free Software Foundation may publish revised and/or new versions of
+the GNU General Public License from time to time. Such new versions will
+be similar in spirit to the present version, but may differ in detail to
+address new problems or concerns.
+
+ Each version is given a distinguishing version number. If the
+Program specifies that a certain numbered version of the GNU General
+Public License "or any later version" applies to it, you have the
+option of following the terms and conditions either of that numbered
+version or of any later version published by the Free Software
+Foundation. If the Program does not specify a version number of the
+GNU General Public License, you may choose any version ever published
+by the Free Software Foundation.
+
+ If the Program specifies that a proxy can decide which future
+versions of the GNU General Public License can be used, that proxy's
+public statement of acceptance of a version permanently authorizes you
+to choose that version for the Program.
+
+ Later license versions may give you additional or different
+permissions. However, no additional obligations are imposed on any
+author or copyright holder as a result of your choosing to follow a
+later version.
+
+ 15. Disclaimer of Warranty.
+
+ THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY
+APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT
+HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY
+OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO,
+THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM
+IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF
+ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
+
+ 16. Limitation of Liability.
+
+ IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS
+THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY
+GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE
+USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF
+DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD
+PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS),
+EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF
+SUCH DAMAGES.
+
+ 17. Interpretation of Sections 15 and 16.
+
+ If the disclaimer of warranty and limitation of liability provided
+above cannot be given local legal effect according to their terms,
+reviewing courts shall apply local law that most closely approximates
+an absolute waiver of all civil liability in connection with the
+Program, unless a warranty or assumption of liability accompanies a
+copy of the Program in return for a fee.
+
+ END OF TERMS AND CONDITIONS
+
+ How to Apply These Terms to Your New Programs
+
+ If you develop a new program, and you want it to be of the greatest
+possible use to the public, the best way to achieve this is to make it
+free software which everyone can redistribute and change under these terms.
+
+ To do so, attach the following notices to the program. It is safest
+to attach them to the start of each source file to most effectively
+state the exclusion of warranty; and each file should have at least
+the "copyright" line and a pointer to where the full notice is found.
+
+
+ Copyright (C)
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see .
+
+Also add information on how to contact you by electronic and paper mail.
+
+ If the program does terminal interaction, make it output a short
+notice like this when it starts in an interactive mode:
+
+ Copyright (C)
+ This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
+ This is free software, and you are welcome to redistribute it
+ under certain conditions; type `show c' for details.
+
+The hypothetical commands `show w' and `show c' should show the appropriate
+parts of the General Public License. Of course, your program's commands
+might be different; for a GUI interface, you would use an "about box".
+
+ You should also get your employer (if you work as a programmer) or school,
+if any, to sign a "copyright disclaimer" for the program, if necessary.
+For more information on this, and how to apply and follow the GNU GPL, see
+.
+
+ The GNU General Public License does not permit incorporating your program
+into proprietary programs. If your program is a subroutine library, you
+may consider it more useful to permit linking proprietary applications with
+the library. If this is what you want to do, use the GNU Lesser General
+Public License instead of this License. But first, please read
+.
diff --git a/modules/sale_extra/MANIFEST.in b/modules/sale_extra/MANIFEST.in
new file mode 100644
index 0000000000..e88b2348a3
--- /dev/null
+++ b/modules/sale_extra/MANIFEST.in
@@ -0,0 +1,5 @@
+include CHANGELOG
+include COPYRIGHT
+include LICENSE
+include README.rst
+include doc/*
diff --git a/modules/sale_extra/README.rst b/modules/sale_extra/README.rst
new file mode 120000
index 0000000000..176d9c2695
--- /dev/null
+++ b/modules/sale_extra/README.rst
@@ -0,0 +1 @@
+doc/index.rst
\ No newline at end of file
diff --git a/modules/sale_extra/__init__.py b/modules/sale_extra/__init__.py
new file mode 100644
index 0000000000..394925dde4
--- /dev/null
+++ b/modules/sale_extra/__init__.py
@@ -0,0 +1,14 @@
+# This file is part of Tryton. The COPYRIGHT file at the top level of
+# this repository contains the full copyright notices and license terms.
+
+from trytond.pool import Pool
+from . import sale
+
+
+def register():
+ Pool.register(
+ sale.Extra,
+ sale.ExtraLine,
+ sale.Sale,
+ sale.Line,
+ module='sale_extra', type_='model')
diff --git a/modules/sale_extra/doc/index.rst b/modules/sale_extra/doc/index.rst
new file mode 100644
index 0000000000..31b9e198aa
--- /dev/null
+++ b/modules/sale_extra/doc/index.rst
@@ -0,0 +1,37 @@
+Sale Extra
+##########
+
+The sale_extra module allows to add extra line on sale based on criteria.
+
+The extra products are added when the sale goes into quotation but the added
+lines can be modified when going back to draft.
+
+The criteria are defined by the *Sale Extras* of the *Price List*.
+
+Sale Extra
+**********
+
+Each matching *Sale Extra* is evaluated to add an extra line.
+The criteria are the fields:
+
+- *Price List*
+- *Start/End Date*
+- *Sale Amount*: If untaxed sale amount is greater or equal
+ (in the price list company currency).
+
+Sale Extra Line
+***************
+
+Once a *Sale Extra* is selected, its first line that match the line's criteria
+is used to setup the extra line.
+The criteria are the fields:
+
+- *Sale Amount*: If the untaxed sale amount is greater or equal
+ (in the price list company currency).
+
+The sale line is setup using the fields:
+
+- *Product*: The product to use on the sale line.
+- *Quantity*: The quantity to set on the sale line (in the *Unit*).
+- *Unit*: The unit of measure to use.
+- *Free*: Set unit price of the sale line to zero, otherwise to the sale price.
diff --git a/modules/sale_extra/locale/bg.po b/modules/sale_extra/locale/bg.po
new file mode 100644
index 0000000000..68285c0c76
--- /dev/null
+++ b/modules/sale_extra/locale/bg.po
@@ -0,0 +1,115 @@
+#
+msgid ""
+msgstr "Content-Type: text/plain; charset=utf-8\n"
+
+#, fuzzy
+msgctxt "field:sale.extra,company:"
+msgid "Company"
+msgstr "Фирма"
+
+#, fuzzy
+msgctxt "field:sale.extra,currency_digits:"
+msgid "Currency Digits"
+msgstr "Цифри за валута"
+
+#, fuzzy
+msgctxt "field:sale.extra,end_date:"
+msgid "End Date"
+msgstr "Крайна дата"
+
+#, fuzzy
+msgctxt "field:sale.extra,lines:"
+msgid "Lines"
+msgstr "Транзакции"
+
+#, fuzzy
+msgctxt "field:sale.extra,name:"
+msgid "Name"
+msgstr "Условие за плащане"
+
+#, fuzzy
+msgctxt "field:sale.extra,price_list:"
+msgid "Price List"
+msgstr "Ценова листа"
+
+msgctxt "field:sale.extra,sale_amount:"
+msgid "Sale Amount"
+msgstr ""
+
+#, fuzzy
+msgctxt "field:sale.extra,start_date:"
+msgid "Start Date"
+msgstr "Начална дата"
+
+#, fuzzy
+msgctxt "field:sale.extra.line,extra:"
+msgid "Extra"
+msgstr "Extras"
+
+#, fuzzy
+msgctxt "field:sale.extra.line,free:"
+msgid "Free"
+msgstr "Свободен"
+
+#, fuzzy
+msgctxt "field:sale.extra.line,product:"
+msgid "Product"
+msgstr "Продукт"
+
+msgctxt "field:sale.extra.line,product_uom_category:"
+msgid "Product UoM Category"
+msgstr ""
+
+#, fuzzy
+msgctxt "field:sale.extra.line,quantity:"
+msgid "Quantity"
+msgstr "Количество"
+
+msgctxt "field:sale.extra.line,sale_amount:"
+msgid "Sale Amount"
+msgstr ""
+
+#, fuzzy
+msgctxt "field:sale.extra.line,unit:"
+msgid "Unit"
+msgstr "Единица"
+
+#, fuzzy
+msgctxt "field:sale.extra.line,unit_digits:"
+msgid "Unit Digits"
+msgstr "Десетични единици"
+
+#, fuzzy
+msgctxt "field:sale.line,extra:"
+msgid "Extra"
+msgstr "Extras"
+
+msgctxt "model:ir.action,name:act_extra_form"
+msgid "Extras"
+msgstr "Extras"
+
+msgctxt "model:ir.action,name:act_extra_relate"
+msgid "Sale Extras"
+msgstr "Sale Extras"
+
+msgctxt "model:ir.rule.group,name:rule_group_extra_companies"
+msgid "User in companies"
+msgstr ""
+
+msgctxt "model:ir.ui.menu,name:menu_extra"
+msgid "Extras"
+msgstr "Extras"
+
+#, fuzzy
+msgctxt "model:sale.extra,name:"
+msgid "Sale Extra"
+msgstr "Sale Extras"
+
+msgctxt "model:sale.extra.line,name:"
+msgid "Sale Extra Line"
+msgstr ""
+
+#, fuzzy
+msgctxt "view:sale.extra.line:"
+msgid "Sale Line"
+msgstr "Ред от продажба"
diff --git a/modules/sale_extra/locale/ca.po b/modules/sale_extra/locale/ca.po
new file mode 100644
index 0000000000..e29239542c
--- /dev/null
+++ b/modules/sale_extra/locale/ca.po
@@ -0,0 +1,99 @@
+#
+msgid ""
+msgstr "Content-Type: text/plain; charset=utf-8\n"
+
+msgctxt "field:sale.extra,company:"
+msgid "Company"
+msgstr "Empresa"
+
+msgctxt "field:sale.extra,currency_digits:"
+msgid "Currency Digits"
+msgstr "Decimals de la moneda"
+
+msgctxt "field:sale.extra,end_date:"
+msgid "End Date"
+msgstr "Data final"
+
+msgctxt "field:sale.extra,lines:"
+msgid "Lines"
+msgstr "Línies"
+
+msgctxt "field:sale.extra,name:"
+msgid "Name"
+msgstr "Nom"
+
+msgctxt "field:sale.extra,price_list:"
+msgid "Price List"
+msgstr "Tarifa"
+
+msgctxt "field:sale.extra,sale_amount:"
+msgid "Sale Amount"
+msgstr "Import de la venda"
+
+msgctxt "field:sale.extra,start_date:"
+msgid "Start Date"
+msgstr "Data inicial"
+
+msgctxt "field:sale.extra.line,extra:"
+msgid "Extra"
+msgstr "Extra"
+
+msgctxt "field:sale.extra.line,free:"
+msgid "Free"
+msgstr "Gratis"
+
+msgctxt "field:sale.extra.line,product:"
+msgid "Product"
+msgstr "Producte"
+
+msgctxt "field:sale.extra.line,product_uom_category:"
+msgid "Product UoM Category"
+msgstr "Categoria UdM del producte"
+
+msgctxt "field:sale.extra.line,quantity:"
+msgid "Quantity"
+msgstr "Quantitat"
+
+msgctxt "field:sale.extra.line,sale_amount:"
+msgid "Sale Amount"
+msgstr "Import de la venda"
+
+msgctxt "field:sale.extra.line,unit:"
+msgid "Unit"
+msgstr "Unitat"
+
+msgctxt "field:sale.extra.line,unit_digits:"
+msgid "Unit Digits"
+msgstr "Dígits de la unitat"
+
+msgctxt "field:sale.line,extra:"
+msgid "Extra"
+msgstr "Extra"
+
+msgctxt "model:ir.action,name:act_extra_form"
+msgid "Extras"
+msgstr "Extres"
+
+msgctxt "model:ir.action,name:act_extra_relate"
+msgid "Sale Extras"
+msgstr "Extres de venda"
+
+msgctxt "model:ir.rule.group,name:rule_group_extra_companies"
+msgid "User in companies"
+msgstr "Usuari a les empreses"
+
+msgctxt "model:ir.ui.menu,name:menu_extra"
+msgid "Extras"
+msgstr "Extres"
+
+msgctxt "model:sale.extra,name:"
+msgid "Sale Extra"
+msgstr "Extra de venda"
+
+msgctxt "model:sale.extra.line,name:"
+msgid "Sale Extra Line"
+msgstr "Línia extra de venda"
+
+msgctxt "view:sale.extra.line:"
+msgid "Sale Line"
+msgstr "Línia de venta"
diff --git a/modules/sale_extra/locale/cs.po b/modules/sale_extra/locale/cs.po
new file mode 100644
index 0000000000..6c31b63010
--- /dev/null
+++ b/modules/sale_extra/locale/cs.po
@@ -0,0 +1,103 @@
+#
+msgid ""
+msgstr "Content-Type: text/plain; charset=utf-8\n"
+
+msgctxt "field:sale.extra,company:"
+msgid "Company"
+msgstr ""
+
+msgctxt "field:sale.extra,currency_digits:"
+msgid "Currency Digits"
+msgstr ""
+
+msgctxt "field:sale.extra,end_date:"
+msgid "End Date"
+msgstr ""
+
+msgctxt "field:sale.extra,lines:"
+msgid "Lines"
+msgstr ""
+
+#, fuzzy
+msgctxt "field:sale.extra,name:"
+msgid "Name"
+msgstr "Namu"
+
+msgctxt "field:sale.extra,price_list:"
+msgid "Price List"
+msgstr ""
+
+msgctxt "field:sale.extra,sale_amount:"
+msgid "Sale Amount"
+msgstr ""
+
+msgctxt "field:sale.extra,start_date:"
+msgid "Start Date"
+msgstr ""
+
+#, fuzzy
+msgctxt "field:sale.extra.line,extra:"
+msgid "Extra"
+msgstr "Extras"
+
+msgctxt "field:sale.extra.line,free:"
+msgid "Free"
+msgstr ""
+
+msgctxt "field:sale.extra.line,product:"
+msgid "Product"
+msgstr ""
+
+msgctxt "field:sale.extra.line,product_uom_category:"
+msgid "Product UoM Category"
+msgstr ""
+
+msgctxt "field:sale.extra.line,quantity:"
+msgid "Quantity"
+msgstr ""
+
+msgctxt "field:sale.extra.line,sale_amount:"
+msgid "Sale Amount"
+msgstr ""
+
+msgctxt "field:sale.extra.line,unit:"
+msgid "Unit"
+msgstr ""
+
+msgctxt "field:sale.extra.line,unit_digits:"
+msgid "Unit Digits"
+msgstr ""
+
+#, fuzzy
+msgctxt "field:sale.line,extra:"
+msgid "Extra"
+msgstr "Extras"
+
+msgctxt "model:ir.action,name:act_extra_form"
+msgid "Extras"
+msgstr "Extras"
+
+msgctxt "model:ir.action,name:act_extra_relate"
+msgid "Sale Extras"
+msgstr "Sale Extras"
+
+msgctxt "model:ir.rule.group,name:rule_group_extra_companies"
+msgid "User in companies"
+msgstr ""
+
+msgctxt "model:ir.ui.menu,name:menu_extra"
+msgid "Extras"
+msgstr "Extras"
+
+#, fuzzy
+msgctxt "model:sale.extra,name:"
+msgid "Sale Extra"
+msgstr "Sale Extras"
+
+msgctxt "model:sale.extra.line,name:"
+msgid "Sale Extra Line"
+msgstr ""
+
+msgctxt "view:sale.extra.line:"
+msgid "Sale Line"
+msgstr ""
diff --git a/modules/sale_extra/locale/de.po b/modules/sale_extra/locale/de.po
new file mode 100644
index 0000000000..489d9d7c72
--- /dev/null
+++ b/modules/sale_extra/locale/de.po
@@ -0,0 +1,99 @@
+#
+msgid ""
+msgstr "Content-Type: text/plain; charset=utf-8\n"
+
+msgctxt "field:sale.extra,company:"
+msgid "Company"
+msgstr "Unternehmen"
+
+msgctxt "field:sale.extra,currency_digits:"
+msgid "Currency Digits"
+msgstr "Nachkommastellen Währung"
+
+msgctxt "field:sale.extra,end_date:"
+msgid "End Date"
+msgstr "Enddatum"
+
+msgctxt "field:sale.extra,lines:"
+msgid "Lines"
+msgstr "Positionen"
+
+msgctxt "field:sale.extra,name:"
+msgid "Name"
+msgstr "Name"
+
+msgctxt "field:sale.extra,price_list:"
+msgid "Price List"
+msgstr "Preisliste"
+
+msgctxt "field:sale.extra,sale_amount:"
+msgid "Sale Amount"
+msgstr "Verkaufsbetrag"
+
+msgctxt "field:sale.extra,start_date:"
+msgid "Start Date"
+msgstr "Startdatum"
+
+msgctxt "field:sale.extra.line,extra:"
+msgid "Extra"
+msgstr "Extra"
+
+msgctxt "field:sale.extra.line,free:"
+msgid "Free"
+msgstr "Gratis"
+
+msgctxt "field:sale.extra.line,product:"
+msgid "Product"
+msgstr "Artikel"
+
+msgctxt "field:sale.extra.line,product_uom_category:"
+msgid "Product UoM Category"
+msgstr "Maßeinheitenkategorie"
+
+msgctxt "field:sale.extra.line,quantity:"
+msgid "Quantity"
+msgstr "Menge"
+
+msgctxt "field:sale.extra.line,sale_amount:"
+msgid "Sale Amount"
+msgstr "Verkaufsbetrag"
+
+msgctxt "field:sale.extra.line,unit:"
+msgid "Unit"
+msgstr "Einheit"
+
+msgctxt "field:sale.extra.line,unit_digits:"
+msgid "Unit Digits"
+msgstr "Nachkommastellen"
+
+msgctxt "field:sale.line,extra:"
+msgid "Extra"
+msgstr "Extra"
+
+msgctxt "model:ir.action,name:act_extra_form"
+msgid "Extras"
+msgstr "Extras"
+
+msgctxt "model:ir.action,name:act_extra_relate"
+msgid "Sale Extras"
+msgstr "Verkaufsextras"
+
+msgctxt "model:ir.rule.group,name:rule_group_extra_companies"
+msgid "User in companies"
+msgstr "Benutzer in Unternehmen"
+
+msgctxt "model:ir.ui.menu,name:menu_extra"
+msgid "Extras"
+msgstr "Extras"
+
+msgctxt "model:sale.extra,name:"
+msgid "Sale Extra"
+msgstr "Verkaufsextra"
+
+msgctxt "model:sale.extra.line,name:"
+msgid "Sale Extra Line"
+msgstr "Verkaufsextrazeile"
+
+msgctxt "view:sale.extra.line:"
+msgid "Sale Line"
+msgstr "Verkaufsposition"
diff --git a/modules/sale_extra/locale/es.po b/modules/sale_extra/locale/es.po
new file mode 100644
index 0000000000..d27776edfe
--- /dev/null
+++ b/modules/sale_extra/locale/es.po
@@ -0,0 +1,99 @@
+#
+msgid ""
+msgstr "Content-Type: text/plain; charset=utf-8\n"
+
+msgctxt "field:sale.extra,company:"
+msgid "Company"
+msgstr "Empresa"
+
+msgctxt "field:sale.extra,currency_digits:"
+msgid "Currency Digits"
+msgstr "Decimales de la moneda"
+
+msgctxt "field:sale.extra,end_date:"
+msgid "End Date"
+msgstr "Fecha final"
+
+msgctxt "field:sale.extra,lines:"
+msgid "Lines"
+msgstr "Líneas"
+
+msgctxt "field:sale.extra,name:"
+msgid "Name"
+msgstr "Nombre"
+
+msgctxt "field:sale.extra,price_list:"
+msgid "Price List"
+msgstr "Tarifa"
+
+msgctxt "field:sale.extra,sale_amount:"
+msgid "Sale Amount"
+msgstr "Importe de la venta"
+
+msgctxt "field:sale.extra,start_date:"
+msgid "Start Date"
+msgstr "Fecha inicial"
+
+msgctxt "field:sale.extra.line,extra:"
+msgid "Extra"
+msgstr "Extra"
+
+msgctxt "field:sale.extra.line,free:"
+msgid "Free"
+msgstr "Gratis"
+
+msgctxt "field:sale.extra.line,product:"
+msgid "Product"
+msgstr "Producto"
+
+msgctxt "field:sale.extra.line,product_uom_category:"
+msgid "Product UoM Category"
+msgstr "Categoría UdM del producto"
+
+msgctxt "field:sale.extra.line,quantity:"
+msgid "Quantity"
+msgstr "Cantidad"
+
+msgctxt "field:sale.extra.line,sale_amount:"
+msgid "Sale Amount"
+msgstr "Importe de la venta"
+
+msgctxt "field:sale.extra.line,unit:"
+msgid "Unit"
+msgstr "Unidad"
+
+msgctxt "field:sale.extra.line,unit_digits:"
+msgid "Unit Digits"
+msgstr "Dígitos de la unidad"
+
+msgctxt "field:sale.line,extra:"
+msgid "Extra"
+msgstr "Extra"
+
+msgctxt "model:ir.action,name:act_extra_form"
+msgid "Extras"
+msgstr "Extras"
+
+msgctxt "model:ir.action,name:act_extra_relate"
+msgid "Sale Extras"
+msgstr "Extras de venta"
+
+msgctxt "model:ir.rule.group,name:rule_group_extra_companies"
+msgid "User in companies"
+msgstr "Usuario en las empresas"
+
+msgctxt "model:ir.ui.menu,name:menu_extra"
+msgid "Extras"
+msgstr "Extras"
+
+msgctxt "model:sale.extra,name:"
+msgid "Sale Extra"
+msgstr "Extra de venta"
+
+msgctxt "model:sale.extra.line,name:"
+msgid "Sale Extra Line"
+msgstr "Línea extra de venta"
+
+msgctxt "view:sale.extra.line:"
+msgid "Sale Line"
+msgstr "Línea de venta"
diff --git a/modules/sale_extra/locale/es_419.po b/modules/sale_extra/locale/es_419.po
new file mode 100644
index 0000000000..533080ee4b
--- /dev/null
+++ b/modules/sale_extra/locale/es_419.po
@@ -0,0 +1,99 @@
+#
+msgid ""
+msgstr "Content-Type: text/plain; charset=utf-8\n"
+
+msgctxt "field:sale.extra,company:"
+msgid "Company"
+msgstr ""
+
+msgctxt "field:sale.extra,currency_digits:"
+msgid "Currency Digits"
+msgstr ""
+
+msgctxt "field:sale.extra,end_date:"
+msgid "End Date"
+msgstr ""
+
+msgctxt "field:sale.extra,lines:"
+msgid "Lines"
+msgstr ""
+
+msgctxt "field:sale.extra,name:"
+msgid "Name"
+msgstr ""
+
+msgctxt "field:sale.extra,price_list:"
+msgid "Price List"
+msgstr "Lista de precios"
+
+msgctxt "field:sale.extra,sale_amount:"
+msgid "Sale Amount"
+msgstr ""
+
+msgctxt "field:sale.extra,start_date:"
+msgid "Start Date"
+msgstr ""
+
+msgctxt "field:sale.extra.line,extra:"
+msgid "Extra"
+msgstr ""
+
+msgctxt "field:sale.extra.line,free:"
+msgid "Free"
+msgstr ""
+
+msgctxt "field:sale.extra.line,product:"
+msgid "Product"
+msgstr ""
+
+msgctxt "field:sale.extra.line,product_uom_category:"
+msgid "Product UoM Category"
+msgstr "Cateogría de UdM de producto"
+
+msgctxt "field:sale.extra.line,quantity:"
+msgid "Quantity"
+msgstr ""
+
+msgctxt "field:sale.extra.line,sale_amount:"
+msgid "Sale Amount"
+msgstr ""
+
+msgctxt "field:sale.extra.line,unit:"
+msgid "Unit"
+msgstr ""
+
+msgctxt "field:sale.extra.line,unit_digits:"
+msgid "Unit Digits"
+msgstr ""
+
+msgctxt "field:sale.line,extra:"
+msgid "Extra"
+msgstr ""
+
+msgctxt "model:ir.action,name:act_extra_form"
+msgid "Extras"
+msgstr ""
+
+msgctxt "model:ir.action,name:act_extra_relate"
+msgid "Sale Extras"
+msgstr ""
+
+msgctxt "model:ir.rule.group,name:rule_group_extra_companies"
+msgid "User in companies"
+msgstr ""
+
+msgctxt "model:ir.ui.menu,name:menu_extra"
+msgid "Extras"
+msgstr ""
+
+msgctxt "model:sale.extra,name:"
+msgid "Sale Extra"
+msgstr ""
+
+msgctxt "model:sale.extra.line,name:"
+msgid "Sale Extra Line"
+msgstr ""
+
+msgctxt "view:sale.extra.line:"
+msgid "Sale Line"
+msgstr ""
diff --git a/modules/sale_extra/locale/et.po b/modules/sale_extra/locale/et.po
new file mode 100644
index 0000000000..ab013bd433
--- /dev/null
+++ b/modules/sale_extra/locale/et.po
@@ -0,0 +1,102 @@
+#
+msgid ""
+msgstr "Content-Type: text/plain; charset=utf-8\n"
+
+msgctxt "field:sale.extra,company:"
+msgid "Company"
+msgstr "Ettevõte"
+
+msgctxt "field:sale.extra,currency_digits:"
+msgid "Currency Digits"
+msgstr "Valuuta numbriväärtus"
+
+msgctxt "field:sale.extra,end_date:"
+msgid "End Date"
+msgstr "Lõppkuupäev"
+
+msgctxt "field:sale.extra,lines:"
+msgid "Lines"
+msgstr "Read"
+
+msgctxt "field:sale.extra,name:"
+msgid "Name"
+msgstr "Nimi"
+
+msgctxt "field:sale.extra,price_list:"
+msgid "Price List"
+msgstr "Hinnakiri"
+
+msgctxt "field:sale.extra,sale_amount:"
+msgid "Sale Amount"
+msgstr "Summa"
+
+msgctxt "field:sale.extra,start_date:"
+msgid "Start Date"
+msgstr "Alguskuupäev"
+
+msgctxt "field:sale.extra.line,extra:"
+msgid "Extra"
+msgstr "Ekstra"
+
+msgctxt "field:sale.extra.line,free:"
+msgid "Free"
+msgstr "Tasuta"
+
+msgctxt "field:sale.extra.line,product:"
+msgid "Product"
+msgstr "Toode"
+
+msgctxt "field:sale.extra.line,product_uom_category:"
+msgid "Product UoM Category"
+msgstr "Toote mõõtühiku kategooria"
+
+msgctxt "field:sale.extra.line,quantity:"
+msgid "Quantity"
+msgstr "Kogus"
+
+msgctxt "field:sale.extra.line,sale_amount:"
+msgid "Sale Amount"
+msgstr "Summa"
+
+msgctxt "field:sale.extra.line,unit:"
+msgid "Unit"
+msgstr "Ühik"
+
+msgctxt "field:sale.extra.line,unit_digits:"
+msgid "Unit Digits"
+msgstr "Ühiku numbriväärtus"
+
+msgctxt "field:sale.line,extra:"
+msgid "Extra"
+msgstr "Ekstra"
+
+msgctxt "model:ir.action,name:act_extra_form"
+msgid "Extras"
+msgstr "Ekstrad"
+
+msgctxt "model:ir.action,name:act_extra_relate"
+msgid "Sale Extras"
+msgstr "Müügi ekstra"
+
+#, fuzzy
+msgctxt "model:ir.rule.group,name:rule_group_extra_companies"
+msgid "User in companies"
+msgstr "Kasutaja ettevõttes"
+
+#, fuzzy
+msgctxt "model:ir.ui.menu,name:menu_extra"
+msgid "Extras"
+msgstr "Ekstrad"
+
+#, fuzzy
+msgctxt "model:sale.extra,name:"
+msgid "Sale Extra"
+msgstr "Müügi ekstra"
+
+msgctxt "model:sale.extra.line,name:"
+msgid "Sale Extra Line"
+msgstr ""
+
+msgctxt "view:sale.extra.line:"
+msgid "Sale Line"
+msgstr "Müügirida"
diff --git a/modules/sale_extra/locale/fa.po b/modules/sale_extra/locale/fa.po
new file mode 100644
index 0000000000..a97c2d30bf
--- /dev/null
+++ b/modules/sale_extra/locale/fa.po
@@ -0,0 +1,99 @@
+#
+msgid ""
+msgstr "Content-Type: text/plain; charset=utf-8\n"
+
+msgctxt "field:sale.extra,company:"
+msgid "Company"
+msgstr "شرکت"
+
+msgctxt "field:sale.extra,currency_digits:"
+msgid "Currency Digits"
+msgstr "رقم های واحد پول"
+
+msgctxt "field:sale.extra,end_date:"
+msgid "End Date"
+msgstr "تاریخ پایان"
+
+msgctxt "field:sale.extra,lines:"
+msgid "Lines"
+msgstr "سطرها"
+
+msgctxt "field:sale.extra,name:"
+msgid "Name"
+msgstr "نام"
+
+msgctxt "field:sale.extra,price_list:"
+msgid "Price List"
+msgstr "لیست قیمت"
+
+msgctxt "field:sale.extra,sale_amount:"
+msgid "Sale Amount"
+msgstr "میزان فروش"
+
+msgctxt "field:sale.extra,start_date:"
+msgid "Start Date"
+msgstr "تاریخ شروع"
+
+msgctxt "field:sale.extra.line,extra:"
+msgid "Extra"
+msgstr "اضافی"
+
+msgctxt "field:sale.extra.line,free:"
+msgid "Free"
+msgstr "رایگان"
+
+msgctxt "field:sale.extra.line,product:"
+msgid "Product"
+msgstr "محصول"
+
+msgctxt "field:sale.extra.line,product_uom_category:"
+msgid "Product UoM Category"
+msgstr "زیرمجموعه واحد اندازه گیری محصول"
+
+msgctxt "field:sale.extra.line,quantity:"
+msgid "Quantity"
+msgstr "مقدار/تعداد"
+
+msgctxt "field:sale.extra.line,sale_amount:"
+msgid "Sale Amount"
+msgstr "میزان فروش"
+
+msgctxt "field:sale.extra.line,unit:"
+msgid "Unit"
+msgstr "واحد"
+
+msgctxt "field:sale.extra.line,unit_digits:"
+msgid "Unit Digits"
+msgstr "ارقام واحد"
+
+msgctxt "field:sale.line,extra:"
+msgid "Extra"
+msgstr "اضافی"
+
+msgctxt "model:ir.action,name:act_extra_form"
+msgid "Extras"
+msgstr "اضافات"
+
+msgctxt "model:ir.action,name:act_extra_relate"
+msgid "Sale Extras"
+msgstr "فروش اضافات"
+
+msgctxt "model:ir.rule.group,name:rule_group_extra_companies"
+msgid "User in companies"
+msgstr ""
+
+msgctxt "model:ir.ui.menu,name:menu_extra"
+msgid "Extras"
+msgstr "اضافات"
+
+msgctxt "model:sale.extra,name:"
+msgid "Sale Extra"
+msgstr "فروش اضافی"
+
+msgctxt "model:sale.extra.line,name:"
+msgid "Sale Extra Line"
+msgstr "سطر فروش اضافی"
+
+msgctxt "view:sale.extra.line:"
+msgid "Sale Line"
+msgstr "سطر فروش"
diff --git a/modules/sale_extra/locale/fi.po b/modules/sale_extra/locale/fi.po
new file mode 100644
index 0000000000..2f9aa89137
--- /dev/null
+++ b/modules/sale_extra/locale/fi.po
@@ -0,0 +1,102 @@
+#
+msgid ""
+msgstr "Content-Type: text/plain; charset=utf-8\n"
+
+msgctxt "field:sale.extra,company:"
+msgid "Company"
+msgstr ""
+
+msgctxt "field:sale.extra,currency_digits:"
+msgid "Currency Digits"
+msgstr ""
+
+msgctxt "field:sale.extra,end_date:"
+msgid "End Date"
+msgstr ""
+
+msgctxt "field:sale.extra,lines:"
+msgid "Lines"
+msgstr ""
+
+msgctxt "field:sale.extra,name:"
+msgid "Name"
+msgstr ""
+
+msgctxt "field:sale.extra,price_list:"
+msgid "Price List"
+msgstr ""
+
+msgctxt "field:sale.extra,sale_amount:"
+msgid "Sale Amount"
+msgstr ""
+
+msgctxt "field:sale.extra,start_date:"
+msgid "Start Date"
+msgstr ""
+
+#, fuzzy
+msgctxt "field:sale.extra.line,extra:"
+msgid "Extra"
+msgstr "Extras"
+
+msgctxt "field:sale.extra.line,free:"
+msgid "Free"
+msgstr ""
+
+msgctxt "field:sale.extra.line,product:"
+msgid "Product"
+msgstr ""
+
+msgctxt "field:sale.extra.line,product_uom_category:"
+msgid "Product UoM Category"
+msgstr ""
+
+msgctxt "field:sale.extra.line,quantity:"
+msgid "Quantity"
+msgstr ""
+
+msgctxt "field:sale.extra.line,sale_amount:"
+msgid "Sale Amount"
+msgstr ""
+
+msgctxt "field:sale.extra.line,unit:"
+msgid "Unit"
+msgstr ""
+
+msgctxt "field:sale.extra.line,unit_digits:"
+msgid "Unit Digits"
+msgstr ""
+
+#, fuzzy
+msgctxt "field:sale.line,extra:"
+msgid "Extra"
+msgstr "Extras"
+
+msgctxt "model:ir.action,name:act_extra_form"
+msgid "Extras"
+msgstr "Extras"
+
+msgctxt "model:ir.action,name:act_extra_relate"
+msgid "Sale Extras"
+msgstr "Sale Extras"
+
+msgctxt "model:ir.rule.group,name:rule_group_extra_companies"
+msgid "User in companies"
+msgstr ""
+
+msgctxt "model:ir.ui.menu,name:menu_extra"
+msgid "Extras"
+msgstr "Extras"
+
+#, fuzzy
+msgctxt "model:sale.extra,name:"
+msgid "Sale Extra"
+msgstr "Sale Extras"
+
+msgctxt "model:sale.extra.line,name:"
+msgid "Sale Extra Line"
+msgstr ""
+
+msgctxt "view:sale.extra.line:"
+msgid "Sale Line"
+msgstr ""
diff --git a/modules/sale_extra/locale/fr.po b/modules/sale_extra/locale/fr.po
new file mode 100644
index 0000000000..26ae360a5b
--- /dev/null
+++ b/modules/sale_extra/locale/fr.po
@@ -0,0 +1,99 @@
+#
+msgid ""
+msgstr "Content-Type: text/plain; charset=utf-8\n"
+
+msgctxt "field:sale.extra,company:"
+msgid "Company"
+msgstr "Société"
+
+msgctxt "field:sale.extra,currency_digits:"
+msgid "Currency Digits"
+msgstr "Décimales de la devise"
+
+msgctxt "field:sale.extra,end_date:"
+msgid "End Date"
+msgstr "Date de fin"
+
+msgctxt "field:sale.extra,lines:"
+msgid "Lines"
+msgstr "Lignes"
+
+msgctxt "field:sale.extra,name:"
+msgid "Name"
+msgstr "Nom"
+
+msgctxt "field:sale.extra,price_list:"
+msgid "Price List"
+msgstr "Liste de prix"
+
+msgctxt "field:sale.extra,sale_amount:"
+msgid "Sale Amount"
+msgstr "Montant de la vente"
+
+msgctxt "field:sale.extra,start_date:"
+msgid "Start Date"
+msgstr "Date de début"
+
+msgctxt "field:sale.extra.line,extra:"
+msgid "Extra"
+msgstr "Extra"
+
+msgctxt "field:sale.extra.line,free:"
+msgid "Free"
+msgstr "Gratuit"
+
+msgctxt "field:sale.extra.line,product:"
+msgid "Product"
+msgstr "Produit"
+
+msgctxt "field:sale.extra.line,product_uom_category:"
+msgid "Product UoM Category"
+msgstr "Catégorie d'unité de mesure"
+
+msgctxt "field:sale.extra.line,quantity:"
+msgid "Quantity"
+msgstr "Quantité"
+
+msgctxt "field:sale.extra.line,sale_amount:"
+msgid "Sale Amount"
+msgstr "Montant de la vente"
+
+msgctxt "field:sale.extra.line,unit:"
+msgid "Unit"
+msgstr "Unité"
+
+msgctxt "field:sale.extra.line,unit_digits:"
+msgid "Unit Digits"
+msgstr "Décimales de l'unité"
+
+msgctxt "field:sale.line,extra:"
+msgid "Extra"
+msgstr "Extra"
+
+msgctxt "model:ir.action,name:act_extra_form"
+msgid "Extras"
+msgstr "Extras"
+
+msgctxt "model:ir.action,name:act_extra_relate"
+msgid "Sale Extras"
+msgstr "Extras de vente"
+
+msgctxt "model:ir.rule.group,name:rule_group_extra_companies"
+msgid "User in companies"
+msgstr "Utilisateur dans les sociétés"
+
+msgctxt "model:ir.ui.menu,name:menu_extra"
+msgid "Extras"
+msgstr "Extras"
+
+msgctxt "model:sale.extra,name:"
+msgid "Sale Extra"
+msgstr "Extra de vente"
+
+msgctxt "model:sale.extra.line,name:"
+msgid "Sale Extra Line"
+msgstr "Ligne de vente extra"
+
+msgctxt "view:sale.extra.line:"
+msgid "Sale Line"
+msgstr "Ligne de vente"
diff --git a/modules/sale_extra/locale/hu.po b/modules/sale_extra/locale/hu.po
new file mode 100644
index 0000000000..563cd39611
--- /dev/null
+++ b/modules/sale_extra/locale/hu.po
@@ -0,0 +1,102 @@
+#
+msgid ""
+msgstr "Content-Type: text/plain; charset=utf-8\n"
+
+msgctxt "field:sale.extra,company:"
+msgid "Company"
+msgstr "Társaság"
+
+msgctxt "field:sale.extra,currency_digits:"
+msgid "Currency Digits"
+msgstr "Tizedes vessző utáni számjegy"
+
+msgctxt "field:sale.extra,end_date:"
+msgid "End Date"
+msgstr "Befejezési dátum"
+
+msgctxt "field:sale.extra,lines:"
+msgid "Lines"
+msgstr "Sor"
+
+msgctxt "field:sale.extra,name:"
+msgid "Name"
+msgstr "Név"
+
+msgctxt "field:sale.extra,price_list:"
+msgid "Price List"
+msgstr "Árlista"
+
+msgctxt "field:sale.extra,sale_amount:"
+msgid "Sale Amount"
+msgstr "Eladási összeg"
+
+msgctxt "field:sale.extra,start_date:"
+msgid "Start Date"
+msgstr "Kezdő dátum"
+
+msgctxt "field:sale.extra.line,extra:"
+msgid "Extra"
+msgstr "Extra"
+
+msgctxt "field:sale.extra.line,free:"
+msgid "Free"
+msgstr "Szabad"
+
+msgctxt "field:sale.extra.line,product:"
+msgid "Product"
+msgstr "Termék"
+
+msgctxt "field:sale.extra.line,product_uom_category:"
+msgid "Product UoM Category"
+msgstr "Mértékegység kategória"
+
+msgctxt "field:sale.extra.line,quantity:"
+msgid "Quantity"
+msgstr "Mennyiség"
+
+msgctxt "field:sale.extra.line,sale_amount:"
+msgid "Sale Amount"
+msgstr "Eladási ár"
+
+msgctxt "field:sale.extra.line,unit:"
+msgid "Unit"
+msgstr "Egység"
+
+msgctxt "field:sale.extra.line,unit_digits:"
+msgid "Unit Digits"
+msgstr "Tizedes vessző utáni számjegy"
+
+msgctxt "field:sale.line,extra:"
+msgid "Extra"
+msgstr "Extra"
+
+#, fuzzy
+msgctxt "model:ir.action,name:act_extra_form"
+msgid "Extras"
+msgstr "Extras"
+
+#, fuzzy
+msgctxt "model:ir.action,name:act_extra_relate"
+msgid "Sale Extras"
+msgstr "Sale Extras"
+
+msgctxt "model:ir.rule.group,name:rule_group_extra_companies"
+msgid "User in companies"
+msgstr ""
+
+#, fuzzy
+msgctxt "model:ir.ui.menu,name:menu_extra"
+msgid "Extras"
+msgstr "Extras"
+
+msgctxt "model:sale.extra,name:"
+msgid "Sale Extra"
+msgstr "Eladási extrák"
+
+msgctxt "model:sale.extra.line,name:"
+msgid "Sale Extra Line"
+msgstr "Eladási extra sor"
+
+msgctxt "view:sale.extra.line:"
+msgid "Sale Line"
+msgstr "Eladási sor"
diff --git a/modules/sale_extra/locale/id.po b/modules/sale_extra/locale/id.po
new file mode 100644
index 0000000000..a19ff9a53c
--- /dev/null
+++ b/modules/sale_extra/locale/id.po
@@ -0,0 +1,100 @@
+#
+msgid ""
+msgstr "Content-Type: text/plain; charset=utf-8\n"
+
+msgctxt "field:sale.extra,company:"
+msgid "Company"
+msgstr "Perusahaan"
+
+msgctxt "field:sale.extra,currency_digits:"
+msgid "Currency Digits"
+msgstr ""
+
+msgctxt "field:sale.extra,end_date:"
+msgid "End Date"
+msgstr "Tanggal Akhir"
+
+msgctxt "field:sale.extra,lines:"
+msgid "Lines"
+msgstr "Baris"
+
+msgctxt "field:sale.extra,name:"
+msgid "Name"
+msgstr "Nama"
+
+msgctxt "field:sale.extra,price_list:"
+msgid "Price List"
+msgstr ""
+
+msgctxt "field:sale.extra,sale_amount:"
+msgid "Sale Amount"
+msgstr ""
+
+msgctxt "field:sale.extra,start_date:"
+msgid "Start Date"
+msgstr "Tanggal Awal"
+
+msgctxt "field:sale.extra.line,extra:"
+msgid "Extra"
+msgstr ""
+
+msgctxt "field:sale.extra.line,free:"
+msgid "Free"
+msgstr ""
+
+msgctxt "field:sale.extra.line,product:"
+msgid "Product"
+msgstr "Produk"
+
+msgctxt "field:sale.extra.line,product_uom_category:"
+msgid "Product UoM Category"
+msgstr ""
+
+msgctxt "field:sale.extra.line,quantity:"
+msgid "Quantity"
+msgstr ""
+
+msgctxt "field:sale.extra.line,sale_amount:"
+msgid "Sale Amount"
+msgstr ""
+
+msgctxt "field:sale.extra.line,unit:"
+msgid "Unit"
+msgstr ""
+
+msgctxt "field:sale.extra.line,unit_digits:"
+msgid "Unit Digits"
+msgstr ""
+
+msgctxt "field:sale.line,extra:"
+msgid "Extra"
+msgstr ""
+
+msgctxt "model:ir.action,name:act_extra_form"
+msgid "Extras"
+msgstr ""
+
+msgctxt "model:ir.action,name:act_extra_relate"
+msgid "Sale Extras"
+msgstr ""
+
+#, fuzzy
+msgctxt "model:ir.rule.group,name:rule_group_extra_companies"
+msgid "User in companies"
+msgstr "Pengguna di dalam perusahaan"
+
+msgctxt "model:ir.ui.menu,name:menu_extra"
+msgid "Extras"
+msgstr ""
+
+msgctxt "model:sale.extra,name:"
+msgid "Sale Extra"
+msgstr ""
+
+msgctxt "model:sale.extra.line,name:"
+msgid "Sale Extra Line"
+msgstr ""
+
+msgctxt "view:sale.extra.line:"
+msgid "Sale Line"
+msgstr "Baris Penjualan"
diff --git a/modules/sale_extra/locale/it.po b/modules/sale_extra/locale/it.po
new file mode 100644
index 0000000000..8b91ff29e4
--- /dev/null
+++ b/modules/sale_extra/locale/it.po
@@ -0,0 +1,101 @@
+#
+msgid ""
+msgstr "Content-Type: text/plain; charset=utf-8\n"
+
+msgctxt "field:sale.extra,company:"
+msgid "Company"
+msgstr "Azienda"
+
+msgctxt "field:sale.extra,currency_digits:"
+msgid "Currency Digits"
+msgstr "posizioni valuta"
+
+msgctxt "field:sale.extra,end_date:"
+msgid "End Date"
+msgstr "Data fine"
+
+msgctxt "field:sale.extra,lines:"
+msgid "Lines"
+msgstr "Righe"
+
+msgctxt "field:sale.extra,name:"
+msgid "Name"
+msgstr "Nome"
+
+msgctxt "field:sale.extra,price_list:"
+msgid "Price List"
+msgstr "Listino"
+
+msgctxt "field:sale.extra,sale_amount:"
+msgid "Sale Amount"
+msgstr "Importo vendita"
+
+msgctxt "field:sale.extra,start_date:"
+msgid "Start Date"
+msgstr "Data inizio"
+
+msgctxt "field:sale.extra.line,extra:"
+msgid "Extra"
+msgstr "Extra"
+
+msgctxt "field:sale.extra.line,free:"
+msgid "Free"
+msgstr "Libero"
+
+msgctxt "field:sale.extra.line,product:"
+msgid "Product"
+msgstr "Prodotto"
+
+msgctxt "field:sale.extra.line,product_uom_category:"
+msgid "Product UoM Category"
+msgstr "Categoria UdM prodotto"
+
+msgctxt "field:sale.extra.line,quantity:"
+msgid "Quantity"
+msgstr "Quantità"
+
+msgctxt "field:sale.extra.line,sale_amount:"
+msgid "Sale Amount"
+msgstr "Importo vendita"
+
+msgctxt "field:sale.extra.line,unit:"
+msgid "Unit"
+msgstr "Unità"
+
+msgctxt "field:sale.extra.line,unit_digits:"
+msgid "Unit Digits"
+msgstr "Posizioni Unità"
+
+msgctxt "field:sale.line,extra:"
+msgid "Extra"
+msgstr "Extra"
+
+msgctxt "model:ir.action,name:act_extra_form"
+msgid "Extras"
+msgstr "Extras"
+
+#, fuzzy
+msgctxt "model:ir.action,name:act_extra_relate"
+msgid "Sale Extras"
+msgstr "Sale Extras"
+
+msgctxt "model:ir.rule.group,name:rule_group_extra_companies"
+msgid "User in companies"
+msgstr ""
+
+#, fuzzy
+msgctxt "model:ir.ui.menu,name:menu_extra"
+msgid "Extras"
+msgstr "Extras"
+
+msgctxt "model:sale.extra,name:"
+msgid "Sale Extra"
+msgstr "extra vendita"
+
+msgctxt "model:sale.extra.line,name:"
+msgid "Sale Extra Line"
+msgstr "riga extra vendita"
+
+msgctxt "view:sale.extra.line:"
+msgid "Sale Line"
+msgstr "riga vendita"
diff --git a/modules/sale_extra/locale/lo.po b/modules/sale_extra/locale/lo.po
new file mode 100644
index 0000000000..5376754f2f
--- /dev/null
+++ b/modules/sale_extra/locale/lo.po
@@ -0,0 +1,114 @@
+#
+msgid ""
+msgstr "Content-Type: text/plain; charset=utf-8\n"
+
+#, fuzzy
+msgctxt "field:sale.extra,company:"
+msgid "Company"
+msgstr "ຫ້ອງການ/ສຳນັກງານ"
+
+#, fuzzy
+msgctxt "field:sale.extra,currency_digits:"
+msgid "Currency Digits"
+msgstr "ໂຕເລກສະກຸນເງິນ"
+
+#, fuzzy
+msgctxt "field:sale.extra,end_date:"
+msgid "End Date"
+msgstr "ວັນທີສິ້ນສຸດ"
+
+#, fuzzy
+msgctxt "field:sale.extra,lines:"
+msgid "Lines"
+msgstr "ຮ່ວງ"
+
+#, fuzzy
+msgctxt "field:sale.extra,name:"
+msgid "Name"
+msgstr "ຊື່"
+
+#, fuzzy
+msgctxt "field:sale.extra,price_list:"
+msgid "Price List"
+msgstr "ລາຍການລາຄາ"
+
+msgctxt "field:sale.extra,sale_amount:"
+msgid "Sale Amount"
+msgstr ""
+
+#, fuzzy
+msgctxt "field:sale.extra,start_date:"
+msgid "Start Date"
+msgstr "ວັນທີເລີ່ມ"
+
+#, fuzzy
+msgctxt "field:sale.extra.line,extra:"
+msgid "Extra"
+msgstr "Extras"
+
+#, fuzzy
+msgctxt "field:sale.extra.line,free:"
+msgid "Free"
+msgstr "ວ່າງ"
+
+#, fuzzy
+msgctxt "field:sale.extra.line,product:"
+msgid "Product"
+msgstr "ຜະລິດຕະພັນ"
+
+msgctxt "field:sale.extra.line,product_uom_category:"
+msgid "Product UoM Category"
+msgstr ""
+
+#, fuzzy
+msgctxt "field:sale.extra.line,quantity:"
+msgid "Quantity"
+msgstr "ຈຳນວນ"
+
+msgctxt "field:sale.extra.line,sale_amount:"
+msgid "Sale Amount"
+msgstr ""
+
+#, fuzzy
+msgctxt "field:sale.extra.line,unit:"
+msgid "Unit"
+msgstr "ໜ່ວຍ"
+
+#, fuzzy
+msgctxt "field:sale.extra.line,unit_digits:"
+msgid "Unit Digits"
+msgstr "ຫົວໜ່ວຍເສດ"
+
+#, fuzzy
+msgctxt "field:sale.line,extra:"
+msgid "Extra"
+msgstr "Extras"
+
+msgctxt "model:ir.action,name:act_extra_form"
+msgid "Extras"
+msgstr "Extras"
+
+msgctxt "model:ir.action,name:act_extra_relate"
+msgid "Sale Extras"
+msgstr "Sale Extras"
+
+msgctxt "model:ir.rule.group,name:rule_group_extra_companies"
+msgid "User in companies"
+msgstr ""
+
+msgctxt "model:ir.ui.menu,name:menu_extra"
+msgid "Extras"
+msgstr "Extras"
+
+#, fuzzy
+msgctxt "model:sale.extra,name:"
+msgid "Sale Extra"
+msgstr "Sale Extras"
+
+msgctxt "model:sale.extra.line,name:"
+msgid "Sale Extra Line"
+msgstr ""
+
+msgctxt "view:sale.extra.line:"
+msgid "Sale Line"
+msgstr ""
diff --git a/modules/sale_extra/locale/lt.po b/modules/sale_extra/locale/lt.po
new file mode 100644
index 0000000000..7dbf397a9e
--- /dev/null
+++ b/modules/sale_extra/locale/lt.po
@@ -0,0 +1,103 @@
+#
+msgid ""
+msgstr "Content-Type: text/plain; charset=utf-8\n"
+
+msgctxt "field:sale.extra,company:"
+msgid "Company"
+msgstr "Organizacija"
+
+msgctxt "field:sale.extra,currency_digits:"
+msgid "Currency Digits"
+msgstr "Valiutos skaitmenų skaičius"
+
+msgctxt "field:sale.extra,end_date:"
+msgid "End Date"
+msgstr "Pabaigos data"
+
+msgctxt "field:sale.extra,lines:"
+msgid "Lines"
+msgstr ""
+
+#, fuzzy
+msgctxt "field:sale.extra,name:"
+msgid "Name"
+msgstr "Namu"
+
+msgctxt "field:sale.extra,price_list:"
+msgid "Price List"
+msgstr ""
+
+msgctxt "field:sale.extra,sale_amount:"
+msgid "Sale Amount"
+msgstr ""
+
+msgctxt "field:sale.extra,start_date:"
+msgid "Start Date"
+msgstr "Pradžios data"
+
+#, fuzzy
+msgctxt "field:sale.extra.line,extra:"
+msgid "Extra"
+msgstr "Extras"
+
+msgctxt "field:sale.extra.line,free:"
+msgid "Free"
+msgstr ""
+
+msgctxt "field:sale.extra.line,product:"
+msgid "Product"
+msgstr ""
+
+msgctxt "field:sale.extra.line,product_uom_category:"
+msgid "Product UoM Category"
+msgstr ""
+
+msgctxt "field:sale.extra.line,quantity:"
+msgid "Quantity"
+msgstr ""
+
+msgctxt "field:sale.extra.line,sale_amount:"
+msgid "Sale Amount"
+msgstr ""
+
+msgctxt "field:sale.extra.line,unit:"
+msgid "Unit"
+msgstr ""
+
+msgctxt "field:sale.extra.line,unit_digits:"
+msgid "Unit Digits"
+msgstr ""
+
+#, fuzzy
+msgctxt "field:sale.line,extra:"
+msgid "Extra"
+msgstr "Extras"
+
+msgctxt "model:ir.action,name:act_extra_form"
+msgid "Extras"
+msgstr "Extras"
+
+msgctxt "model:ir.action,name:act_extra_relate"
+msgid "Sale Extras"
+msgstr "Sale Extras"
+
+msgctxt "model:ir.rule.group,name:rule_group_extra_companies"
+msgid "User in companies"
+msgstr ""
+
+msgctxt "model:ir.ui.menu,name:menu_extra"
+msgid "Extras"
+msgstr "Extras"
+
+#, fuzzy
+msgctxt "model:sale.extra,name:"
+msgid "Sale Extra"
+msgstr "Sale Extras"
+
+msgctxt "model:sale.extra.line,name:"
+msgid "Sale Extra Line"
+msgstr ""
+
+msgctxt "view:sale.extra.line:"
+msgid "Sale Line"
+msgstr ""
diff --git a/modules/sale_extra/locale/nl.po b/modules/sale_extra/locale/nl.po
new file mode 100644
index 0000000000..6d03d50e31
--- /dev/null
+++ b/modules/sale_extra/locale/nl.po
@@ -0,0 +1,100 @@
+#
+msgid ""
+msgstr "Content-Type: text/plain; charset=utf-8\n"
+
+msgctxt "field:sale.extra,company:"
+msgid "Company"
+msgstr "Bedrijf"
+
+msgctxt "field:sale.extra,currency_digits:"
+msgid "Currency Digits"
+msgstr "Valuta decimalen"
+
+msgctxt "field:sale.extra,end_date:"
+msgid "End Date"
+msgstr "Eind datum"
+
+msgctxt "field:sale.extra,lines:"
+msgid "Lines"
+msgstr "Regels"
+
+msgctxt "field:sale.extra,name:"
+msgid "Name"
+msgstr "Naam"
+
+msgctxt "field:sale.extra,price_list:"
+msgid "Price List"
+msgstr "Prijslijst"
+
+msgctxt "field:sale.extra,sale_amount:"
+msgid "Sale Amount"
+msgstr "Verkoopbedrag"
+
+msgctxt "field:sale.extra,start_date:"
+msgid "Start Date"
+msgstr "Start datum"
+
+msgctxt "field:sale.extra.line,extra:"
+msgid "Extra"
+msgstr "Extra"
+
+msgctxt "field:sale.extra.line,free:"
+msgid "Free"
+msgstr "Gratis"
+
+msgctxt "field:sale.extra.line,product:"
+msgid "Product"
+msgstr "Product"
+
+msgctxt "field:sale.extra.line,product_uom_category:"
+msgid "Product UoM Category"
+msgstr "product eenheidsmaat categorie"
+
+msgctxt "field:sale.extra.line,quantity:"
+msgid "Quantity"
+msgstr "Hoeveelheid"
+
+msgctxt "field:sale.extra.line,sale_amount:"
+msgid "Sale Amount"
+msgstr "Verkoopbedrag"
+
+msgctxt "field:sale.extra.line,unit:"
+msgid "Unit"
+msgstr "Eenheid"
+
+msgctxt "field:sale.extra.line,unit_digits:"
+msgid "Unit Digits"
+msgstr "Decimalen eenheid"
+
+msgctxt "field:sale.line,extra:"
+msgid "Extra"
+msgstr "Extra"
+
+msgctxt "model:ir.action,name:act_extra_form"
+msgid "Extras"
+msgstr "Extras"
+
+msgctxt "model:ir.action,name:act_extra_relate"
+msgid "Sale Extras"
+msgstr "verkoop Extras"
+
+#, fuzzy
+msgctxt "model:ir.rule.group,name:rule_group_extra_companies"
+msgid "User in companies"
+msgstr "Gebruiker in het bedrijf"
+
+msgctxt "model:ir.ui.menu,name:menu_extra"
+msgid "Extras"
+msgstr "Extras"
+
+msgctxt "model:sale.extra,name:"
+msgid "Sale Extra"
+msgstr "verkoop Extras"
+
+msgctxt "model:sale.extra.line,name:"
+msgid "Sale Extra Line"
+msgstr "Verkoop extra lijn"
+
+msgctxt "view:sale.extra.line:"
+msgid "Sale Line"
+msgstr "Verkooplijn"
diff --git a/modules/sale_extra/locale/pl.po b/modules/sale_extra/locale/pl.po
new file mode 100644
index 0000000000..5c8b335cf2
--- /dev/null
+++ b/modules/sale_extra/locale/pl.po
@@ -0,0 +1,105 @@
+#
+msgid ""
+msgstr "Content-Type: text/plain; charset=utf-8\n"
+
+msgctxt "field:sale.extra,company:"
+msgid "Company"
+msgstr "Firma"
+
+msgctxt "field:sale.extra,currency_digits:"
+msgid "Currency Digits"
+msgstr "Cyfry waluty"
+
+msgctxt "field:sale.extra,end_date:"
+msgid "End Date"
+msgstr "Data ukończenia"
+
+msgctxt "field:sale.extra,lines:"
+msgid "Lines"
+msgstr "Wiersze"
+
+msgctxt "field:sale.extra,name:"
+msgid "Name"
+msgstr "Nazwa"
+
+msgctxt "field:sale.extra,price_list:"
+msgid "Price List"
+msgstr "Cennik"
+
+msgctxt "field:sale.extra,sale_amount:"
+msgid "Sale Amount"
+msgstr ""
+
+msgctxt "field:sale.extra,start_date:"
+msgid "Start Date"
+msgstr "Data rozpoczęcia"
+
+#, fuzzy
+msgctxt "field:sale.extra.line,extra:"
+msgid "Extra"
+msgstr "Extras"
+
+msgctxt "field:sale.extra.line,free:"
+msgid "Free"
+msgstr ""
+
+msgctxt "field:sale.extra.line,product:"
+msgid "Product"
+msgstr "Produkt"
+
+msgctxt "field:sale.extra.line,product_uom_category:"
+msgid "Product UoM Category"
+msgstr "Kategoria jm produktu"
+
+msgctxt "field:sale.extra.line,quantity:"
+msgid "Quantity"
+msgstr "Ilość"
+
+msgctxt "field:sale.extra.line,sale_amount:"
+msgid "Sale Amount"
+msgstr ""
+
+msgctxt "field:sale.extra.line,unit:"
+msgid "Unit"
+msgstr "Jednostka"
+
+msgctxt "field:sale.extra.line,unit_digits:"
+msgid "Unit Digits"
+msgstr "Cyfry jednostki"
+
+#, fuzzy
+msgctxt "field:sale.line,extra:"
+msgid "Extra"
+msgstr "Extras"
+
+#, fuzzy
+msgctxt "model:ir.action,name:act_extra_form"
+msgid "Extras"
+msgstr "Extras"
+
+#, fuzzy
+msgctxt "model:ir.action,name:act_extra_relate"
+msgid "Sale Extras"
+msgstr "Sale Extras"
+
+msgctxt "model:ir.rule.group,name:rule_group_extra_companies"
+msgid "User in companies"
+msgstr ""
+
+#, fuzzy
+msgctxt "model:ir.ui.menu,name:menu_extra"
+msgid "Extras"
+msgstr "Extras"
+
+#, fuzzy
+msgctxt "model:sale.extra,name:"
+msgid "Sale Extra"
+msgstr "Sale Extras"
+
+msgctxt "model:sale.extra.line,name:"
+msgid "Sale Extra Line"
+msgstr ""
+
+msgctxt "view:sale.extra.line:"
+msgid "Sale Line"
+msgstr "Wiersz sprzedaży"
diff --git a/modules/sale_extra/locale/pt.po b/modules/sale_extra/locale/pt.po
new file mode 100644
index 0000000000..79f82d078f
--- /dev/null
+++ b/modules/sale_extra/locale/pt.po
@@ -0,0 +1,100 @@
+#
+msgid ""
+msgstr "Content-Type: text/plain; charset=utf-8\n"
+
+msgctxt "field:sale.extra,company:"
+msgid "Company"
+msgstr "Empresa"
+
+msgctxt "field:sale.extra,currency_digits:"
+msgid "Currency Digits"
+msgstr "Dígitos Decimais da Moeda"
+
+msgctxt "field:sale.extra,end_date:"
+msgid "End Date"
+msgstr "Data Final"
+
+msgctxt "field:sale.extra,lines:"
+msgid "Lines"
+msgstr "Linhas"
+
+msgctxt "field:sale.extra,name:"
+msgid "Name"
+msgstr "Nome"
+
+msgctxt "field:sale.extra,price_list:"
+msgid "Price List"
+msgstr "Lista de Preços"
+
+msgctxt "field:sale.extra,sale_amount:"
+msgid "Sale Amount"
+msgstr "Montande de Venda"
+
+msgctxt "field:sale.extra,start_date:"
+msgid "Start Date"
+msgstr "Data inicial"
+
+msgctxt "field:sale.extra.line,extra:"
+msgid "Extra"
+msgstr "Extra"
+
+msgctxt "field:sale.extra.line,free:"
+msgid "Free"
+msgstr "Gratuito"
+
+msgctxt "field:sale.extra.line,product:"
+msgid "Product"
+msgstr "Produto"
+
+msgctxt "field:sale.extra.line,product_uom_category:"
+msgid "Product UoM Category"
+msgstr "Categoria da UDM do Produto"
+
+msgctxt "field:sale.extra.line,quantity:"
+msgid "Quantity"
+msgstr "Quantidade"
+
+msgctxt "field:sale.extra.line,sale_amount:"
+msgid "Sale Amount"
+msgstr "Montante da Venda"
+
+msgctxt "field:sale.extra.line,unit:"
+msgid "Unit"
+msgstr "Unidade"
+
+msgctxt "field:sale.extra.line,unit_digits:"
+msgid "Unit Digits"
+msgstr "Dígitos Decimais da Unidade"
+
+msgctxt "field:sale.line,extra:"
+msgid "Extra"
+msgstr "Extra"
+
+msgctxt "model:ir.action,name:act_extra_form"
+msgid "Extras"
+msgstr "Extras"
+
+#, fuzzy
+msgctxt "model:ir.action,name:act_extra_relate"
+msgid "Sale Extras"
+msgstr "Sale Extras"
+
+msgctxt "model:ir.rule.group,name:rule_group_extra_companies"
+msgid "User in companies"
+msgstr ""
+
+msgctxt "model:ir.ui.menu,name:menu_extra"
+msgid "Extras"
+msgstr "Extras"
+
+msgctxt "model:sale.extra,name:"
+msgid "Sale Extra"
+msgstr "Extra de Venda"
+
+msgctxt "model:sale.extra.line,name:"
+msgid "Sale Extra Line"
+msgstr "Linha Extra de Venda"
+
+msgctxt "view:sale.extra.line:"
+msgid "Sale Line"
+msgstr "Linha de Venda"
diff --git a/modules/sale_extra/locale/ro.po b/modules/sale_extra/locale/ro.po
new file mode 100644
index 0000000000..6330db5afc
--- /dev/null
+++ b/modules/sale_extra/locale/ro.po
@@ -0,0 +1,99 @@
+#
+msgid ""
+msgstr "Content-Type: text/plain; charset=utf-8\n"
+
+msgctxt "field:sale.extra,company:"
+msgid "Company"
+msgstr "Companie"
+
+msgctxt "field:sale.extra,currency_digits:"
+msgid "Currency Digits"
+msgstr "Zecimale valută"
+
+msgctxt "field:sale.extra,end_date:"
+msgid "End Date"
+msgstr ""
+
+msgctxt "field:sale.extra,lines:"
+msgid "Lines"
+msgstr "Rânduri"
+
+msgctxt "field:sale.extra,name:"
+msgid "Name"
+msgstr ""
+
+msgctxt "field:sale.extra,price_list:"
+msgid "Price List"
+msgstr "Listă de prețuri"
+
+msgctxt "field:sale.extra,sale_amount:"
+msgid "Sale Amount"
+msgstr ""
+
+msgctxt "field:sale.extra,start_date:"
+msgid "Start Date"
+msgstr ""
+
+msgctxt "field:sale.extra.line,extra:"
+msgid "Extra"
+msgstr ""
+
+msgctxt "field:sale.extra.line,free:"
+msgid "Free"
+msgstr ""
+
+msgctxt "field:sale.extra.line,product:"
+msgid "Product"
+msgstr "Produs"
+
+msgctxt "field:sale.extra.line,product_uom_category:"
+msgid "Product UoM Category"
+msgstr ""
+
+msgctxt "field:sale.extra.line,quantity:"
+msgid "Quantity"
+msgstr ""
+
+msgctxt "field:sale.extra.line,sale_amount:"
+msgid "Sale Amount"
+msgstr ""
+
+msgctxt "field:sale.extra.line,unit:"
+msgid "Unit"
+msgstr ""
+
+msgctxt "field:sale.extra.line,unit_digits:"
+msgid "Unit Digits"
+msgstr ""
+
+msgctxt "field:sale.line,extra:"
+msgid "Extra"
+msgstr ""
+
+msgctxt "model:ir.action,name:act_extra_form"
+msgid "Extras"
+msgstr ""
+
+msgctxt "model:ir.action,name:act_extra_relate"
+msgid "Sale Extras"
+msgstr ""
+
+msgctxt "model:ir.rule.group,name:rule_group_extra_companies"
+msgid "User in companies"
+msgstr ""
+
+msgctxt "model:ir.ui.menu,name:menu_extra"
+msgid "Extras"
+msgstr ""
+
+msgctxt "model:sale.extra,name:"
+msgid "Sale Extra"
+msgstr ""
+
+msgctxt "model:sale.extra.line,name:"
+msgid "Sale Extra Line"
+msgstr ""
+
+msgctxt "view:sale.extra.line:"
+msgid "Sale Line"
+msgstr ""
diff --git a/modules/sale_extra/locale/ru.po b/modules/sale_extra/locale/ru.po
new file mode 100644
index 0000000000..7b3b97a3e5
--- /dev/null
+++ b/modules/sale_extra/locale/ru.po
@@ -0,0 +1,114 @@
+#
+msgid ""
+msgstr "Content-Type: text/plain; charset=utf-8\n"
+
+#, fuzzy
+msgctxt "field:sale.extra,company:"
+msgid "Company"
+msgstr "Учет.орг."
+
+#, fuzzy
+msgctxt "field:sale.extra,currency_digits:"
+msgid "Currency Digits"
+msgstr "Кол-во цифр валюты"
+
+#, fuzzy
+msgctxt "field:sale.extra,end_date:"
+msgid "End Date"
+msgstr "Дата окончания"
+
+#, fuzzy
+msgctxt "field:sale.extra,lines:"
+msgid "Lines"
+msgstr "Строки"
+
+#, fuzzy
+msgctxt "field:sale.extra,name:"
+msgid "Name"
+msgstr "Правило оплаты"
+
+msgctxt "field:sale.extra,price_list:"
+msgid "Price List"
+msgstr ""
+
+msgctxt "field:sale.extra,sale_amount:"
+msgid "Sale Amount"
+msgstr ""
+
+#, fuzzy
+msgctxt "field:sale.extra,start_date:"
+msgid "Start Date"
+msgstr "Дата начала"
+
+#, fuzzy
+msgctxt "field:sale.extra.line,extra:"
+msgid "Extra"
+msgstr "Extras"
+
+#, fuzzy
+msgctxt "field:sale.extra.line,free:"
+msgid "Free"
+msgstr "Свободно"
+
+#, fuzzy
+msgctxt "field:sale.extra.line,product:"
+msgid "Product"
+msgstr "Товарно материальные ценности (ТМЦ)"
+
+msgctxt "field:sale.extra.line,product_uom_category:"
+msgid "Product UoM Category"
+msgstr ""
+
+#, fuzzy
+msgctxt "field:sale.extra.line,quantity:"
+msgid "Quantity"
+msgstr "Кол-во"
+
+msgctxt "field:sale.extra.line,sale_amount:"
+msgid "Sale Amount"
+msgstr ""
+
+#, fuzzy
+msgctxt "field:sale.extra.line,unit:"
+msgid "Unit"
+msgstr "Штука"
+
+#, fuzzy
+msgctxt "field:sale.extra.line,unit_digits:"
+msgid "Unit Digits"
+msgstr "Кол-во цифр после запятой"
+
+#, fuzzy
+msgctxt "field:sale.line,extra:"
+msgid "Extra"
+msgstr "Extras"
+
+msgctxt "model:ir.action,name:act_extra_form"
+msgid "Extras"
+msgstr "Extras"
+
+msgctxt "model:ir.action,name:act_extra_relate"
+msgid "Sale Extras"
+msgstr "Sale Extras"
+
+msgctxt "model:ir.rule.group,name:rule_group_extra_companies"
+msgid "User in companies"
+msgstr ""
+
+msgctxt "model:ir.ui.menu,name:menu_extra"
+msgid "Extras"
+msgstr "Extras"
+
+#, fuzzy
+msgctxt "model:sale.extra,name:"
+msgid "Sale Extra"
+msgstr "Sale Extras"
+
+msgctxt "model:sale.extra.line,name:"
+msgid "Sale Extra Line"
+msgstr ""
+
+#, fuzzy
+msgctxt "view:sale.extra.line:"
+msgid "Sale Line"
+msgstr "Строка продажи"
diff --git a/modules/sale_extra/locale/sl.po b/modules/sale_extra/locale/sl.po
new file mode 100644
index 0000000000..a8d214e4aa
--- /dev/null
+++ b/modules/sale_extra/locale/sl.po
@@ -0,0 +1,102 @@
+#
+msgid ""
+msgstr "Content-Type: text/plain; charset=utf-8\n"
+
+msgctxt "field:sale.extra,company:"
+msgid "Company"
+msgstr "Družba"
+
+msgctxt "field:sale.extra,currency_digits:"
+msgid "Currency Digits"
+msgstr "Decimalke"
+
+msgctxt "field:sale.extra,end_date:"
+msgid "End Date"
+msgstr "Končni datum"
+
+msgctxt "field:sale.extra,lines:"
+msgid "Lines"
+msgstr "Postavke"
+
+msgctxt "field:sale.extra,name:"
+msgid "Name"
+msgstr "Naziv"
+
+msgctxt "field:sale.extra,price_list:"
+msgid "Price List"
+msgstr "Cenik"
+
+msgctxt "field:sale.extra,sale_amount:"
+msgid "Sale Amount"
+msgstr "Znesek prodaje"
+
+msgctxt "field:sale.extra,start_date:"
+msgid "Start Date"
+msgstr "Začetni datum"
+
+msgctxt "field:sale.extra.line,extra:"
+msgid "Extra"
+msgstr "Dodatno"
+
+msgctxt "field:sale.extra.line,free:"
+msgid "Free"
+msgstr "Prosto"
+
+msgctxt "field:sale.extra.line,product:"
+msgid "Product"
+msgstr "Izdelek"
+
+msgctxt "field:sale.extra.line,product_uom_category:"
+msgid "Product UoM Category"
+msgstr "Kategorije EM izdelka"
+
+msgctxt "field:sale.extra.line,quantity:"
+msgid "Quantity"
+msgstr "Količina"
+
+msgctxt "field:sale.extra.line,sale_amount:"
+msgid "Sale Amount"
+msgstr "Znesek prodaje"
+
+msgctxt "field:sale.extra.line,unit:"
+msgid "Unit"
+msgstr "enota"
+
+msgctxt "field:sale.extra.line,unit_digits:"
+msgid "Unit Digits"
+msgstr "Decimalke"
+
+msgctxt "field:sale.line,extra:"
+msgid "Extra"
+msgstr "Dodatno"
+
+#, fuzzy
+msgctxt "model:ir.action,name:act_extra_form"
+msgid "Extras"
+msgstr "Extras"
+
+#, fuzzy
+msgctxt "model:ir.action,name:act_extra_relate"
+msgid "Sale Extras"
+msgstr "Sale Extras"
+
+msgctxt "model:ir.rule.group,name:rule_group_extra_companies"
+msgid "User in companies"
+msgstr ""
+
+#, fuzzy
+msgctxt "model:ir.ui.menu,name:menu_extra"
+msgid "Extras"
+msgstr "Extras"
+
+msgctxt "model:sale.extra,name:"
+msgid "Sale Extra"
+msgstr "Dodatno"
+
+msgctxt "model:sale.extra.line,name:"
+msgid "Sale Extra Line"
+msgstr "Dodatna prodajna postavka"
+
+msgctxt "view:sale.extra.line:"
+msgid "Sale Line"
+msgstr "Prodajna postavka"
diff --git a/modules/sale_extra/locale/tr.po b/modules/sale_extra/locale/tr.po
new file mode 100644
index 0000000000..2f9aa89137
--- /dev/null
+++ b/modules/sale_extra/locale/tr.po
@@ -0,0 +1,102 @@
+#
+msgid ""
+msgstr "Content-Type: text/plain; charset=utf-8\n"
+
+msgctxt "field:sale.extra,company:"
+msgid "Company"
+msgstr ""
+
+msgctxt "field:sale.extra,currency_digits:"
+msgid "Currency Digits"
+msgstr ""
+
+msgctxt "field:sale.extra,end_date:"
+msgid "End Date"
+msgstr ""
+
+msgctxt "field:sale.extra,lines:"
+msgid "Lines"
+msgstr ""
+
+msgctxt "field:sale.extra,name:"
+msgid "Name"
+msgstr ""
+
+msgctxt "field:sale.extra,price_list:"
+msgid "Price List"
+msgstr ""
+
+msgctxt "field:sale.extra,sale_amount:"
+msgid "Sale Amount"
+msgstr ""
+
+msgctxt "field:sale.extra,start_date:"
+msgid "Start Date"
+msgstr ""
+
+#, fuzzy
+msgctxt "field:sale.extra.line,extra:"
+msgid "Extra"
+msgstr "Extras"
+
+msgctxt "field:sale.extra.line,free:"
+msgid "Free"
+msgstr ""
+
+msgctxt "field:sale.extra.line,product:"
+msgid "Product"
+msgstr ""
+
+msgctxt "field:sale.extra.line,product_uom_category:"
+msgid "Product UoM Category"
+msgstr ""
+
+msgctxt "field:sale.extra.line,quantity:"
+msgid "Quantity"
+msgstr ""
+
+msgctxt "field:sale.extra.line,sale_amount:"
+msgid "Sale Amount"
+msgstr ""
+
+msgctxt "field:sale.extra.line,unit:"
+msgid "Unit"
+msgstr ""
+
+msgctxt "field:sale.extra.line,unit_digits:"
+msgid "Unit Digits"
+msgstr ""
+
+#, fuzzy
+msgctxt "field:sale.line,extra:"
+msgid "Extra"
+msgstr "Extras"
+
+msgctxt "model:ir.action,name:act_extra_form"
+msgid "Extras"
+msgstr "Extras"
+
+msgctxt "model:ir.action,name:act_extra_relate"
+msgid "Sale Extras"
+msgstr "Sale Extras"
+
+msgctxt "model:ir.rule.group,name:rule_group_extra_companies"
+msgid "User in companies"
+msgstr ""
+
+msgctxt "model:ir.ui.menu,name:menu_extra"
+msgid "Extras"
+msgstr "Extras"
+
+#, fuzzy
+msgctxt "model:sale.extra,name:"
+msgid "Sale Extra"
+msgstr "Sale Extras"
+
+msgctxt "model:sale.extra.line,name:"
+msgid "Sale Extra Line"
+msgstr ""
+
+msgctxt "view:sale.extra.line:"
+msgid "Sale Line"
+msgstr ""
diff --git a/modules/sale_extra/locale/zh_CN.po b/modules/sale_extra/locale/zh_CN.po
new file mode 100644
index 0000000000..4d0d8911f2
--- /dev/null
+++ b/modules/sale_extra/locale/zh_CN.po
@@ -0,0 +1,103 @@
+#
+msgid ""
+msgstr "Content-Type: text/plain; charset=utf-8\n"
+
+msgctxt "field:sale.extra,company:"
+msgid "Company"
+msgstr ""
+
+msgctxt "field:sale.extra,currency_digits:"
+msgid "Currency Digits"
+msgstr ""
+
+msgctxt "field:sale.extra,end_date:"
+msgid "End Date"
+msgstr ""
+
+msgctxt "field:sale.extra,lines:"
+msgid "Lines"
+msgstr ""
+
+#, fuzzy
+msgctxt "field:sale.extra,name:"
+msgid "Name"
+msgstr "纳木"
+
+msgctxt "field:sale.extra,price_list:"
+msgid "Price List"
+msgstr ""
+
+msgctxt "field:sale.extra,sale_amount:"
+msgid "Sale Amount"
+msgstr ""
+
+msgctxt "field:sale.extra,start_date:"
+msgid "Start Date"
+msgstr ""
+
+#, fuzzy
+msgctxt "field:sale.extra.line,extra:"
+msgid "Extra"
+msgstr "Extras"
+
+msgctxt "field:sale.extra.line,free:"
+msgid "Free"
+msgstr ""
+
+msgctxt "field:sale.extra.line,product:"
+msgid "Product"
+msgstr ""
+
+msgctxt "field:sale.extra.line,product_uom_category:"
+msgid "Product UoM Category"
+msgstr ""
+
+msgctxt "field:sale.extra.line,quantity:"
+msgid "Quantity"
+msgstr ""
+
+msgctxt "field:sale.extra.line,sale_amount:"
+msgid "Sale Amount"
+msgstr ""
+
+msgctxt "field:sale.extra.line,unit:"
+msgid "Unit"
+msgstr ""
+
+msgctxt "field:sale.extra.line,unit_digits:"
+msgid "Unit Digits"
+msgstr ""
+
+#, fuzzy
+msgctxt "field:sale.line,extra:"
+msgid "Extra"
+msgstr "Extras"
+
+msgctxt "model:ir.action,name:act_extra_form"
+msgid "Extras"
+msgstr "Extras"
+
+msgctxt "model:ir.action,name:act_extra_relate"
+msgid "Sale Extras"
+msgstr "Sale Extras"
+
+msgctxt "model:ir.rule.group,name:rule_group_extra_companies"
+msgid "User in companies"
+msgstr ""
+
+msgctxt "model:ir.ui.menu,name:menu_extra"
+msgid "Extras"
+msgstr "Extras"
+
+#, fuzzy
+msgctxt "model:sale.extra,name:"
+msgid "Sale Extra"
+msgstr "Sale Extras"
+
+msgctxt "model:sale.extra.line,name:"
+msgid "Sale Extra Line"
+msgstr ""
+
+msgctxt "view:sale.extra.line:"
+msgid "Sale Line"
+msgstr ""
diff --git a/modules/sale_extra/sale.py b/modules/sale_extra/sale.py
new file mode 100644
index 0000000000..4d30d5da4b
--- /dev/null
+++ b/modules/sale_extra/sale.py
@@ -0,0 +1,282 @@
+# This file is part of Tryton. The COPYRIGHT file at the top level of
+# this repository contains the full copyright notices and license terms.
+import datetime
+from decimal import Decimal
+
+from sql import Null
+
+from trytond.pool import PoolMeta, Pool
+from trytond.model import (
+ ModelSQL, ModelView, MatchMixin, Workflow, DeactivableMixin, fields,
+ sequence_ordered)
+from trytond.pyson import Eval, If
+from trytond.transaction import Transaction
+
+
+class Sale(metaclass=PoolMeta):
+ __name__ = 'sale.sale'
+
+ @classmethod
+ @ModelView.button
+ @Workflow.transition('quotation')
+ def quote(cls, sales):
+ pool = Pool()
+ Line = pool.get('sale.line')
+
+ super(Sale, cls).quote(sales)
+
+ lines_to_delete = []
+ for sale in sales:
+ sale.set_extra(lines_to_delete)
+ if lines_to_delete:
+ Line.delete(lines_to_delete)
+ cls.save(sales)
+
+ def set_extra(self, lines_to_delete):
+ 'Set extra lines and fill lines_to_delete'
+ pool = Pool()
+ Extra = pool.get('sale.extra')
+
+ extra_lines = Extra.get_lines(self)
+ extra2lines = {line.extra: line for line in extra_lines}
+ lines = list(self.lines)
+ for line in list(lines):
+ if line.type != 'line' or not line.extra:
+ continue
+ if line.extra in extra2lines:
+ del extra2lines[line.extra]
+ continue
+ else:
+ lines.remove(line)
+ lines_to_delete.append(line)
+ if extra2lines:
+ lines.extend(extra2lines.values())
+ self.lines = lines
+
+
+class Line(metaclass=PoolMeta):
+ __name__ = 'sale.line'
+
+ extra = fields.Many2One('sale.extra.line', 'Extra', ondelete='RESTRICT')
+
+
+class Extra(DeactivableMixin, ModelSQL, ModelView, MatchMixin):
+ 'Sale Extra'
+ __name__ = 'sale.extra'
+
+ name = fields.Char('Name', translate=True, required=True)
+ company = fields.Many2One(
+ 'company.company', "Company", required=True, select=True,
+ states={
+ 'readonly': Eval('id', 0) > 0,
+ })
+ start_date = fields.Date('Start Date',
+ domain=['OR',
+ ('start_date', '<=', If(~Eval('end_date', None),
+ datetime.date.max,
+ Eval('end_date', datetime.date.max))),
+ ('start_date', '=', None),
+ ],
+ depends=['end_date'])
+ end_date = fields.Date('End Date',
+ domain=['OR',
+ ('end_date', '>=', If(~Eval('start_date', None),
+ datetime.date.min,
+ Eval('start_date', datetime.date.min))),
+ ('end_date', '=', None),
+ ],
+ depends=['start_date'])
+ price_list = fields.Many2One('product.price_list', 'Price List',
+ ondelete='CASCADE',
+ domain=[
+ ('company', '=', Eval('company', -1)),
+ ],
+ depends=['company'])
+ sale_amount = fields.Numeric('Sale Amount',
+ digits=(16, Eval('currency_digits', 2)),
+ depends=['currency_digits'])
+ currency_digits = fields.Function(fields.Integer('Currency Digits'),
+ 'on_change_with_currency_digits')
+ lines = fields.One2Many('sale.extra.line', 'extra', 'Lines')
+
+ @classmethod
+ def __register__(cls, module_name):
+ pool = Pool()
+ PriceList = pool.get('product.price_list')
+ transaction = Transaction()
+ cursor = transaction.connection.cursor()
+ update = transaction.connection.cursor()
+ sql_table = cls.__table__()
+ price_list = PriceList.__table__()
+
+ super().__register__(module_name)
+
+ table = cls.__table_handler__(module_name)
+ # Migration from 3.6: price_list not required and new company
+ table.not_null_action('price_list', 'remove')
+ query = sql_table.join(price_list,
+ condition=sql_table.price_list == price_list.id
+ ).select(sql_table.id, price_list.company,
+ where=sql_table.company == Null)
+ cursor.execute(*query)
+ for extra_id, company_id in cursor:
+ query = sql_table.update([sql_table.company], [company_id],
+ where=sql_table.id == extra_id)
+ update.execute(*query)
+
+ @staticmethod
+ def default_company():
+ return Transaction().context.get('company')
+
+ @fields.depends('company')
+ def on_change_with_currency_digits(self, name=None):
+ if self.company:
+ return self.company.currency.digits
+ return 2
+
+ @classmethod
+ def _extras_domain(cls, sale):
+ return [
+ ['OR',
+ ('start_date', '<=', sale.sale_date),
+ ('start_date', '=', None),
+ ],
+ ['OR',
+ ('end_date', '=', None),
+ ('end_date', '>=', sale.sale_date),
+ ],
+ ['OR',
+ ('price_list', '=', None),
+ ('price_list', '=',
+ sale.price_list.id if sale.price_list else None),
+ ],
+ ('company', '=', sale.company.id),
+ ]
+
+ @classmethod
+ def get_lines(cls, sale, pattern=None):
+ 'Yield extra sale lines'
+ pool = Pool()
+ Currency = pool.get('currency.currency')
+ extras = cls.search(cls._extras_domain(sale))
+ if pattern is None:
+ pattern = {}
+ else:
+ pattern = pattern.copy()
+ pattern['sale_amount'] = Currency.compute(sale.currency,
+ sale.untaxed_amount, sale.company.currency)
+
+ for extra in extras:
+ epattern = pattern.copy()
+ epattern.update(extra.get_pattern(sale))
+ if extra.match(epattern):
+ for line in extra.lines:
+ lpattern = epattern.copy()
+ lpattern.update(line.get_pattern(sale))
+ if line.match(lpattern):
+ yield line.get_line(sale)
+ break
+
+ def get_pattern(self, sale):
+ return {}
+
+ def match(self, pattern):
+ pattern = pattern.copy()
+ sale_amount = pattern.pop('sale_amount')
+
+ match = super().match(pattern)
+
+ if self.sale_amount is not None:
+ if sale_amount < self.sale_amount:
+ return False
+ return match
+
+
+class ExtraLine(sequence_ordered(), ModelSQL, ModelView, MatchMixin):
+ 'Sale Extra Line'
+ __name__ = 'sale.extra.line'
+
+ extra = fields.Many2One('sale.extra', 'Extra', required=True,
+ ondelete='CASCADE')
+ sale_amount = fields.Numeric('Sale Amount',
+ digits=(16, Eval('_parent_extra', {}).get('currency_digits', 2)))
+ product = fields.Many2One('product.product', 'Product', required=True,
+ domain=[('salable', '=', True)])
+ product_uom_category = fields.Function(
+ fields.Many2One('product.uom.category', 'Product UoM Category'),
+ 'on_change_with_product_uom_category')
+ quantity = fields.Float('Quantity',
+ digits=(16, Eval('unit_digits', 2)), required=True,
+ depends=['unit_digits'])
+ unit = fields.Many2One('product.uom', 'Unit', required=True,
+ domain=[
+ ('category', '=', Eval('product_uom_category', -1)),
+ ],
+ depends=['product_uom_category'])
+ unit_digits = fields.Function(fields.Integer('Unit Digits'),
+ 'on_change_with_unit_digits')
+ free = fields.Boolean('Free')
+
+ @classmethod
+ def __setup__(cls):
+ super().__setup__()
+ cls.__access__.add('extra')
+ cls._order.insert(1, ('extra', 'ASC'))
+
+ @fields.depends('product')
+ def on_change_with_product_uom_category(self, name=None):
+ if self.product:
+ return self.product.default_uom_category.id
+
+ @fields.depends('unit')
+ def on_change_with_unit_digits(self, name=None):
+ if self.unit:
+ return self.unit.digits
+ return 2
+
+ @fields.depends('product')
+ def on_change_product(self):
+ if self.product:
+ self.unit = self.product.sale_uom
+
+ @staticmethod
+ def default_free():
+ return False
+
+ def get_pattern(self, sale):
+ return {}
+
+ def match(self, pattern):
+ pattern = pattern.copy()
+ sale_amount = pattern.pop('sale_amount')
+
+ match = super().match(pattern)
+
+ if self.sale_amount is not None:
+ if sale_amount < self.sale_amount:
+ return False
+ return match
+
+ def get_line(self, sale):
+ pool = Pool()
+ Line = pool.get('sale.line')
+
+ sequence = None
+ if sale.lines:
+ last_line = sale.lines[-1]
+ if last_line.sequence is not None:
+ sequence = last_line.sequence + 1
+
+ line = Line(
+ sale=sale,
+ sequence=sequence,
+ type='line',
+ product=self.product,
+ quantity=self.quantity,
+ unit=self.unit,
+ extra=self,
+ )
+ line.on_change_product()
+ if self.free:
+ line.unit_price = line.amount = Decimal(0)
+ return line
diff --git a/modules/sale_extra/sale.xml b/modules/sale_extra/sale.xml
new file mode 100644
index 0000000000..97efa16335
--- /dev/null
+++ b/modules/sale_extra/sale.xml
@@ -0,0 +1,106 @@
+
+
+
+
+
+ sale.extra
+ form
+ extra_form
+
+
+
+ sale.extra
+ tree
+ extra_list
+
+
+
+ Extras
+ sale.extra
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Sale Extras
+ sale.extra
+
+
+
+
+ form_relate
+ product.price_list,-1
+
+
+
+
+ User in companies
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ sale.extra.line
+ form
+ extra_line_form
+
+
+
+ sale.extra.line
+ tree
+ extra_line_list
+
+
+
+
+ sale.extra.line
+ tree
+ extra_line_list_sequence
+
+
+
+
diff --git a/modules/sale_extra/setup.py b/modules/sale_extra/setup.py
new file mode 100755
index 0000000000..c0fafb2938
--- /dev/null
+++ b/modules/sale_extra/setup.py
@@ -0,0 +1,149 @@
+#!/usr/bin/env python3
+# This file is part of Tryton. The COPYRIGHT file at the top level of
+# this repository contains the full copyright notices and license terms.
+
+import io
+import os
+import re
+from configparser import ConfigParser
+from setuptools import setup, find_packages
+
+
+def read(fname):
+ return io.open(
+ os.path.join(os.path.dirname(__file__), fname),
+ 'r', encoding='utf-8').read()
+
+
+def get_require_version(name):
+ if minor_version % 2:
+ require = '%s >= %s.%s.dev0, < %s.%s'
+ else:
+ require = '%s >= %s.%s, < %s.%s'
+ require %= (name, major_version, minor_version,
+ major_version, minor_version + 1)
+ return require
+
+
+config = ConfigParser()
+config.read_file(open(os.path.join(os.path.dirname(__file__), 'tryton.cfg')))
+info = dict(config.items('tryton'))
+for key in ('depends', 'extras_depend', 'xml'):
+ if key in info:
+ info[key] = info[key].strip().splitlines()
+version = info.get('version', '0.0.1')
+major_version, minor_version, _ = version.split('.', 2)
+major_version = int(major_version)
+minor_version = int(minor_version)
+name = 'trytond_sale_extra'
+
+download_url = 'http://downloads.tryton.org/%s.%s/' % (
+ major_version, minor_version)
+if minor_version % 2:
+ version = '%s.%s.dev0' % (major_version, minor_version)
+ download_url = (
+ 'hg+http://hg.tryton.org/modules/%s#egg=%s-%s' % (
+ name[8:], name, version))
+local_version = []
+if os.environ.get('CI_JOB_ID'):
+ local_version.append(os.environ['CI_JOB_ID'])
+else:
+ for build in ['CI_BUILD_NUMBER', 'CI_JOB_NUMBER']:
+ if os.environ.get(build):
+ local_version.append(os.environ[build])
+ else:
+ local_version = []
+ break
+if local_version:
+ version += '+' + '.'.join(local_version)
+
+requires = ['python-sql']
+for dep in info.get('depends', []):
+ if not re.match(r'(ir|res)(\W|$)', dep):
+ requires.append(get_require_version('trytond_%s' % dep))
+requires.append(get_require_version('trytond'))
+
+tests_require = [get_require_version('proteus')]
+dependency_links = []
+if minor_version % 2:
+ dependency_links.append(
+ 'https://trydevpi.tryton.org/?local_version='
+ + '.'.join(local_version))
+
+setup(name=name,
+ version=version,
+ description='Tryton module for sale extra',
+ long_description=read('README.rst'),
+ author='Tryton',
+ author_email='bugs@tryton.org',
+ url='http://www.tryton.org/',
+ download_url=download_url,
+ project_urls={
+ "Bug Tracker": 'https://bugs.tryton.org/',
+ "Documentation": 'https://docs.tryton.org/',
+ "Forum": 'https://www.tryton.org/forum',
+ "Source Code": 'https://hg.tryton.org/modules/sale_extra',
+ },
+ keywords='tryton sale extra premium cost',
+ package_dir={'trytond.modules.sale_extra': '.'},
+ packages=(
+ ['trytond.modules.sale_extra']
+ + ['trytond.modules.sale_extra.%s' % p for p in find_packages()]
+ ),
+ package_data={
+ 'trytond.modules.sale_extra': (info.get('xml', [])
+ + ['tryton.cfg', 'view/*.xml', 'locale/*.po', 'tests/*.rst']),
+ },
+ classifiers=[
+ 'Development Status :: 5 - Production/Stable',
+ 'Environment :: Plugins',
+ 'Framework :: Tryton',
+ 'Intended Audience :: Developers',
+ 'Intended Audience :: Financial and Insurance Industry',
+ 'Intended Audience :: Legal Industry',
+ 'License :: OSI Approved :: '
+ 'GNU General Public License v3 or later (GPLv3+)',
+ 'Natural Language :: Bulgarian',
+ 'Natural Language :: Catalan',
+ 'Natural Language :: Chinese (Simplified)',
+ 'Natural Language :: Czech',
+ 'Natural Language :: Dutch',
+ 'Natural Language :: English',
+ 'Natural Language :: Finnish',
+ 'Natural Language :: French',
+ 'Natural Language :: German',
+ 'Natural Language :: Hungarian',
+ 'Natural Language :: Indonesian',
+ 'Natural Language :: Italian',
+ 'Natural Language :: Persian',
+ 'Natural Language :: Polish',
+ 'Natural Language :: Portuguese (Brazilian)',
+ 'Natural Language :: Romanian',
+ 'Natural Language :: Russian',
+ 'Natural Language :: Slovenian',
+ 'Natural Language :: Spanish',
+ 'Natural Language :: Turkish',
+ 'Operating System :: OS Independent',
+ 'Programming Language :: Python :: 3',
+ 'Programming Language :: Python :: 3.6',
+ 'Programming Language :: Python :: 3.7',
+ 'Programming Language :: Python :: 3.8',
+ 'Programming Language :: Python :: 3.9',
+ 'Programming Language :: Python :: Implementation :: CPython',
+ 'Programming Language :: Python :: Implementation :: PyPy',
+ 'Topic :: Office/Business',
+ 'Topic :: Office/Business :: Financial :: Accounting',
+ ],
+ license='GPL-3',
+ python_requires='>=3.6',
+ install_requires=requires,
+ dependency_links=dependency_links,
+ zip_safe=False,
+ entry_points="""
+ [trytond.modules]
+ sale_extra = trytond.modules.sale_extra
+ """,
+ test_suite='tests',
+ test_loader='trytond.test_loader:Loader',
+ tests_require=tests_require,
+ )
diff --git a/modules/sale_extra/tests/__init__.py b/modules/sale_extra/tests/__init__.py
new file mode 100644
index 0000000000..d997401022
--- /dev/null
+++ b/modules/sale_extra/tests/__init__.py
@@ -0,0 +1,9 @@
+# This file is part of Tryton. The COPYRIGHT file at the top level of
+# this repository contains the full copyright notices and license terms.
+
+try:
+ from trytond.modules.sale_extra.tests.test_sale_extra import suite
+except ImportError:
+ from .test_sale_extra import suite
+
+__all__ = ['suite']
diff --git a/modules/sale_extra/tests/scenario_sale_extra.rst b/modules/sale_extra/tests/scenario_sale_extra.rst
new file mode 100644
index 0000000000..b4b8385f1b
--- /dev/null
+++ b/modules/sale_extra/tests/scenario_sale_extra.rst
@@ -0,0 +1,172 @@
+===================
+Sale Extra Scenario
+===================
+
+Imports::
+
+ >>> import datetime
+ >>> from dateutil.relativedelta import relativedelta
+ >>> from decimal import Decimal
+ >>> from proteus import Model, Wizard
+ >>> from trytond.tests.tools import activate_modules
+ >>> from trytond.modules.company.tests.tools import create_company, \
+ ... get_company
+ >>> from trytond.modules.account.tests.tools import create_chart, \
+ ... get_accounts
+ >>> from trytond.modules.account_invoice.tests.tools import \
+ ... create_payment_term
+ >>> today = datetime.date.today()
+
+Activate modules::
+
+ >>> config = activate_modules('sale_extra')
+
+Create company::
+
+ >>> _ = create_company()
+ >>> company = get_company()
+
+Create chart of accounts::
+
+ >>> _ = create_chart(company)
+ >>> accounts = get_accounts(company)
+ >>> revenue = accounts['revenue']
+ >>> expense = accounts['expense']
+
+Create customer::
+
+ >>> Party = Model.get('party.party')
+ >>> customer = Party(name='Customer')
+ >>> customer.save()
+
+Create account category::
+
+ >>> ProductCategory = Model.get('product.category')
+ >>> account_category = ProductCategory(name="Account Category")
+ >>> account_category.accounting = True
+ >>> account_category.account_revenue = revenue
+ >>> account_category.save()
+
+Create product::
+
+ >>> ProductUom = Model.get('product.uom')
+ >>> ProductTemplate = Model.get('product.template')
+ >>> unit, = ProductUom.find([('name', '=', 'Unit')])
+
+ >>> template = ProductTemplate()
+ >>> template.name = 'Product'
+ >>> template.default_uom = unit
+ >>> template.type = 'goods'
+ >>> template.salable = True
+ >>> template.lead_time = datetime.timedelta(0)
+ >>> template.list_price = Decimal('20')
+ >>> template.account_category = account_category
+ >>> template.save()
+ >>> product, = template.products
+
+ >>> extra_template = ProductTemplate()
+ >>> extra_template.name = 'Extra'
+ >>> extra_template.default_uom = unit
+ >>> extra_template.type = 'service'
+ >>> extra_template.salable = True
+ >>> extra_template.lead_time = datetime.timedelta(0)
+ >>> extra_template.list_price = Decimal('3')
+ >>> extra_template.account_category = account_category
+ >>> extra_template.save()
+ >>> extra_product, = extra_template.products
+
+Create payment term::
+
+ >>> payment_term = create_payment_term()
+ >>> payment_term.save()
+
+Create Extra::
+
+ >>> PriceList = Model.get('product.price_list')
+ >>> Extra = Model.get('sale.extra')
+ >>> price_list = PriceList(name='Default')
+ >>> price_list.save()
+ >>> extra = Extra(name='Free Extra')
+ >>> extra.price_list = price_list
+ >>> line = extra.lines.new()
+ >>> line.sale_amount = Decimal('100')
+ >>> line.product = extra_product
+ >>> line.quantity = 2
+ >>> line.free = True
+ >>> line = extra.lines.new()
+ >>> line.sale_amount = Decimal('50')
+ >>> line.product = extra_product
+ >>> line.quantity = 1
+ >>> extra.save()
+
+Sale for 100, 2 free extra added::
+
+ >>> Sale = Model.get('sale.sale')
+ >>> sale = Sale()
+ >>> sale.party = customer
+ >>> sale.price_list = price_list
+ >>> sale.payment_term = payment_term
+ >>> sale_line = sale.lines.new()
+ >>> sale_line.product = product
+ >>> sale_line.quantity = 5
+ >>> sale.save()
+ >>> sale.untaxed_amount
+ Decimal('100.00')
+ >>> len(sale.lines)
+ 1
+ >>> sale.click('quote')
+ >>> sale.untaxed_amount
+ Decimal('100.00')
+ >>> len(sale.lines)
+ 2
+ >>> sum(l.quantity for l in sale.lines)
+ 7.0
+
+Back to draft, nothing change::
+
+ >>> sale.click('draft')
+ >>> sale.click('quote')
+ >>> sale.untaxed_amount
+ Decimal('100.00')
+ >>> len(sale.lines)
+ 2
+
+Sale for 60, 1 extra added::
+
+ >>> sale = Sale()
+ >>> sale.party = customer
+ >>> sale.price_list = price_list
+ >>> sale.payment_term = payment_term
+ >>> sale_line = sale.lines.new()
+ >>> sale_line.product = product
+ >>> sale_line.quantity = 3
+ >>> sale.save()
+ >>> sale.untaxed_amount
+ Decimal('60.00')
+ >>> len(sale.lines)
+ 1
+ >>> sale.click('quote')
+ >>> sale.untaxed_amount
+ Decimal('63.00')
+ >>> len(sale.lines)
+ 2
+
+Sale for 20, nothing added::
+
+ >>> sale = Sale()
+ >>> sale.party = customer
+ >>> sale.price_list = price_list
+ >>> sale.payment_term = payment_term
+ >>> sale_line = sale.lines.new()
+ >>> sale_line.product = product
+ >>> sale_line.quantity = 1
+ >>> sale.save()
+ >>> sale.untaxed_amount
+ Decimal('20.00')
+ >>> len(sale.lines)
+ 1
+ >>> sale.click('quote')
+ >>> sale.untaxed_amount
+ Decimal('20.00')
+ >>> len(sale.lines)
+ 1
diff --git a/modules/sale_extra/tests/test_sale_extra.py b/modules/sale_extra/tests/test_sale_extra.py
new file mode 100644
index 0000000000..4a8908fc26
--- /dev/null
+++ b/modules/sale_extra/tests/test_sale_extra.py
@@ -0,0 +1,26 @@
+# This file is part of Tryton. The COPYRIGHT file at the top level of
+# this repository contains the full copyright notices and license terms.
+import unittest
+import doctest
+import trytond.tests.test_tryton
+from trytond.tests.test_tryton import ModuleTestCase
+from trytond.tests.test_tryton import doctest_teardown
+from trytond.tests.test_tryton import doctest_checker
+
+from trytond.modules.company.tests import CompanyTestMixin
+
+
+class SaleExtraTestCase(CompanyTestMixin, ModuleTestCase):
+ 'Test Sale Extra module'
+ module = 'sale_extra'
+
+
+def suite():
+ suite = trytond.tests.test_tryton.suite()
+ suite.addTests(unittest.TestLoader().loadTestsFromTestCase(
+ SaleExtraTestCase))
+ suite.addTests(doctest.DocFileSuite('scenario_sale_extra.rst',
+ tearDown=doctest_teardown, encoding='utf-8',
+ checker=doctest_checker,
+ optionflags=doctest.REPORT_ONLY_FIRST_FAILURE))
+ return suite
diff --git a/modules/sale_extra/tox.ini b/modules/sale_extra/tox.ini
new file mode 100644
index 0000000000..197496c0cb
--- /dev/null
+++ b/modules/sale_extra/tox.ini
@@ -0,0 +1,15 @@
+[tox]
+envlist = {py36,py37,py38,py39}-{sqlite,postgresql},pypy3-{sqlite,postgresql}
+
+[testenv]
+commands = {envpython} setup.py test
+deps =
+ {py36,py37,py38,py39}-postgresql: psycopg2 >= 2.5
+ pypy3-postgresql: psycopg2cffi >= 2.5
+ py36-sqlite: sqlitebck
+setenv =
+ sqlite: TRYTOND_DATABASE_URI={env:SQLITE_URI:sqlite://}
+ postgresql: TRYTOND_DATABASE_URI={env:POSTGRESQL_URI:postgresql://}
+ sqlite: DB_NAME={env:SQLITE_NAME::memory:}
+ postgresql: DB_NAME={env:POSTGRESQL_NAME:test}
+install_command = pip install --pre --find-links https://trydevpi.tryton.org/?local_version={env:CI_JOB_ID:{env:CI_BUILD_NUMBER}.{env:CI_JOB_NUMBER}} {opts} {packages}
diff --git a/modules/sale_extra/tryton.cfg b/modules/sale_extra/tryton.cfg
new file mode 100644
index 0000000000..28e8e0188a
--- /dev/null
+++ b/modules/sale_extra/tryton.cfg
@@ -0,0 +1,12 @@
+[tryton]
+version=6.0.1
+depends:
+ company
+ ir
+ product
+ product_price_list
+ res
+ sale
+ sale_price_list
+xml:
+ sale.xml
diff --git a/modules/sale_extra/view/extra_form.xml b/modules/sale_extra/view/extra_form.xml
new file mode 100644
index 0000000000..a3f034df67
--- /dev/null
+++ b/modules/sale_extra/view/extra_form.xml
@@ -0,0 +1,22 @@
+
+
+
diff --git a/modules/sale_extra/view/extra_line_form.xml b/modules/sale_extra/view/extra_line_form.xml
new file mode 100644
index 0000000000..56c0e00aec
--- /dev/null
+++ b/modules/sale_extra/view/extra_line_form.xml
@@ -0,0 +1,21 @@
+
+
+
diff --git a/modules/sale_extra/view/extra_line_list.xml b/modules/sale_extra/view/extra_line_list.xml
new file mode 100644
index 0000000000..d8f8b826cc
--- /dev/null
+++ b/modules/sale_extra/view/extra_line_list.xml
@@ -0,0 +1,11 @@
+
+
+
+
+
+
+
+
+
+
diff --git a/modules/sale_extra/view/extra_line_list_sequence.xml b/modules/sale_extra/view/extra_line_list_sequence.xml
new file mode 100644
index 0000000000..992318832d
--- /dev/null
+++ b/modules/sale_extra/view/extra_line_list_sequence.xml
@@ -0,0 +1,11 @@
+
+
+
+
+
+
+
+
+
+
diff --git a/modules/sale_extra/view/extra_list.xml b/modules/sale_extra/view/extra_list.xml
new file mode 100644
index 0000000000..49e2f63350
--- /dev/null
+++ b/modules/sale_extra/view/extra_list.xml
@@ -0,0 +1,11 @@
+
+
+
+
+
+
+
+
+
+
diff --git a/modules/sale_gift_card/.drone.yml b/modules/sale_gift_card/.drone.yml
new file mode 100644
index 0000000000..2049d30a49
--- /dev/null
+++ b/modules/sale_gift_card/.drone.yml
@@ -0,0 +1,68 @@
+clone:
+ hg:
+ image: plugins/hg
+ environment:
+ - HG_SHARE_POOL=/root/.cache/hg
+ volumes:
+ - cache:/root/.cache
+
+pipeline:
+ tox:
+ image: ${IMAGE}
+ environment:
+ - CFLAGS=-O0
+ - DB_CACHE=/cache
+ - TOX_TESTENV_PASSENV=CFLAGS DB_CACHE CI_BUILD_NUMBER CI_JOB_NUMBER CI_JOB_ID
+ - POSTGRESQL_URI=postgresql://postgres@postgresql:5432/
+ commands:
+ - echo "[extensions]" >> /root/.hgrc
+ - echo "hgext.share =" >> /root/.hgrc
+ - echo "[share]" >> /root/.hgrc
+ - echo "pool = /root/.cache/hg" >> /root/.hgrc
+ - pip install tox
+ - tox -e "${TOXENV}-${DATABASE}"
+ volumes:
+ - cache:/root/.cache
+ check_dist:
+ image: ${IMAGE}
+ commands:
+ - pip install twine
+ - python setup.py sdist
+ - twine check dist/*
+
+services:
+ postgresql:
+ image: postgres
+ environment:
+ - POSTGRES_HOST_AUTH_METHOD=trust
+ command: "-c fsync=off -c synchronous_commit=off -c full_page_writes=off"
+ when:
+ matrix:
+ DATABASE: postgresql
+
+matrix:
+ include:
+ - IMAGE: python:3.6
+ TOXENV: py36
+ DATABASE: sqlite
+ - IMAGE: python:3.6
+ TOXENV: py36
+ DATABASE: postgresql
+ - IMAGE: python:3.7
+ TOXENV: py37
+ DATABASE: sqlite
+ - IMAGE: python:3.7
+ TOXENV: py37
+ DATABASE: postgresql
+ - IMAGE: python:3.8
+ TOXENV: py38
+ DATABASE: sqlite
+ - IMAGE: python:3.8
+ TOXENV: py38
+ DATABASE: postgresql
+ - IMAGE: python:3.9
+ TOXENV: py39
+ DATABASE: sqlite
+ - IMAGE: python:3.9
+ TOXENV: py39
+ DATABASE: postgresql
diff --git a/modules/sale_gift_card/.flake8 b/modules/sale_gift_card/.flake8
new file mode 100644
index 0000000000..bb03d08a82
--- /dev/null
+++ b/modules/sale_gift_card/.flake8
@@ -0,0 +1,2 @@
+[flake8]
+ignore=E123,E124,E126,E128,W503
diff --git a/modules/sale_gift_card/CHANGELOG b/modules/sale_gift_card/CHANGELOG
new file mode 100644
index 0000000000..e2e4a2df47
--- /dev/null
+++ b/modules/sale_gift_card/CHANGELOG
@@ -0,0 +1,14 @@
+Version 6.0.4 - 2022-05-06
+* Bug fixes (see mercurial logs for details)
+
+Version 6.0.3 - 2021-08-19
+* Bug fixes (see mercurial logs for details)
+
+Version 6.0.2 - 2021-05-15
+* Bug fixes (see mercurial logs for details)
+
+Version 6.0.1 - 2021-05-10
+* Bug fixes (see mercurial logs for details)
+
+Version 6.0.0 - 2021-05-03
+* Initial release
diff --git a/modules/sale_gift_card/COPYRIGHT b/modules/sale_gift_card/COPYRIGHT
new file mode 100644
index 0000000000..d0b4a3655d
--- /dev/null
+++ b/modules/sale_gift_card/COPYRIGHT
@@ -0,0 +1,15 @@
+Copyright (C) 2020-2022 B2CK
+Copyright (C) 2020-2022 Cédric Krier
+
+This program is free software: you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation, either version 3 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program. If not, see .
diff --git a/modules/sale_gift_card/LICENSE b/modules/sale_gift_card/LICENSE
new file mode 100644
index 0000000000..94a9ed024d
--- /dev/null
+++ b/modules/sale_gift_card/LICENSE
@@ -0,0 +1,674 @@
+ GNU GENERAL PUBLIC LICENSE
+ Version 3, 29 June 2007
+
+ Copyright (C) 2007 Free Software Foundation, Inc.
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+ Preamble
+
+ The GNU General Public License is a free, copyleft license for
+software and other kinds of works.
+
+ The licenses for most software and other practical works are designed
+to take away your freedom to share and change the works. By contrast,
+the GNU General Public License is intended to guarantee your freedom to
+share and change all versions of a program--to make sure it remains free
+software for all its users. We, the Free Software Foundation, use the
+GNU General Public License for most of our software; it applies also to
+any other work released this way by its authors. You can apply it to
+your programs, too.
+
+ When we speak of free software, we are referring to freedom, not
+price. Our General Public Licenses are designed to make sure that you
+have the freedom to distribute copies of free software (and charge for
+them if you wish), that you receive source code or can get it if you
+want it, that you can change the software or use pieces of it in new
+free programs, and that you know you can do these things.
+
+ To protect your rights, we need to prevent others from denying you
+these rights or asking you to surrender the rights. Therefore, you have
+certain responsibilities if you distribute copies of the software, or if
+you modify it: responsibilities to respect the freedom of others.
+
+ For example, if you distribute copies of such a program, whether
+gratis or for a fee, you must pass on to the recipients the same
+freedoms that you received. You must make sure that they, too, receive
+or can get the source code. And you must show them these terms so they
+know their rights.
+
+ Developers that use the GNU GPL protect your rights with two steps:
+(1) assert copyright on the software, and (2) offer you this License
+giving you legal permission to copy, distribute and/or modify it.
+
+ For the developers' and authors' protection, the GPL clearly explains
+that there is no warranty for this free software. For both users' and
+authors' sake, the GPL requires that modified versions be marked as
+changed, so that their problems will not be attributed erroneously to
+authors of previous versions.
+
+ Some devices are designed to deny users access to install or run
+modified versions of the software inside them, although the manufacturer
+can do so. This is fundamentally incompatible with the aim of
+protecting users' freedom to change the software. The systematic
+pattern of such abuse occurs in the area of products for individuals to
+use, which is precisely where it is most unacceptable. Therefore, we
+have designed this version of the GPL to prohibit the practice for those
+products. If such problems arise substantially in other domains, we
+stand ready to extend this provision to those domains in future versions
+of the GPL, as needed to protect the freedom of users.
+
+ Finally, every program is threatened constantly by software patents.
+States should not allow patents to restrict development and use of
+software on general-purpose computers, but in those that do, we wish to
+avoid the special danger that patents applied to a free program could
+make it effectively proprietary. To prevent this, the GPL assures that
+patents cannot be used to render the program non-free.
+
+ The precise terms and conditions for copying, distribution and
+modification follow.
+
+ TERMS AND CONDITIONS
+
+ 0. Definitions.
+
+ "This License" refers to version 3 of the GNU General Public License.
+
+ "Copyright" also means copyright-like laws that apply to other kinds of
+works, such as semiconductor masks.
+
+ "The Program" refers to any copyrightable work licensed under this
+License. Each licensee is addressed as "you". "Licensees" and
+"recipients" may be individuals or organizations.
+
+ To "modify" a work means to copy from or adapt all or part of the work
+in a fashion requiring copyright permission, other than the making of an
+exact copy. The resulting work is called a "modified version" of the
+earlier work or a work "based on" the earlier work.
+
+ A "covered work" means either the unmodified Program or a work based
+on the Program.
+
+ To "propagate" a work means to do anything with it that, without
+permission, would make you directly or secondarily liable for
+infringement under applicable copyright law, except executing it on a
+computer or modifying a private copy. Propagation includes copying,
+distribution (with or without modification), making available to the
+public, and in some countries other activities as well.
+
+ To "convey" a work means any kind of propagation that enables other
+parties to make or receive copies. Mere interaction with a user through
+a computer network, with no transfer of a copy, is not conveying.
+
+ An interactive user interface displays "Appropriate Legal Notices"
+to the extent that it includes a convenient and prominently visible
+feature that (1) displays an appropriate copyright notice, and (2)
+tells the user that there is no warranty for the work (except to the
+extent that warranties are provided), that licensees may convey the
+work under this License, and how to view a copy of this License. If
+the interface presents a list of user commands or options, such as a
+menu, a prominent item in the list meets this criterion.
+
+ 1. Source Code.
+
+ The "source code" for a work means the preferred form of the work
+for making modifications to it. "Object code" means any non-source
+form of a work.
+
+ A "Standard Interface" means an interface that either is an official
+standard defined by a recognized standards body, or, in the case of
+interfaces specified for a particular programming language, one that
+is widely used among developers working in that language.
+
+ The "System Libraries" of an executable work include anything, other
+than the work as a whole, that (a) is included in the normal form of
+packaging a Major Component, but which is not part of that Major
+Component, and (b) serves only to enable use of the work with that
+Major Component, or to implement a Standard Interface for which an
+implementation is available to the public in source code form. A
+"Major Component", in this context, means a major essential component
+(kernel, window system, and so on) of the specific operating system
+(if any) on which the executable work runs, or a compiler used to
+produce the work, or an object code interpreter used to run it.
+
+ The "Corresponding Source" for a work in object code form means all
+the source code needed to generate, install, and (for an executable
+work) run the object code and to modify the work, including scripts to
+control those activities. However, it does not include the work's
+System Libraries, or general-purpose tools or generally available free
+programs which are used unmodified in performing those activities but
+which are not part of the work. For example, Corresponding Source
+includes interface definition files associated with source files for
+the work, and the source code for shared libraries and dynamically
+linked subprograms that the work is specifically designed to require,
+such as by intimate data communication or control flow between those
+subprograms and other parts of the work.
+
+ The Corresponding Source need not include anything that users
+can regenerate automatically from other parts of the Corresponding
+Source.
+
+ The Corresponding Source for a work in source code form is that
+same work.
+
+ 2. Basic Permissions.
+
+ All rights granted under this License are granted for the term of
+copyright on the Program, and are irrevocable provided the stated
+conditions are met. This License explicitly affirms your unlimited
+permission to run the unmodified Program. The output from running a
+covered work is covered by this License only if the output, given its
+content, constitutes a covered work. This License acknowledges your
+rights of fair use or other equivalent, as provided by copyright law.
+
+ You may make, run and propagate covered works that you do not
+convey, without conditions so long as your license otherwise remains
+in force. You may convey covered works to others for the sole purpose
+of having them make modifications exclusively for you, or provide you
+with facilities for running those works, provided that you comply with
+the terms of this License in conveying all material for which you do
+not control copyright. Those thus making or running the covered works
+for you must do so exclusively on your behalf, under your direction
+and control, on terms that prohibit them from making any copies of
+your copyrighted material outside their relationship with you.
+
+ Conveying under any other circumstances is permitted solely under
+the conditions stated below. Sublicensing is not allowed; section 10
+makes it unnecessary.
+
+ 3. Protecting Users' Legal Rights From Anti-Circumvention Law.
+
+ No covered work shall be deemed part of an effective technological
+measure under any applicable law fulfilling obligations under article
+11 of the WIPO copyright treaty adopted on 20 December 1996, or
+similar laws prohibiting or restricting circumvention of such
+measures.
+
+ When you convey a covered work, you waive any legal power to forbid
+circumvention of technological measures to the extent such circumvention
+is effected by exercising rights under this License with respect to
+the covered work, and you disclaim any intention to limit operation or
+modification of the work as a means of enforcing, against the work's
+users, your or third parties' legal rights to forbid circumvention of
+technological measures.
+
+ 4. Conveying Verbatim Copies.
+
+ You may convey verbatim copies of the Program's source code as you
+receive it, in any medium, provided that you conspicuously and
+appropriately publish on each copy an appropriate copyright notice;
+keep intact all notices stating that this License and any
+non-permissive terms added in accord with section 7 apply to the code;
+keep intact all notices of the absence of any warranty; and give all
+recipients a copy of this License along with the Program.
+
+ You may charge any price or no price for each copy that you convey,
+and you may offer support or warranty protection for a fee.
+
+ 5. Conveying Modified Source Versions.
+
+ You may convey a work based on the Program, or the modifications to
+produce it from the Program, in the form of source code under the
+terms of section 4, provided that you also meet all of these conditions:
+
+ a) The work must carry prominent notices stating that you modified
+ it, and giving a relevant date.
+
+ b) The work must carry prominent notices stating that it is
+ released under this License and any conditions added under section
+ 7. This requirement modifies the requirement in section 4 to
+ "keep intact all notices".
+
+ c) You must license the entire work, as a whole, under this
+ License to anyone who comes into possession of a copy. This
+ License will therefore apply, along with any applicable section 7
+ additional terms, to the whole of the work, and all its parts,
+ regardless of how they are packaged. This License gives no
+ permission to license the work in any other way, but it does not
+ invalidate such permission if you have separately received it.
+
+ d) If the work has interactive user interfaces, each must display
+ Appropriate Legal Notices; however, if the Program has interactive
+ interfaces that do not display Appropriate Legal Notices, your
+ work need not make them do so.
+
+ A compilation of a covered work with other separate and independent
+works, which are not by their nature extensions of the covered work,
+and which are not combined with it such as to form a larger program,
+in or on a volume of a storage or distribution medium, is called an
+"aggregate" if the compilation and its resulting copyright are not
+used to limit the access or legal rights of the compilation's users
+beyond what the individual works permit. Inclusion of a covered work
+in an aggregate does not cause this License to apply to the other
+parts of the aggregate.
+
+ 6. Conveying Non-Source Forms.
+
+ You may convey a covered work in object code form under the terms
+of sections 4 and 5, provided that you also convey the
+machine-readable Corresponding Source under the terms of this License,
+in one of these ways:
+
+ a) Convey the object code in, or embodied in, a physical product
+ (including a physical distribution medium), accompanied by the
+ Corresponding Source fixed on a durable physical medium
+ customarily used for software interchange.
+
+ b) Convey the object code in, or embodied in, a physical product
+ (including a physical distribution medium), accompanied by a
+ written offer, valid for at least three years and valid for as
+ long as you offer spare parts or customer support for that product
+ model, to give anyone who possesses the object code either (1) a
+ copy of the Corresponding Source for all the software in the
+ product that is covered by this License, on a durable physical
+ medium customarily used for software interchange, for a price no
+ more than your reasonable cost of physically performing this
+ conveying of source, or (2) access to copy the
+ Corresponding Source from a network server at no charge.
+
+ c) Convey individual copies of the object code with a copy of the
+ written offer to provide the Corresponding Source. This
+ alternative is allowed only occasionally and noncommercially, and
+ only if you received the object code with such an offer, in accord
+ with subsection 6b.
+
+ d) Convey the object code by offering access from a designated
+ place (gratis or for a charge), and offer equivalent access to the
+ Corresponding Source in the same way through the same place at no
+ further charge. You need not require recipients to copy the
+ Corresponding Source along with the object code. If the place to
+ copy the object code is a network server, the Corresponding Source
+ may be on a different server (operated by you or a third party)
+ that supports equivalent copying facilities, provided you maintain
+ clear directions next to the object code saying where to find the
+ Corresponding Source. Regardless of what server hosts the
+ Corresponding Source, you remain obligated to ensure that it is
+ available for as long as needed to satisfy these requirements.
+
+ e) Convey the object code using peer-to-peer transmission, provided
+ you inform other peers where the object code and Corresponding
+ Source of the work are being offered to the general public at no
+ charge under subsection 6d.
+
+ A separable portion of the object code, whose source code is excluded
+from the Corresponding Source as a System Library, need not be
+included in conveying the object code work.
+
+ A "User Product" is either (1) a "consumer product", which means any
+tangible personal property which is normally used for personal, family,
+or household purposes, or (2) anything designed or sold for incorporation
+into a dwelling. In determining whether a product is a consumer product,
+doubtful cases shall be resolved in favor of coverage. For a particular
+product received by a particular user, "normally used" refers to a
+typical or common use of that class of product, regardless of the status
+of the particular user or of the way in which the particular user
+actually uses, or expects or is expected to use, the product. A product
+is a consumer product regardless of whether the product has substantial
+commercial, industrial or non-consumer uses, unless such uses represent
+the only significant mode of use of the product.
+
+ "Installation Information" for a User Product means any methods,
+procedures, authorization keys, or other information required to install
+and execute modified versions of a covered work in that User Product from
+a modified version of its Corresponding Source. The information must
+suffice to ensure that the continued functioning of the modified object
+code is in no case prevented or interfered with solely because
+modification has been made.
+
+ If you convey an object code work under this section in, or with, or
+specifically for use in, a User Product, and the conveying occurs as
+part of a transaction in which the right of possession and use of the
+User Product is transferred to the recipient in perpetuity or for a
+fixed term (regardless of how the transaction is characterized), the
+Corresponding Source conveyed under this section must be accompanied
+by the Installation Information. But this requirement does not apply
+if neither you nor any third party retains the ability to install
+modified object code on the User Product (for example, the work has
+been installed in ROM).
+
+ The requirement to provide Installation Information does not include a
+requirement to continue to provide support service, warranty, or updates
+for a work that has been modified or installed by the recipient, or for
+the User Product in which it has been modified or installed. Access to a
+network may be denied when the modification itself materially and
+adversely affects the operation of the network or violates the rules and
+protocols for communication across the network.
+
+ Corresponding Source conveyed, and Installation Information provided,
+in accord with this section must be in a format that is publicly
+documented (and with an implementation available to the public in
+source code form), and must require no special password or key for
+unpacking, reading or copying.
+
+ 7. Additional Terms.
+
+ "Additional permissions" are terms that supplement the terms of this
+License by making exceptions from one or more of its conditions.
+Additional permissions that are applicable to the entire Program shall
+be treated as though they were included in this License, to the extent
+that they are valid under applicable law. If additional permissions
+apply only to part of the Program, that part may be used separately
+under those permissions, but the entire Program remains governed by
+this License without regard to the additional permissions.
+
+ When you convey a copy of a covered work, you may at your option
+remove any additional permissions from that copy, or from any part of
+it. (Additional permissions may be written to require their own
+removal in certain cases when you modify the work.) You may place
+additional permissions on material, added by you to a covered work,
+for which you have or can give appropriate copyright permission.
+
+ Notwithstanding any other provision of this License, for material you
+add to a covered work, you may (if authorized by the copyright holders of
+that material) supplement the terms of this License with terms:
+
+ a) Disclaiming warranty or limiting liability differently from the
+ terms of sections 15 and 16 of this License; or
+
+ b) Requiring preservation of specified reasonable legal notices or
+ author attributions in that material or in the Appropriate Legal
+ Notices displayed by works containing it; or
+
+ c) Prohibiting misrepresentation of the origin of that material, or
+ requiring that modified versions of such material be marked in
+ reasonable ways as different from the original version; or
+
+ d) Limiting the use for publicity purposes of names of licensors or
+ authors of the material; or
+
+ e) Declining to grant rights under trademark law for use of some
+ trade names, trademarks, or service marks; or
+
+ f) Requiring indemnification of licensors and authors of that
+ material by anyone who conveys the material (or modified versions of
+ it) with contractual assumptions of liability to the recipient, for
+ any liability that these contractual assumptions directly impose on
+ those licensors and authors.
+
+ All other non-permissive additional terms are considered "further
+restrictions" within the meaning of section 10. If the Program as you
+received it, or any part of it, contains a notice stating that it is
+governed by this License along with a term that is a further
+restriction, you may remove that term. If a license document contains
+a further restriction but permits relicensing or conveying under this
+License, you may add to a covered work material governed by the terms
+of that license document, provided that the further restriction does
+not survive such relicensing or conveying.
+
+ If you add terms to a covered work in accord with this section, you
+must place, in the relevant source files, a statement of the
+additional terms that apply to those files, or a notice indicating
+where to find the applicable terms.
+
+ Additional terms, permissive or non-permissive, may be stated in the
+form of a separately written license, or stated as exceptions;
+the above requirements apply either way.
+
+ 8. Termination.
+
+ You may not propagate or modify a covered work except as expressly
+provided under this License. Any attempt otherwise to propagate or
+modify it is void, and will automatically terminate your rights under
+this License (including any patent licenses granted under the third
+paragraph of section 11).
+
+ However, if you cease all violation of this License, then your
+license from a particular copyright holder is reinstated (a)
+provisionally, unless and until the copyright holder explicitly and
+finally terminates your license, and (b) permanently, if the copyright
+holder fails to notify you of the violation by some reasonable means
+prior to 60 days after the cessation.
+
+ Moreover, your license from a particular copyright holder is
+reinstated permanently if the copyright holder notifies you of the
+violation by some reasonable means, this is the first time you have
+received notice of violation of this License (for any work) from that
+copyright holder, and you cure the violation prior to 30 days after
+your receipt of the notice.
+
+ Termination of your rights under this section does not terminate the
+licenses of parties who have received copies or rights from you under
+this License. If your rights have been terminated and not permanently
+reinstated, you do not qualify to receive new licenses for the same
+material under section 10.
+
+ 9. Acceptance Not Required for Having Copies.
+
+ You are not required to accept this License in order to receive or
+run a copy of the Program. Ancillary propagation of a covered work
+occurring solely as a consequence of using peer-to-peer transmission
+to receive a copy likewise does not require acceptance. However,
+nothing other than this License grants you permission to propagate or
+modify any covered work. These actions infringe copyright if you do
+not accept this License. Therefore, by modifying or propagating a
+covered work, you indicate your acceptance of this License to do so.
+
+ 10. Automatic Licensing of Downstream Recipients.
+
+ Each time you convey a covered work, the recipient automatically
+receives a license from the original licensors, to run, modify and
+propagate that work, subject to this License. You are not responsible
+for enforcing compliance by third parties with this License.
+
+ An "entity transaction" is a transaction transferring control of an
+organization, or substantially all assets of one, or subdividing an
+organization, or merging organizations. If propagation of a covered
+work results from an entity transaction, each party to that
+transaction who receives a copy of the work also receives whatever
+licenses to the work the party's predecessor in interest had or could
+give under the previous paragraph, plus a right to possession of the
+Corresponding Source of the work from the predecessor in interest, if
+the predecessor has it or can get it with reasonable efforts.
+
+ You may not impose any further restrictions on the exercise of the
+rights granted or affirmed under this License. For example, you may
+not impose a license fee, royalty, or other charge for exercise of
+rights granted under this License, and you may not initiate litigation
+(including a cross-claim or counterclaim in a lawsuit) alleging that
+any patent claim is infringed by making, using, selling, offering for
+sale, or importing the Program or any portion of it.
+
+ 11. Patents.
+
+ A "contributor" is a copyright holder who authorizes use under this
+License of the Program or a work on which the Program is based. The
+work thus licensed is called the contributor's "contributor version".
+
+ A contributor's "essential patent claims" are all patent claims
+owned or controlled by the contributor, whether already acquired or
+hereafter acquired, that would be infringed by some manner, permitted
+by this License, of making, using, or selling its contributor version,
+but do not include claims that would be infringed only as a
+consequence of further modification of the contributor version. For
+purposes of this definition, "control" includes the right to grant
+patent sublicenses in a manner consistent with the requirements of
+this License.
+
+ Each contributor grants you a non-exclusive, worldwide, royalty-free
+patent license under the contributor's essential patent claims, to
+make, use, sell, offer for sale, import and otherwise run, modify and
+propagate the contents of its contributor version.
+
+ In the following three paragraphs, a "patent license" is any express
+agreement or commitment, however denominated, not to enforce a patent
+(such as an express permission to practice a patent or covenant not to
+sue for patent infringement). To "grant" such a patent license to a
+party means to make such an agreement or commitment not to enforce a
+patent against the party.
+
+ If you convey a covered work, knowingly relying on a patent license,
+and the Corresponding Source of the work is not available for anyone
+to copy, free of charge and under the terms of this License, through a
+publicly available network server or other readily accessible means,
+then you must either (1) cause the Corresponding Source to be so
+available, or (2) arrange to deprive yourself of the benefit of the
+patent license for this particular work, or (3) arrange, in a manner
+consistent with the requirements of this License, to extend the patent
+license to downstream recipients. "Knowingly relying" means you have
+actual knowledge that, but for the patent license, your conveying the
+covered work in a country, or your recipient's use of the covered work
+in a country, would infringe one or more identifiable patents in that
+country that you have reason to believe are valid.
+
+ If, pursuant to or in connection with a single transaction or
+arrangement, you convey, or propagate by procuring conveyance of, a
+covered work, and grant a patent license to some of the parties
+receiving the covered work authorizing them to use, propagate, modify
+or convey a specific copy of the covered work, then the patent license
+you grant is automatically extended to all recipients of the covered
+work and works based on it.
+
+ A patent license is "discriminatory" if it does not include within
+the scope of its coverage, prohibits the exercise of, or is
+conditioned on the non-exercise of one or more of the rights that are
+specifically granted under this License. You may not convey a covered
+work if you are a party to an arrangement with a third party that is
+in the business of distributing software, under which you make payment
+to the third party based on the extent of your activity of conveying
+the work, and under which the third party grants, to any of the
+parties who would receive the covered work from you, a discriminatory
+patent license (a) in connection with copies of the covered work
+conveyed by you (or copies made from those copies), or (b) primarily
+for and in connection with specific products or compilations that
+contain the covered work, unless you entered into that arrangement,
+or that patent license was granted, prior to 28 March 2007.
+
+ Nothing in this License shall be construed as excluding or limiting
+any implied license or other defenses to infringement that may
+otherwise be available to you under applicable patent law.
+
+ 12. No Surrender of Others' Freedom.
+
+ If conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License. If you cannot convey a
+covered work so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you may
+not convey it at all. For example, if you agree to terms that obligate you
+to collect a royalty for further conveying from those to whom you convey
+the Program, the only way you could satisfy both those terms and this
+License would be to refrain entirely from conveying the Program.
+
+ 13. Use with the GNU Affero General Public License.
+
+ Notwithstanding any other provision of this License, you have
+permission to link or combine any covered work with a work licensed
+under version 3 of the GNU Affero General Public License into a single
+combined work, and to convey the resulting work. The terms of this
+License will continue to apply to the part which is the covered work,
+but the special requirements of the GNU Affero General Public License,
+section 13, concerning interaction through a network will apply to the
+combination as such.
+
+ 14. Revised Versions of this License.
+
+ The Free Software Foundation may publish revised and/or new versions of
+the GNU General Public License from time to time. Such new versions will
+be similar in spirit to the present version, but may differ in detail to
+address new problems or concerns.
+
+ Each version is given a distinguishing version number. If the
+Program specifies that a certain numbered version of the GNU General
+Public License "or any later version" applies to it, you have the
+option of following the terms and conditions either of that numbered
+version or of any later version published by the Free Software
+Foundation. If the Program does not specify a version number of the
+GNU General Public License, you may choose any version ever published
+by the Free Software Foundation.
+
+ If the Program specifies that a proxy can decide which future
+versions of the GNU General Public License can be used, that proxy's
+public statement of acceptance of a version permanently authorizes you
+to choose that version for the Program.
+
+ Later license versions may give you additional or different
+permissions. However, no additional obligations are imposed on any
+author or copyright holder as a result of your choosing to follow a
+later version.
+
+ 15. Disclaimer of Warranty.
+
+ THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY
+APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT
+HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY
+OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO,
+THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM
+IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF
+ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
+
+ 16. Limitation of Liability.
+
+ IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS
+THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY
+GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE
+USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF
+DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD
+PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS),
+EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF
+SUCH DAMAGES.
+
+ 17. Interpretation of Sections 15 and 16.
+
+ If the disclaimer of warranty and limitation of liability provided
+above cannot be given local legal effect according to their terms,
+reviewing courts shall apply local law that most closely approximates
+an absolute waiver of all civil liability in connection with the
+Program, unless a warranty or assumption of liability accompanies a
+copy of the Program in return for a fee.
+
+ END OF TERMS AND CONDITIONS
+
+ How to Apply These Terms to Your New Programs
+
+ If you develop a new program, and you want it to be of the greatest
+possible use to the public, the best way to achieve this is to make it
+free software which everyone can redistribute and change under these terms.
+
+ To do so, attach the following notices to the program. It is safest
+to attach them to the start of each source file to most effectively
+state the exclusion of warranty; and each file should have at least
+the "copyright" line and a pointer to where the full notice is found.
+
+
+ Copyright (C)
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see .
+
+Also add information on how to contact you by electronic and paper mail.
+
+ If the program does terminal interaction, make it output a short
+notice like this when it starts in an interactive mode:
+
+ Copyright (C)
+ This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
+ This is free software, and you are welcome to redistribute it
+ under certain conditions; type `show c' for details.
+
+The hypothetical commands `show w' and `show c' should show the appropriate
+parts of the General Public License. Of course, your program's commands
+might be different; for a GUI interface, you would use an "about box".
+
+ You should also get your employer (if you work as a programmer) or school,
+if any, to sign a "copyright disclaimer" for the program, if necessary.
+For more information on this, and how to apply and follow the GNU GPL, see
+.
+
+ The GNU General Public License does not permit incorporating your program
+into proprietary programs. If your program is a subroutine library, you
+may consider it more useful to permit linking proprietary applications with
+the library. If this is what you want to do, use the GNU Lesser General
+Public License instead of this License. But first, please read
+.
diff --git a/modules/sale_gift_card/MANIFEST.in b/modules/sale_gift_card/MANIFEST.in
new file mode 100644
index 0000000000..e88b2348a3
--- /dev/null
+++ b/modules/sale_gift_card/MANIFEST.in
@@ -0,0 +1,5 @@
+include CHANGELOG
+include COPYRIGHT
+include LICENSE
+include README.rst
+include doc/*
diff --git a/modules/sale_gift_card/README.rst b/modules/sale_gift_card/README.rst
new file mode 120000
index 0000000000..176d9c2695
--- /dev/null
+++ b/modules/sale_gift_card/README.rst
@@ -0,0 +1 @@
+doc/index.rst
\ No newline at end of file
diff --git a/modules/sale_gift_card/__init__.py b/modules/sale_gift_card/__init__.py
new file mode 100644
index 0000000000..c54128df0f
--- /dev/null
+++ b/modules/sale_gift_card/__init__.py
@@ -0,0 +1,33 @@
+# This file is part of Tryton. The COPYRIGHT file at the top level of
+# this repository contains the full copyright notices and license terms.
+
+from trytond.pool import Pool
+from . import account
+from . import product
+from . import sale
+from . import stock
+
+__all__ = ['register']
+
+
+def register():
+ Pool.register(
+ account.Configuration,
+ account.ConfigurationGiftCardAccount,
+ account.AccountTypeTemplate,
+ account.AccountType,
+ account.InvoiceLine,
+ product.Template,
+ product.Product,
+ sale.Configuration,
+ sale.ConfigurationGiftCardSequence,
+ sale.GiftCard,
+ sale.Sale,
+ sale.Line,
+ stock.Move,
+ module='sale_gift_card', type_='model')
+ Pool.register(
+ module='sale_gift_card', type_='wizard')
+ Pool.register(
+ sale.GiftCardEmail,
+ module='sale_gift_card', type_='report')
diff --git a/modules/sale_gift_card/account.py b/modules/sale_gift_card/account.py
new file mode 100644
index 0000000000..403e5cb70f
--- /dev/null
+++ b/modules/sale_gift_card/account.py
@@ -0,0 +1,102 @@
+# This file is part of Tryton. The COPYRIGHT file at the top level of
+# this repository contains the full copyright notices and license terms.
+from trytond.model import ModelSQL, fields
+from trytond.pool import PoolMeta, Pool
+from trytond.pyson import Eval, Bool, If
+
+from trytond.modules.company.model import CompanyValueMixin
+
+
+class Configuration(metaclass=PoolMeta):
+ __name__ = 'account.configuration'
+
+ gift_card_account_expense = fields.MultiValue(fields.Many2One(
+ 'account.account', "Gift Card Expense",
+ domain=[
+ ('type.gift_card', '=', True),
+ ('closed', '!=', True),
+ ('company', '=', Eval('context', {}).get('company', -1)),
+ ]))
+ gift_card_account_revenue = fields.MultiValue(fields.Many2One(
+ 'account.account', "Gift Card Revenue",
+ domain=[
+ ('type.gift_card', '=', True),
+ ('closed', '!=', True),
+ ('company', '=', Eval('context', {}).get('company', -1)),
+ ]))
+
+ @classmethod
+ def multivalue_model(cls, field):
+ pool = Pool()
+ if field in {'gift_card_account_expense', 'gift_card_account_revenue'}:
+ return pool.get('account.configuration.gift_card_account')
+ return super().multivalue_model(field)
+
+
+class ConfigurationGiftCardAccount(ModelSQL, CompanyValueMixin):
+ "Account Configuration Gift Card Account"
+ __name__ = 'account.configuration.gift_card_account'
+
+ gift_card_account_expense = fields.Many2One(
+ 'account.account', "Gift Card Expense",
+ domain=[
+ ('type.gift_card', '=', True),
+ ('closed', '!=', True),
+ ('company', '=', Eval('company', -1)),
+ ],
+ depends=['company'])
+ gift_card_account_revenue = fields.Many2One(
+ 'account.account', "Gift Card Revenue",
+ domain=[
+ ('type.gift_card', '=', True),
+ ('closed', '!=', True),
+ ('company', '=', Eval('company', -1)),
+ ],
+ depends=['company'])
+
+
+def AccountTypeMixin(template=False):
+
+ class Mixin:
+ __slots__ = ()
+ gift_card = fields.Boolean(
+ "Gift Card",
+ domain=[
+ If(Eval('statement') != 'balance',
+ ('gift_card', '=', False), ()),
+ ],
+ states={
+ 'invisible': Eval('statement') != 'balance',
+ },
+ depends=['statement'])
+ if not template:
+ for fname in dir(Mixin):
+ field = getattr(Mixin, fname)
+ if not isinstance(field, fields.Field):
+ continue
+ field.states['readonly'] = (
+ Bool(Eval('template', -1)) & ~Eval('template_override', False))
+ return Mixin
+
+
+class AccountTypeTemplate(AccountTypeMixin(template=True), metaclass=PoolMeta):
+ __name__ = 'account.account.type.template'
+
+ def _get_type_value(self, type=None):
+ values = super()._get_type_value(type=type)
+ if not type or type.gift_card != self.gift_card:
+ values['gift_card'] = self.gift_card
+ return values
+
+
+class AccountType(AccountTypeMixin(), metaclass=PoolMeta):
+ __name__ = 'account.account.type'
+
+
+class InvoiceLine(metaclass=PoolMeta):
+ __name__ = 'account.invoice.line'
+
+ @classmethod
+ def _account_domain(cls, type_):
+ domain = super(InvoiceLine, cls)._account_domain(type_)
+ return domain + [('type.gift_card', '=', True)]
diff --git a/modules/sale_gift_card/account.xml b/modules/sale_gift_card/account.xml
new file mode 100644
index 0000000000..8579d59b94
--- /dev/null
+++ b/modules/sale_gift_card/account.xml
@@ -0,0 +1,24 @@
+
+
+
+
+
+ account.configuration
+
+ account_configuration_form
+
+
+
+ account.account.type.template
+
+ account_type_form
+
+
+
+ account.account.type
+
+ account_type_form
+
+
+
diff --git a/modules/sale_gift_card/doc/conf.py b/modules/sale_gift_card/doc/conf.py
new file mode 100644
index 0000000000..8513b72dd2
--- /dev/null
+++ b/modules/sale_gift_card/doc/conf.py
@@ -0,0 +1,61 @@
+# This file is part of Tryton. The COPYRIGHT file at the top level of
+# this repository contains the full copyright notices and license terms.
+
+modules_url = 'https://docs.tryton.org/projects/modules-{module}/en/{series}/'
+trytond_url = 'https://docs.tryton.org/projects/server/en/{series}/'
+
+
+def get_info():
+ import configparser
+ import os
+ import subprocess
+ import sys
+
+ module_dir = os.path.dirname(os.path.dirname(__file__))
+
+ config = configparser.ConfigParser()
+ config.read_file(open(os.path.join(module_dir, 'tryton.cfg')))
+ info = dict(config.items('tryton'))
+
+ result = subprocess.run(
+ [sys.executable, 'setup.py', '--name'],
+ stdout=subprocess.PIPE, check=True, cwd=module_dir)
+ info['name'] = result.stdout.decode('utf-8').strip()
+
+ result = subprocess.run(
+ [sys.executable, 'setup.py', '--version'],
+ stdout=subprocess.PIPE, check=True, cwd=module_dir)
+ version = result.stdout.decode('utf-8').strip()
+ if 'dev' in version:
+ info['series'] = 'latest'
+ else:
+ info['series'] = '.'.join(version.split('.', 2)[:2])
+
+ for key in {'depends', 'extras_depend'}:
+ info[key] = info.get(key, '').strip().splitlines()
+ info['modules'] = set(info['depends'] + info['extras_depend'])
+ info['modules'] -= {'ir', 'res'}
+
+ return info
+
+
+info = get_info()
+
+master_doc = 'index'
+project = info['name']
+release = version = info['series']
+default_role = 'ref'
+highlight_language = 'none'
+extensions = [
+ 'sphinx.ext.intersphinx',
+ ]
+intersphinx_mapping = {
+ 'trytond': (trytond_url.format(series=version), None),
+ }
+intersphinx_mapping.update({
+ m: (modules_url.format(
+ module=m.replace('_', '-'), series=version), None)
+ for m in info['modules']
+ })
+
+del get_info, info, modules_url, trytond_url
diff --git a/modules/sale_gift_card/doc/design.rst b/modules/sale_gift_card/doc/design.rst
new file mode 100644
index 0000000000..697695c27d
--- /dev/null
+++ b/modules/sale_gift_card/doc/design.rst
@@ -0,0 +1,67 @@
+******
+Design
+******
+
+The *Sale Gift Card Module* introduces or extends the following concepts.
+
+.. _concept-product:
+
+Product
+=======
+
+When the *Sale Gift Card Module* is activated, services and goods can be
+defined as gift cards.
+
+.. seealso::
+
+ The `Product ` concept is introduced by the
+ :doc:`Product Module `.
+
+.. _model-sale.gift_card:
+
+Gift Card
+=========
+
+The *Gift Card* concept stores the unique number and value for each gift card.
+
+.. seealso::
+
+ Gift cards can be seen by opening the main menu item:
+
+ |Sales --> Gift Cards|__
+
+ .. |Sales --> Gift Cards| replace:: :menuselection:`Sales --> Gift Cards`
+ __ https://demo.tryton.org/model/sale.gift_card
+
+.. _model-sale.sale:
+
+Sale
+====
+
+The *Sale* concept is extended to allow `Gift Cards `
+presented by customers to be redeemed.
+On quotation these gift cards are deducted from the total.
+
+For *Sale Lines* that are for gift cards represented by service products an
+optional email address can be provided.
+This email address is then used to send the gift card to the customer by email.
+
+.. seealso::
+
+ The `Sale ` concept is introduced by the :doc:`Sale
+ Module `.
+
+
+.. _model-stock.move:
+
+Stock Move
+==========
+
+The *Stock Move* concept is extended to record the `Gift Cards
+` shipped to customers.
+
+
+.. seealso::
+
+ The `Move ` concept is introduced by the :doc:`Stock
+ Module `.
diff --git a/modules/sale_gift_card/doc/index.rst b/modules/sale_gift_card/doc/index.rst
new file mode 100644
index 0000000000..a7610bd6cb
--- /dev/null
+++ b/modules/sale_gift_card/doc/index.rst
@@ -0,0 +1,11 @@
+#####################
+Sale Gift Card Module
+#####################
+
+The *Sale Gift Card Module* manages the selling and redeeming of gift cards.
+
+.. toctree::
+ :maxdepth: 2
+
+ design
+ usage
diff --git a/modules/sale_gift_card/doc/usage.rst b/modules/sale_gift_card/doc/usage.rst
new file mode 100644
index 0000000000..5dcf4cbaf2
--- /dev/null
+++ b/modules/sale_gift_card/doc/usage.rst
@@ -0,0 +1,32 @@
+*****
+Usage
+*****
+
+.. _Selling gift cards:
+
+Selling gift cards
+==================
+
+A gift card `Product ` can sold on a `Sale
+`.
+When it is a service, the `Gift Card ` are created and
+sent automatically by email to the email address from the sale line or, if this
+has not been filled in, to the customer's email address.
+When the *Product* is goods, the *Gift Cards* must be linked to the outgoing
+`Stock Moves ` that send the gift card to the customer.
+
+.. _Redeeming gift card:
+
+Redeeming gift card
+===================
+
+Existing `Gift Cards ` can be added once to a `Sale
+`.
+On quotation, a return line for the amount of each gift card is created.
+
+.. note::
+
+ If the value of the redeemed gift cards exceeds the value of the sale then
+ the sales total will be negative.
+ This will normally result in a credit note being generated by the sale
+ instead of an `Invoice `.
diff --git a/modules/sale_gift_card/email.html b/modules/sale_gift_card/email.html
new file mode 100644
index 0000000000..40906ce78b
--- /dev/null
+++ b/modules/sale_gift_card/email.html
@@ -0,0 +1,20 @@
+
+
+
+ Gift Card
+
+
+
+
+
You received a gift card of ${format_currency(gift_card.value, None, gift_card.currency)} for ${gift_card.company.rec_name}.
+
Here is your code:
+
+ ${gift_card.number}
+
+
+
+
+
diff --git a/modules/sale_gift_card/exceptions.py b/modules/sale_gift_card/exceptions.py
new file mode 100644
index 0000000000..7f094879d9
--- /dev/null
+++ b/modules/sale_gift_card/exceptions.py
@@ -0,0 +1,15 @@
+# This file is part of Tryton. The COPYRIGHT file at the top level of
+# this repository contains the full copyright notices and license terms.
+
+from trytond.model.exceptions import (
+ RequiredValidationError, SizeValidationError)
+from trytond.modules.product.exceptions import TemplateValidationError
+
+
+class GiftCardValidationError(TemplateValidationError):
+ pass
+
+
+class MoveGiftCardValidationError(
+ RequiredValidationError, SizeValidationError):
+ pass
diff --git a/modules/sale_gift_card/locale/bg.po b/modules/sale_gift_card/locale/bg.po
new file mode 100644
index 0000000000..bd14ca036a
--- /dev/null
+++ b/modules/sale_gift_card/locale/bg.po
@@ -0,0 +1,204 @@
+#
+msgid ""
+msgstr "Content-Type: text/plain; charset=utf-8\n"
+
+msgctxt "field:account.account.type,gift_card:"
+msgid "Gift Card"
+msgstr ""
+
+msgctxt "field:account.account.type.template,gift_card:"
+msgid "Gift Card"
+msgstr ""
+
+msgctxt "field:account.configuration,gift_card_account_expense:"
+msgid "Gift Card Expense"
+msgstr ""
+
+msgctxt "field:account.configuration,gift_card_account_revenue:"
+msgid "Gift Card Revenue"
+msgstr ""
+
+msgctxt "field:account.configuration.gift_card_account,company:"
+msgid "Company"
+msgstr ""
+
+msgctxt ""
+"field:account.configuration.gift_card_account,gift_card_account_expense:"
+msgid "Gift Card Expense"
+msgstr ""
+
+msgctxt ""
+"field:account.configuration.gift_card_account,gift_card_account_revenue:"
+msgid "Gift Card Revenue"
+msgstr ""
+
+msgctxt "field:product.product,gift_card:"
+msgid "Gift Card"
+msgstr ""
+
+msgctxt "field:product.template,gift_card:"
+msgid "Gift Card"
+msgstr ""
+
+msgctxt "field:sale.configuration,gift_card_sequence:"
+msgid "Gift Card Sequence"
+msgstr ""
+
+msgctxt "field:sale.configuration.gift_card.sequence,company:"
+msgid "Company"
+msgstr ""
+
+msgctxt "field:sale.configuration.gift_card.sequence,gift_card_sequence:"
+msgid "Gift Card Sequence"
+msgstr ""
+
+msgctxt "field:sale.gift_card,company:"
+msgid "Company"
+msgstr ""
+
+msgctxt "field:sale.gift_card,currency:"
+msgid "Currency"
+msgstr ""
+
+msgctxt "field:sale.gift_card,currency_digits:"
+msgid "Currency Digits"
+msgstr ""
+
+msgctxt "field:sale.gift_card,number:"
+msgid "Number"
+msgstr ""
+
+msgctxt "field:sale.gift_card,origin:"
+msgid "Origin"
+msgstr ""
+
+msgctxt "field:sale.gift_card,product:"
+msgid "Product"
+msgstr ""
+
+msgctxt "field:sale.gift_card,spent_on:"
+msgid "Spent On"
+msgstr ""
+
+msgctxt "field:sale.gift_card,value:"
+msgid "Value"
+msgstr ""
+
+msgctxt "field:sale.line,gift_card_email:"
+msgid "Gift Card Email"
+msgstr ""
+
+msgctxt "field:sale.line,gift_cards:"
+msgid "Gift Cards"
+msgstr ""
+
+msgctxt "field:sale.line,is_gift_card:"
+msgid "Is Gift Card"
+msgstr ""
+
+msgctxt "field:sale.line,is_gift_card_service:"
+msgid "Is Gift Card Service"
+msgstr ""
+
+msgctxt "field:sale.sale,gift_cards:"
+msgid "Gift Cards"
+msgstr ""
+
+msgctxt "field:stock.move,gift_cards:"
+msgid "Gift Cards"
+msgstr ""
+
+msgctxt "field:stock.move,gift_cards_required:"
+msgid "Gift Cards Required"
+msgstr ""
+
+msgctxt "help:sale.line,gift_card_email:"
+msgid "Leave empty for the customer email."
+msgstr ""
+
+msgctxt "model:account.configuration.gift_card_account,name:"
+msgid "Account Configuration Gift Card Account"
+msgstr ""
+
+msgctxt "model:ir.action,name:act_gift_card_form"
+msgid "Gift Cards"
+msgstr ""
+
+msgctxt "model:ir.action,name:report_gift_card_email"
+msgid "Gift Card"
+msgstr ""
+
+msgctxt "model:ir.action.act_window.domain,name:act_gift_card_form_domain_all"
+msgid "All"
+msgstr ""
+
+msgctxt ""
+"model:ir.action.act_window.domain,name:act_gift_card_form_domain_pending"
+msgid "Pending"
+msgstr ""
+
+msgctxt ""
+"model:ir.action.act_window.domain,name:act_gift_card_form_domain_sent"
+msgid "Sent"
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_gift_card_invalid_uom"
+msgid "The default UOM for the gift card \"%(template)s\" must be \"%(unit)s\"."
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_gift_card_move_quantity"
+msgid ""
+"To do the move \"%(move)s\", you must use exactly %(quantity)d gift card(s)."
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_gift_card_number_unique"
+msgid "The numbers for each company's gift cards must be unique."
+msgstr ""
+
+msgctxt "model:ir.rule.group,name:rule_group_gift_card_companies"
+msgid "User in companies"
+msgstr ""
+
+msgctxt "model:ir.sequence.type,name:sequence_type_gift_card"
+msgid "Gift Card"
+msgstr ""
+
+msgctxt "model:ir.ui.menu,name:menu_gift_card_form"
+msgid "Gift Cards"
+msgstr ""
+
+msgctxt "model:res.group,name:group_gift_card_admin"
+msgid "Gift Card Administration"
+msgstr ""
+
+msgctxt "model:sale.configuration.gift_card.sequence,name:"
+msgid "Gift Card Configuration Sequence"
+msgstr ""
+
+msgctxt "model:sale.gift_card,name:"
+msgid "Gift Card"
+msgstr ""
+
+msgctxt "report:sale.gift_card.email:"
+msgid "Gift Card"
+msgstr ""
+
+msgctxt "report:sale.gift_card.email:"
+msgid "Here is your code:"
+msgstr ""
+
+msgctxt "report:sale.gift_card.email:"
+msgid "You received a gift card of"
+msgstr ""
+
+msgctxt "report:sale.gift_card.email:"
+msgid "for"
+msgstr ""
+
+msgctxt "view:account.configuration:"
+msgid "Gift Card"
+msgstr ""
+
+msgctxt "view:sale.line:"
+msgid "Gift Cards"
+msgstr ""
diff --git a/modules/sale_gift_card/locale/ca.po b/modules/sale_gift_card/locale/ca.po
new file mode 100644
index 0000000000..cc51d389fa
--- /dev/null
+++ b/modules/sale_gift_card/locale/ca.po
@@ -0,0 +1,208 @@
+#
+msgid ""
+msgstr "Content-Type: text/plain; charset=utf-8\n"
+
+msgctxt "field:account.account.type,gift_card:"
+msgid "Gift Card"
+msgstr "Targeta regal"
+
+msgctxt "field:account.account.type.template,gift_card:"
+msgid "Gift Card"
+msgstr "Targeta regal"
+
+msgctxt "field:account.configuration,gift_card_account_expense:"
+msgid "Gift Card Expense"
+msgstr "Despeses de la targeta regal"
+
+msgctxt "field:account.configuration,gift_card_account_revenue:"
+msgid "Gift Card Revenue"
+msgstr "Ingressos de la targeta regal"
+
+msgctxt "field:account.configuration.gift_card_account,company:"
+msgid "Company"
+msgstr "Empresa"
+
+msgctxt ""
+"field:account.configuration.gift_card_account,gift_card_account_expense:"
+msgid "Gift Card Expense"
+msgstr "Despeses de la targeta regal"
+
+msgctxt ""
+"field:account.configuration.gift_card_account,gift_card_account_revenue:"
+msgid "Gift Card Revenue"
+msgstr "Ingressos de la targeta regal"
+
+msgctxt "field:product.product,gift_card:"
+msgid "Gift Card"
+msgstr "Targeta regal"
+
+msgctxt "field:product.template,gift_card:"
+msgid "Gift Card"
+msgstr "Targeta regal"
+
+msgctxt "field:sale.configuration,gift_card_sequence:"
+msgid "Gift Card Sequence"
+msgstr "Seqüència de targeta regal"
+
+msgctxt "field:sale.configuration.gift_card.sequence,company:"
+msgid "Company"
+msgstr "Empresa"
+
+msgctxt "field:sale.configuration.gift_card.sequence,gift_card_sequence:"
+msgid "Gift Card Sequence"
+msgstr "Seqüència de targeta regal"
+
+msgctxt "field:sale.gift_card,company:"
+msgid "Company"
+msgstr "Empresa"
+
+msgctxt "field:sale.gift_card,currency:"
+msgid "Currency"
+msgstr "Moneda"
+
+msgctxt "field:sale.gift_card,currency_digits:"
+msgid "Currency Digits"
+msgstr "Decimals de la moneda"
+
+msgctxt "field:sale.gift_card,number:"
+msgid "Number"
+msgstr "Número"
+
+msgctxt "field:sale.gift_card,origin:"
+msgid "Origin"
+msgstr "Origen"
+
+msgctxt "field:sale.gift_card,product:"
+msgid "Product"
+msgstr "Producte"
+
+msgctxt "field:sale.gift_card,spent_on:"
+msgid "Spent On"
+msgstr "Gastar amb"
+
+msgctxt "field:sale.gift_card,value:"
+msgid "Value"
+msgstr "Valor"
+
+msgctxt "field:sale.line,gift_card_email:"
+msgid "Gift Card Email"
+msgstr "Correu electrònic de la targeta regal"
+
+msgctxt "field:sale.line,gift_cards:"
+msgid "Gift Cards"
+msgstr "Targetes regal"
+
+msgctxt "field:sale.line,is_gift_card:"
+msgid "Is Gift Card"
+msgstr "És una targeta regal"
+
+msgctxt "field:sale.line,is_gift_card_service:"
+msgid "Is Gift Card Service"
+msgstr "Es el servei de targetes regal"
+
+msgctxt "field:sale.sale,gift_cards:"
+msgid "Gift Cards"
+msgstr "Targetes regal"
+
+msgctxt "field:stock.move,gift_cards:"
+msgid "Gift Cards"
+msgstr "Targetes regal"
+
+msgctxt "field:stock.move,gift_cards_required:"
+msgid "Gift Cards Required"
+msgstr "Targetes de regal obligatories"
+
+msgctxt "help:sale.line,gift_card_email:"
+msgid "Leave empty for the customer email."
+msgstr "Deixeu-ho en blanc per al correu electrònic del client."
+
+msgctxt "model:account.configuration.gift_card_account,name:"
+msgid "Account Configuration Gift Card Account"
+msgstr "Configuració de comptes comptables de targetes regal"
+
+msgctxt "model:ir.action,name:act_gift_card_form"
+msgid "Gift Cards"
+msgstr "Targetes regal"
+
+msgctxt "model:ir.action,name:report_gift_card_email"
+msgid "Gift Card"
+msgstr "Targeta regal"
+
+msgctxt "model:ir.action.act_window.domain,name:act_gift_card_form_domain_all"
+msgid "All"
+msgstr "Tot"
+
+msgctxt ""
+"model:ir.action.act_window.domain,name:act_gift_card_form_domain_pending"
+msgid "Pending"
+msgstr "Pendent"
+
+msgctxt ""
+"model:ir.action.act_window.domain,name:act_gift_card_form_domain_sent"
+msgid "Sent"
+msgstr "Enviada"
+
+msgctxt "model:ir.message,text:msg_gift_card_invalid_uom"
+msgid "The default UOM for the gift card \"%(template)s\" must be \"%(unit)s\"."
+msgstr ""
+"La UdM per defecte de la targeta regal \"%(template)s\" ha de ser "
+"\"%(unit)s\"."
+
+msgctxt "model:ir.message,text:msg_gift_card_move_quantity"
+msgid ""
+"To do the move \"%(move)s\", you must use exactly %(quantity)d gift card(s)."
+msgstr ""
+"Per realiztar el movimient \"%(move)s\", heu d'utiltizar exactament "
+"%(quantity)d targeta(es) regal."
+
+msgctxt "model:ir.message,text:msg_gift_card_number_unique"
+msgid "The numbers for each company's gift cards must be unique."
+msgstr "Els números de les targetes regal de cada empresa han de ser únics."
+
+msgctxt "model:ir.rule.group,name:rule_group_gift_card_companies"
+msgid "User in companies"
+msgstr "Usuari a les empreses"
+
+msgctxt "model:ir.sequence.type,name:sequence_type_gift_card"
+msgid "Gift Card"
+msgstr "Targeta regal"
+
+msgctxt "model:ir.ui.menu,name:menu_gift_card_form"
+msgid "Gift Cards"
+msgstr "Targetes regal"
+
+msgctxt "model:res.group,name:group_gift_card_admin"
+msgid "Gift Card Administration"
+msgstr "Administració de targetes regal"
+
+msgctxt "model:sale.configuration.gift_card.sequence,name:"
+msgid "Gift Card Configuration Sequence"
+msgstr "Configuració de seqüencies de targetes regal"
+
+msgctxt "model:sale.gift_card,name:"
+msgid "Gift Card"
+msgstr "Targeta regal"
+
+msgctxt "report:sale.gift_card.email:"
+msgid "Gift Card"
+msgstr "Targeta regal"
+
+msgctxt "report:sale.gift_card.email:"
+msgid "Here is your code:"
+msgstr "Aquí teniu el vostre codi:"
+
+msgctxt "report:sale.gift_card.email:"
+msgid "You received a gift card of"
+msgstr "Heu rebut una targeta regal de"
+
+msgctxt "report:sale.gift_card.email:"
+msgid "for"
+msgstr "per"
+
+msgctxt "view:account.configuration:"
+msgid "Gift Card"
+msgstr "Targeta regal"
+
+msgctxt "view:sale.line:"
+msgid "Gift Cards"
+msgstr "Targetes regal"
diff --git a/modules/sale_gift_card/locale/cs.po b/modules/sale_gift_card/locale/cs.po
new file mode 100644
index 0000000000..bd14ca036a
--- /dev/null
+++ b/modules/sale_gift_card/locale/cs.po
@@ -0,0 +1,204 @@
+#
+msgid ""
+msgstr "Content-Type: text/plain; charset=utf-8\n"
+
+msgctxt "field:account.account.type,gift_card:"
+msgid "Gift Card"
+msgstr ""
+
+msgctxt "field:account.account.type.template,gift_card:"
+msgid "Gift Card"
+msgstr ""
+
+msgctxt "field:account.configuration,gift_card_account_expense:"
+msgid "Gift Card Expense"
+msgstr ""
+
+msgctxt "field:account.configuration,gift_card_account_revenue:"
+msgid "Gift Card Revenue"
+msgstr ""
+
+msgctxt "field:account.configuration.gift_card_account,company:"
+msgid "Company"
+msgstr ""
+
+msgctxt ""
+"field:account.configuration.gift_card_account,gift_card_account_expense:"
+msgid "Gift Card Expense"
+msgstr ""
+
+msgctxt ""
+"field:account.configuration.gift_card_account,gift_card_account_revenue:"
+msgid "Gift Card Revenue"
+msgstr ""
+
+msgctxt "field:product.product,gift_card:"
+msgid "Gift Card"
+msgstr ""
+
+msgctxt "field:product.template,gift_card:"
+msgid "Gift Card"
+msgstr ""
+
+msgctxt "field:sale.configuration,gift_card_sequence:"
+msgid "Gift Card Sequence"
+msgstr ""
+
+msgctxt "field:sale.configuration.gift_card.sequence,company:"
+msgid "Company"
+msgstr ""
+
+msgctxt "field:sale.configuration.gift_card.sequence,gift_card_sequence:"
+msgid "Gift Card Sequence"
+msgstr ""
+
+msgctxt "field:sale.gift_card,company:"
+msgid "Company"
+msgstr ""
+
+msgctxt "field:sale.gift_card,currency:"
+msgid "Currency"
+msgstr ""
+
+msgctxt "field:sale.gift_card,currency_digits:"
+msgid "Currency Digits"
+msgstr ""
+
+msgctxt "field:sale.gift_card,number:"
+msgid "Number"
+msgstr ""
+
+msgctxt "field:sale.gift_card,origin:"
+msgid "Origin"
+msgstr ""
+
+msgctxt "field:sale.gift_card,product:"
+msgid "Product"
+msgstr ""
+
+msgctxt "field:sale.gift_card,spent_on:"
+msgid "Spent On"
+msgstr ""
+
+msgctxt "field:sale.gift_card,value:"
+msgid "Value"
+msgstr ""
+
+msgctxt "field:sale.line,gift_card_email:"
+msgid "Gift Card Email"
+msgstr ""
+
+msgctxt "field:sale.line,gift_cards:"
+msgid "Gift Cards"
+msgstr ""
+
+msgctxt "field:sale.line,is_gift_card:"
+msgid "Is Gift Card"
+msgstr ""
+
+msgctxt "field:sale.line,is_gift_card_service:"
+msgid "Is Gift Card Service"
+msgstr ""
+
+msgctxt "field:sale.sale,gift_cards:"
+msgid "Gift Cards"
+msgstr ""
+
+msgctxt "field:stock.move,gift_cards:"
+msgid "Gift Cards"
+msgstr ""
+
+msgctxt "field:stock.move,gift_cards_required:"
+msgid "Gift Cards Required"
+msgstr ""
+
+msgctxt "help:sale.line,gift_card_email:"
+msgid "Leave empty for the customer email."
+msgstr ""
+
+msgctxt "model:account.configuration.gift_card_account,name:"
+msgid "Account Configuration Gift Card Account"
+msgstr ""
+
+msgctxt "model:ir.action,name:act_gift_card_form"
+msgid "Gift Cards"
+msgstr ""
+
+msgctxt "model:ir.action,name:report_gift_card_email"
+msgid "Gift Card"
+msgstr ""
+
+msgctxt "model:ir.action.act_window.domain,name:act_gift_card_form_domain_all"
+msgid "All"
+msgstr ""
+
+msgctxt ""
+"model:ir.action.act_window.domain,name:act_gift_card_form_domain_pending"
+msgid "Pending"
+msgstr ""
+
+msgctxt ""
+"model:ir.action.act_window.domain,name:act_gift_card_form_domain_sent"
+msgid "Sent"
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_gift_card_invalid_uom"
+msgid "The default UOM for the gift card \"%(template)s\" must be \"%(unit)s\"."
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_gift_card_move_quantity"
+msgid ""
+"To do the move \"%(move)s\", you must use exactly %(quantity)d gift card(s)."
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_gift_card_number_unique"
+msgid "The numbers for each company's gift cards must be unique."
+msgstr ""
+
+msgctxt "model:ir.rule.group,name:rule_group_gift_card_companies"
+msgid "User in companies"
+msgstr ""
+
+msgctxt "model:ir.sequence.type,name:sequence_type_gift_card"
+msgid "Gift Card"
+msgstr ""
+
+msgctxt "model:ir.ui.menu,name:menu_gift_card_form"
+msgid "Gift Cards"
+msgstr ""
+
+msgctxt "model:res.group,name:group_gift_card_admin"
+msgid "Gift Card Administration"
+msgstr ""
+
+msgctxt "model:sale.configuration.gift_card.sequence,name:"
+msgid "Gift Card Configuration Sequence"
+msgstr ""
+
+msgctxt "model:sale.gift_card,name:"
+msgid "Gift Card"
+msgstr ""
+
+msgctxt "report:sale.gift_card.email:"
+msgid "Gift Card"
+msgstr ""
+
+msgctxt "report:sale.gift_card.email:"
+msgid "Here is your code:"
+msgstr ""
+
+msgctxt "report:sale.gift_card.email:"
+msgid "You received a gift card of"
+msgstr ""
+
+msgctxt "report:sale.gift_card.email:"
+msgid "for"
+msgstr ""
+
+msgctxt "view:account.configuration:"
+msgid "Gift Card"
+msgstr ""
+
+msgctxt "view:sale.line:"
+msgid "Gift Cards"
+msgstr ""
diff --git a/modules/sale_gift_card/locale/de.po b/modules/sale_gift_card/locale/de.po
new file mode 100644
index 0000000000..9ba78402d0
--- /dev/null
+++ b/modules/sale_gift_card/locale/de.po
@@ -0,0 +1,209 @@
+#
+msgid ""
+msgstr "Content-Type: text/plain; charset=utf-8\n"
+
+msgctxt "field:account.account.type,gift_card:"
+msgid "Gift Card"
+msgstr "Geschenkgutschein"
+
+msgctxt "field:account.account.type.template,gift_card:"
+msgid "Gift Card"
+msgstr "Geschenkgutschein"
+
+msgctxt "field:account.configuration,gift_card_account_expense:"
+msgid "Gift Card Expense"
+msgstr "Aufwandskonto Geschenkgutscheine"
+
+msgctxt "field:account.configuration,gift_card_account_revenue:"
+msgid "Gift Card Revenue"
+msgstr "Ertragskonto Geschenkgutscheine"
+
+msgctxt "field:account.configuration.gift_card_account,company:"
+msgid "Company"
+msgstr "Unternehmen"
+
+msgctxt ""
+"field:account.configuration.gift_card_account,gift_card_account_expense:"
+msgid "Gift Card Expense"
+msgstr "Aufwandskonto Geschenkgutscheine"
+
+msgctxt ""
+"field:account.configuration.gift_card_account,gift_card_account_revenue:"
+msgid "Gift Card Revenue"
+msgstr "Ertragskonto Geschenkgutscheine"
+
+msgctxt "field:product.product,gift_card:"
+msgid "Gift Card"
+msgstr "Geschenkgutschein"
+
+msgctxt "field:product.template,gift_card:"
+msgid "Gift Card"
+msgstr "Geschenkgutschein"
+
+msgctxt "field:sale.configuration,gift_card_sequence:"
+msgid "Gift Card Sequence"
+msgstr "Nummernkreis Geschenkgutschein"
+
+msgctxt "field:sale.configuration.gift_card.sequence,company:"
+msgid "Company"
+msgstr "Unternehmen"
+
+msgctxt "field:sale.configuration.gift_card.sequence,gift_card_sequence:"
+msgid "Gift Card Sequence"
+msgstr "Nummernkreis Geschenkgutschein"
+
+msgctxt "field:sale.gift_card,company:"
+msgid "Company"
+msgstr "Unternehmen"
+
+msgctxt "field:sale.gift_card,currency:"
+msgid "Currency"
+msgstr "Währung"
+
+msgctxt "field:sale.gift_card,currency_digits:"
+msgid "Currency Digits"
+msgstr "Nachkommastellen Währung"
+
+msgctxt "field:sale.gift_card,number:"
+msgid "Number"
+msgstr "Nummer"
+
+msgctxt "field:sale.gift_card,origin:"
+msgid "Origin"
+msgstr "Herkunft"
+
+msgctxt "field:sale.gift_card,product:"
+msgid "Product"
+msgstr "Artikel"
+
+msgctxt "field:sale.gift_card,spent_on:"
+msgid "Spent On"
+msgstr "Eingelöst auf"
+
+msgctxt "field:sale.gift_card,value:"
+msgid "Value"
+msgstr "Wert"
+
+msgctxt "field:sale.line,gift_card_email:"
+msgid "Gift Card Email"
+msgstr "E-Mail Geschenkgutschein"
+
+msgctxt "field:sale.line,gift_cards:"
+msgid "Gift Cards"
+msgstr "Geschenkgutscheine"
+
+msgctxt "field:sale.line,is_gift_card:"
+msgid "Is Gift Card"
+msgstr "Ist Geschenkgutschein"
+
+msgctxt "field:sale.line,is_gift_card_service:"
+msgid "Is Gift Card Service"
+msgstr "Ist Geschenkgutschein Für Dienstleistung"
+
+msgctxt "field:sale.sale,gift_cards:"
+msgid "Gift Cards"
+msgstr "Geschenkgutscheine"
+
+msgctxt "field:stock.move,gift_cards:"
+msgid "Gift Cards"
+msgstr "Geschenkgutscheine"
+
+msgctxt "field:stock.move,gift_cards_required:"
+msgid "Gift Cards Required"
+msgstr "Geschenkgutscheine Erforderlich"
+
+msgctxt "help:sale.line,gift_card_email:"
+msgid "Leave empty for the customer email."
+msgstr "Leer lassen um die E-Mail des Kunden zu verwenden."
+
+msgctxt "model:account.configuration.gift_card_account,name:"
+msgid "Account Configuration Gift Card Account"
+msgstr "Buchhaltung Einstellungen Konto Geschenkgutschein"
+
+msgctxt "model:ir.action,name:act_gift_card_form"
+msgid "Gift Cards"
+msgstr "Geschenkgutscheine"
+
+msgctxt "model:ir.action,name:report_gift_card_email"
+msgid "Gift Card"
+msgstr "Geschenkgutschein"
+
+msgctxt "model:ir.action.act_window.domain,name:act_gift_card_form_domain_all"
+msgid "All"
+msgstr "Alle"
+
+msgctxt ""
+"model:ir.action.act_window.domain,name:act_gift_card_form_domain_pending"
+msgid "Pending"
+msgstr "Nicht eingelöst"
+
+msgctxt ""
+"model:ir.action.act_window.domain,name:act_gift_card_form_domain_sent"
+msgid "Sent"
+msgstr "Gesendet"
+
+msgctxt "model:ir.message,text:msg_gift_card_invalid_uom"
+msgid "The default UOM for the gift card \"%(template)s\" must be \"%(unit)s\"."
+msgstr ""
+"Die Standardmaßeinheit für den Geschenkgutschein \"%(template)s\" muss "
+"\"%(unit)s\" sein."
+
+msgctxt "model:ir.message,text:msg_gift_card_move_quantity"
+msgid ""
+"To do the move \"%(move)s\", you must use exactly %(quantity)d gift card(s)."
+msgstr ""
+"Um die Lagerbewegung \"%(move)s\" auszuführen müssen genau %(quantity)d "
+"Geschenkgutschein(e) verwendet werden."
+
+msgctxt "model:ir.message,text:msg_gift_card_number_unique"
+msgid "The numbers for each company's gift cards must be unique."
+msgstr ""
+"Die Nummer für jeden Geschenkgutschein des Unternehmens muss eindeutig sein."
+
+msgctxt "model:ir.rule.group,name:rule_group_gift_card_companies"
+msgid "User in companies"
+msgstr "Benutzer im Unternehmen"
+
+msgctxt "model:ir.sequence.type,name:sequence_type_gift_card"
+msgid "Gift Card"
+msgstr "Geschenkgutschein"
+
+msgctxt "model:ir.ui.menu,name:menu_gift_card_form"
+msgid "Gift Cards"
+msgstr "Geschenkgutscheine"
+
+msgctxt "model:res.group,name:group_gift_card_admin"
+msgid "Gift Card Administration"
+msgstr "Administration Geschenkgutscheine"
+
+msgctxt "model:sale.configuration.gift_card.sequence,name:"
+msgid "Gift Card Configuration Sequence"
+msgstr "Einstellungen Nummernkreis Geschenkgutschein"
+
+msgctxt "model:sale.gift_card,name:"
+msgid "Gift Card"
+msgstr "Geschenkgutschein"
+
+msgctxt "report:sale.gift_card.email:"
+msgid "Gift Card"
+msgstr "Geschenkgutschein"
+
+msgctxt "report:sale.gift_card.email:"
+msgid "Here is your code:"
+msgstr "Hier ist Ihr Code:"
+
+msgctxt "report:sale.gift_card.email:"
+msgid "You received a gift card of"
+msgstr "Sie haben einen Geschenkgutschein erhalten von"
+
+msgctxt "report:sale.gift_card.email:"
+msgid "for"
+msgstr "für"
+
+msgctxt "view:account.configuration:"
+msgid "Gift Card"
+msgstr "Geschenkgutschein"
+
+msgctxt "view:sale.line:"
+msgid "Gift Cards"
+msgstr "Geschenkgutscheine"
diff --git a/modules/sale_gift_card/locale/es.po b/modules/sale_gift_card/locale/es.po
new file mode 100644
index 0000000000..03f05994fd
--- /dev/null
+++ b/modules/sale_gift_card/locale/es.po
@@ -0,0 +1,208 @@
+#
+msgid ""
+msgstr "Content-Type: text/plain; charset=utf-8\n"
+
+msgctxt "field:account.account.type,gift_card:"
+msgid "Gift Card"
+msgstr "Tarjeta regalo"
+
+msgctxt "field:account.account.type.template,gift_card:"
+msgid "Gift Card"
+msgstr "Tarjeta regalo"
+
+msgctxt "field:account.configuration,gift_card_account_expense:"
+msgid "Gift Card Expense"
+msgstr "Gastos de la tarjeta regalo"
+
+msgctxt "field:account.configuration,gift_card_account_revenue:"
+msgid "Gift Card Revenue"
+msgstr "Ingresos de la tarjeta regalo"
+
+msgctxt "field:account.configuration.gift_card_account,company:"
+msgid "Company"
+msgstr "Empresa"
+
+msgctxt ""
+"field:account.configuration.gift_card_account,gift_card_account_expense:"
+msgid "Gift Card Expense"
+msgstr "Gastos de la tarjeta regalo"
+
+msgctxt ""
+"field:account.configuration.gift_card_account,gift_card_account_revenue:"
+msgid "Gift Card Revenue"
+msgstr "Ingresos de la tarjeta regalo"
+
+msgctxt "field:product.product,gift_card:"
+msgid "Gift Card"
+msgstr "Tarjeta regalo"
+
+msgctxt "field:product.template,gift_card:"
+msgid "Gift Card"
+msgstr "Tarjeta regalo"
+
+msgctxt "field:sale.configuration,gift_card_sequence:"
+msgid "Gift Card Sequence"
+msgstr "Secuencia de tarjeta regalo"
+
+msgctxt "field:sale.configuration.gift_card.sequence,company:"
+msgid "Company"
+msgstr "Empresa"
+
+msgctxt "field:sale.configuration.gift_card.sequence,gift_card_sequence:"
+msgid "Gift Card Sequence"
+msgstr "Secuencia de tarjeta regalo"
+
+msgctxt "field:sale.gift_card,company:"
+msgid "Company"
+msgstr "Empresa"
+
+msgctxt "field:sale.gift_card,currency:"
+msgid "Currency"
+msgstr "Moneda"
+
+msgctxt "field:sale.gift_card,currency_digits:"
+msgid "Currency Digits"
+msgstr "Decimales de la moneda"
+
+msgctxt "field:sale.gift_card,number:"
+msgid "Number"
+msgstr "Número"
+
+msgctxt "field:sale.gift_card,origin:"
+msgid "Origin"
+msgstr "Origen"
+
+msgctxt "field:sale.gift_card,product:"
+msgid "Product"
+msgstr "Producto"
+
+msgctxt "field:sale.gift_card,spent_on:"
+msgid "Spent On"
+msgstr "Gastada en"
+
+msgctxt "field:sale.gift_card,value:"
+msgid "Value"
+msgstr "Valor"
+
+msgctxt "field:sale.line,gift_card_email:"
+msgid "Gift Card Email"
+msgstr "Correo electrònico de la tarjeta regalo"
+
+msgctxt "field:sale.line,gift_cards:"
+msgid "Gift Cards"
+msgstr "Tarjetas regalo"
+
+msgctxt "field:sale.line,is_gift_card:"
+msgid "Is Gift Card"
+msgstr "Es tarjeta regalo"
+
+msgctxt "field:sale.line,is_gift_card_service:"
+msgid "Is Gift Card Service"
+msgstr "Es el servicio de tarjetas de regalo"
+
+msgctxt "field:sale.sale,gift_cards:"
+msgid "Gift Cards"
+msgstr "Tarjetas regalo"
+
+msgctxt "field:stock.move,gift_cards:"
+msgid "Gift Cards"
+msgstr "Tarjetas regalo"
+
+msgctxt "field:stock.move,gift_cards_required:"
+msgid "Gift Cards Required"
+msgstr "Tarjetas de regalo obligatorias"
+
+msgctxt "help:sale.line,gift_card_email:"
+msgid "Leave empty for the customer email."
+msgstr "Dejar vacío para el correo electrónico del cliente."
+
+msgctxt "model:account.configuration.gift_card_account,name:"
+msgid "Account Configuration Gift Card Account"
+msgstr "Configuración cuentas contables tarjetas regalo"
+
+msgctxt "model:ir.action,name:act_gift_card_form"
+msgid "Gift Cards"
+msgstr "Tarjetas regalo"
+
+msgctxt "model:ir.action,name:report_gift_card_email"
+msgid "Gift Card"
+msgstr "Tarjeta regalo"
+
+msgctxt "model:ir.action.act_window.domain,name:act_gift_card_form_domain_all"
+msgid "All"
+msgstr "Todo"
+
+msgctxt ""
+"model:ir.action.act_window.domain,name:act_gift_card_form_domain_pending"
+msgid "Pending"
+msgstr "Pendiente"
+
+msgctxt ""
+"model:ir.action.act_window.domain,name:act_gift_card_form_domain_sent"
+msgid "Sent"
+msgstr "Enviada"
+
+msgctxt "model:ir.message,text:msg_gift_card_invalid_uom"
+msgid "The default UOM for the gift card \"%(template)s\" must be \"%(unit)s\"."
+msgstr ""
+"La UdM por defecto para la tarjeta de regalo \"%(template)s\" tiene que ser "
+"\"%(unit)s\"."
+
+msgctxt "model:ir.message,text:msg_gift_card_move_quantity"
+msgid ""
+"To do the move \"%(move)s\", you must use exactly %(quantity)d gift card(s)."
+msgstr ""
+"Para realizar el movimiento \"%(move)s\", debes usar exactamente "
+"%(quantity)d tarjeta(s) regalo."
+
+msgctxt "model:ir.message,text:msg_gift_card_number_unique"
+msgid "The numbers for each company's gift cards must be unique."
+msgstr "Los números para cada tarjeta regalo de la compañía deben ser únicos."
+
+msgctxt "model:ir.rule.group,name:rule_group_gift_card_companies"
+msgid "User in companies"
+msgstr "Usuario en las empresas"
+
+msgctxt "model:ir.sequence.type,name:sequence_type_gift_card"
+msgid "Gift Card"
+msgstr "Tarjeta regalo"
+
+msgctxt "model:ir.ui.menu,name:menu_gift_card_form"
+msgid "Gift Cards"
+msgstr "Tarjetas regalo"
+
+msgctxt "model:res.group,name:group_gift_card_admin"
+msgid "Gift Card Administration"
+msgstr "Administración de tarjetas regalo"
+
+msgctxt "model:sale.configuration.gift_card.sequence,name:"
+msgid "Gift Card Configuration Sequence"
+msgstr "Configuración de secuèncias de tarjetas regalo"
+
+msgctxt "model:sale.gift_card,name:"
+msgid "Gift Card"
+msgstr "Tarjeta regalo"
+
+msgctxt "report:sale.gift_card.email:"
+msgid "Gift Card"
+msgstr "Tarjeta regalo"
+
+msgctxt "report:sale.gift_card.email:"
+msgid "Here is your code:"
+msgstr "Aqui tenéis vuestro código:"
+
+msgctxt "report:sale.gift_card.email:"
+msgid "You received a gift card of"
+msgstr "Has recibido una tarjeta regalo de"
+
+msgctxt "report:sale.gift_card.email:"
+msgid "for"
+msgstr "para"
+
+msgctxt "view:account.configuration:"
+msgid "Gift Card"
+msgstr "Tarjeta regalo"
+
+msgctxt "view:sale.line:"
+msgid "Gift Cards"
+msgstr "Tarjetas regalo"
diff --git a/modules/sale_gift_card/locale/es_419.po b/modules/sale_gift_card/locale/es_419.po
new file mode 100644
index 0000000000..bd14ca036a
--- /dev/null
+++ b/modules/sale_gift_card/locale/es_419.po
@@ -0,0 +1,204 @@
+#
+msgid ""
+msgstr "Content-Type: text/plain; charset=utf-8\n"
+
+msgctxt "field:account.account.type,gift_card:"
+msgid "Gift Card"
+msgstr ""
+
+msgctxt "field:account.account.type.template,gift_card:"
+msgid "Gift Card"
+msgstr ""
+
+msgctxt "field:account.configuration,gift_card_account_expense:"
+msgid "Gift Card Expense"
+msgstr ""
+
+msgctxt "field:account.configuration,gift_card_account_revenue:"
+msgid "Gift Card Revenue"
+msgstr ""
+
+msgctxt "field:account.configuration.gift_card_account,company:"
+msgid "Company"
+msgstr ""
+
+msgctxt ""
+"field:account.configuration.gift_card_account,gift_card_account_expense:"
+msgid "Gift Card Expense"
+msgstr ""
+
+msgctxt ""
+"field:account.configuration.gift_card_account,gift_card_account_revenue:"
+msgid "Gift Card Revenue"
+msgstr ""
+
+msgctxt "field:product.product,gift_card:"
+msgid "Gift Card"
+msgstr ""
+
+msgctxt "field:product.template,gift_card:"
+msgid "Gift Card"
+msgstr ""
+
+msgctxt "field:sale.configuration,gift_card_sequence:"
+msgid "Gift Card Sequence"
+msgstr ""
+
+msgctxt "field:sale.configuration.gift_card.sequence,company:"
+msgid "Company"
+msgstr ""
+
+msgctxt "field:sale.configuration.gift_card.sequence,gift_card_sequence:"
+msgid "Gift Card Sequence"
+msgstr ""
+
+msgctxt "field:sale.gift_card,company:"
+msgid "Company"
+msgstr ""
+
+msgctxt "field:sale.gift_card,currency:"
+msgid "Currency"
+msgstr ""
+
+msgctxt "field:sale.gift_card,currency_digits:"
+msgid "Currency Digits"
+msgstr ""
+
+msgctxt "field:sale.gift_card,number:"
+msgid "Number"
+msgstr ""
+
+msgctxt "field:sale.gift_card,origin:"
+msgid "Origin"
+msgstr ""
+
+msgctxt "field:sale.gift_card,product:"
+msgid "Product"
+msgstr ""
+
+msgctxt "field:sale.gift_card,spent_on:"
+msgid "Spent On"
+msgstr ""
+
+msgctxt "field:sale.gift_card,value:"
+msgid "Value"
+msgstr ""
+
+msgctxt "field:sale.line,gift_card_email:"
+msgid "Gift Card Email"
+msgstr ""
+
+msgctxt "field:sale.line,gift_cards:"
+msgid "Gift Cards"
+msgstr ""
+
+msgctxt "field:sale.line,is_gift_card:"
+msgid "Is Gift Card"
+msgstr ""
+
+msgctxt "field:sale.line,is_gift_card_service:"
+msgid "Is Gift Card Service"
+msgstr ""
+
+msgctxt "field:sale.sale,gift_cards:"
+msgid "Gift Cards"
+msgstr ""
+
+msgctxt "field:stock.move,gift_cards:"
+msgid "Gift Cards"
+msgstr ""
+
+msgctxt "field:stock.move,gift_cards_required:"
+msgid "Gift Cards Required"
+msgstr ""
+
+msgctxt "help:sale.line,gift_card_email:"
+msgid "Leave empty for the customer email."
+msgstr ""
+
+msgctxt "model:account.configuration.gift_card_account,name:"
+msgid "Account Configuration Gift Card Account"
+msgstr ""
+
+msgctxt "model:ir.action,name:act_gift_card_form"
+msgid "Gift Cards"
+msgstr ""
+
+msgctxt "model:ir.action,name:report_gift_card_email"
+msgid "Gift Card"
+msgstr ""
+
+msgctxt "model:ir.action.act_window.domain,name:act_gift_card_form_domain_all"
+msgid "All"
+msgstr ""
+
+msgctxt ""
+"model:ir.action.act_window.domain,name:act_gift_card_form_domain_pending"
+msgid "Pending"
+msgstr ""
+
+msgctxt ""
+"model:ir.action.act_window.domain,name:act_gift_card_form_domain_sent"
+msgid "Sent"
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_gift_card_invalid_uom"
+msgid "The default UOM for the gift card \"%(template)s\" must be \"%(unit)s\"."
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_gift_card_move_quantity"
+msgid ""
+"To do the move \"%(move)s\", you must use exactly %(quantity)d gift card(s)."
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_gift_card_number_unique"
+msgid "The numbers for each company's gift cards must be unique."
+msgstr ""
+
+msgctxt "model:ir.rule.group,name:rule_group_gift_card_companies"
+msgid "User in companies"
+msgstr ""
+
+msgctxt "model:ir.sequence.type,name:sequence_type_gift_card"
+msgid "Gift Card"
+msgstr ""
+
+msgctxt "model:ir.ui.menu,name:menu_gift_card_form"
+msgid "Gift Cards"
+msgstr ""
+
+msgctxt "model:res.group,name:group_gift_card_admin"
+msgid "Gift Card Administration"
+msgstr ""
+
+msgctxt "model:sale.configuration.gift_card.sequence,name:"
+msgid "Gift Card Configuration Sequence"
+msgstr ""
+
+msgctxt "model:sale.gift_card,name:"
+msgid "Gift Card"
+msgstr ""
+
+msgctxt "report:sale.gift_card.email:"
+msgid "Gift Card"
+msgstr ""
+
+msgctxt "report:sale.gift_card.email:"
+msgid "Here is your code:"
+msgstr ""
+
+msgctxt "report:sale.gift_card.email:"
+msgid "You received a gift card of"
+msgstr ""
+
+msgctxt "report:sale.gift_card.email:"
+msgid "for"
+msgstr ""
+
+msgctxt "view:account.configuration:"
+msgid "Gift Card"
+msgstr ""
+
+msgctxt "view:sale.line:"
+msgid "Gift Cards"
+msgstr ""
diff --git a/modules/sale_gift_card/locale/et.po b/modules/sale_gift_card/locale/et.po
new file mode 100644
index 0000000000..bd14ca036a
--- /dev/null
+++ b/modules/sale_gift_card/locale/et.po
@@ -0,0 +1,204 @@
+#
+msgid ""
+msgstr "Content-Type: text/plain; charset=utf-8\n"
+
+msgctxt "field:account.account.type,gift_card:"
+msgid "Gift Card"
+msgstr ""
+
+msgctxt "field:account.account.type.template,gift_card:"
+msgid "Gift Card"
+msgstr ""
+
+msgctxt "field:account.configuration,gift_card_account_expense:"
+msgid "Gift Card Expense"
+msgstr ""
+
+msgctxt "field:account.configuration,gift_card_account_revenue:"
+msgid "Gift Card Revenue"
+msgstr ""
+
+msgctxt "field:account.configuration.gift_card_account,company:"
+msgid "Company"
+msgstr ""
+
+msgctxt ""
+"field:account.configuration.gift_card_account,gift_card_account_expense:"
+msgid "Gift Card Expense"
+msgstr ""
+
+msgctxt ""
+"field:account.configuration.gift_card_account,gift_card_account_revenue:"
+msgid "Gift Card Revenue"
+msgstr ""
+
+msgctxt "field:product.product,gift_card:"
+msgid "Gift Card"
+msgstr ""
+
+msgctxt "field:product.template,gift_card:"
+msgid "Gift Card"
+msgstr ""
+
+msgctxt "field:sale.configuration,gift_card_sequence:"
+msgid "Gift Card Sequence"
+msgstr ""
+
+msgctxt "field:sale.configuration.gift_card.sequence,company:"
+msgid "Company"
+msgstr ""
+
+msgctxt "field:sale.configuration.gift_card.sequence,gift_card_sequence:"
+msgid "Gift Card Sequence"
+msgstr ""
+
+msgctxt "field:sale.gift_card,company:"
+msgid "Company"
+msgstr ""
+
+msgctxt "field:sale.gift_card,currency:"
+msgid "Currency"
+msgstr ""
+
+msgctxt "field:sale.gift_card,currency_digits:"
+msgid "Currency Digits"
+msgstr ""
+
+msgctxt "field:sale.gift_card,number:"
+msgid "Number"
+msgstr ""
+
+msgctxt "field:sale.gift_card,origin:"
+msgid "Origin"
+msgstr ""
+
+msgctxt "field:sale.gift_card,product:"
+msgid "Product"
+msgstr ""
+
+msgctxt "field:sale.gift_card,spent_on:"
+msgid "Spent On"
+msgstr ""
+
+msgctxt "field:sale.gift_card,value:"
+msgid "Value"
+msgstr ""
+
+msgctxt "field:sale.line,gift_card_email:"
+msgid "Gift Card Email"
+msgstr ""
+
+msgctxt "field:sale.line,gift_cards:"
+msgid "Gift Cards"
+msgstr ""
+
+msgctxt "field:sale.line,is_gift_card:"
+msgid "Is Gift Card"
+msgstr ""
+
+msgctxt "field:sale.line,is_gift_card_service:"
+msgid "Is Gift Card Service"
+msgstr ""
+
+msgctxt "field:sale.sale,gift_cards:"
+msgid "Gift Cards"
+msgstr ""
+
+msgctxt "field:stock.move,gift_cards:"
+msgid "Gift Cards"
+msgstr ""
+
+msgctxt "field:stock.move,gift_cards_required:"
+msgid "Gift Cards Required"
+msgstr ""
+
+msgctxt "help:sale.line,gift_card_email:"
+msgid "Leave empty for the customer email."
+msgstr ""
+
+msgctxt "model:account.configuration.gift_card_account,name:"
+msgid "Account Configuration Gift Card Account"
+msgstr ""
+
+msgctxt "model:ir.action,name:act_gift_card_form"
+msgid "Gift Cards"
+msgstr ""
+
+msgctxt "model:ir.action,name:report_gift_card_email"
+msgid "Gift Card"
+msgstr ""
+
+msgctxt "model:ir.action.act_window.domain,name:act_gift_card_form_domain_all"
+msgid "All"
+msgstr ""
+
+msgctxt ""
+"model:ir.action.act_window.domain,name:act_gift_card_form_domain_pending"
+msgid "Pending"
+msgstr ""
+
+msgctxt ""
+"model:ir.action.act_window.domain,name:act_gift_card_form_domain_sent"
+msgid "Sent"
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_gift_card_invalid_uom"
+msgid "The default UOM for the gift card \"%(template)s\" must be \"%(unit)s\"."
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_gift_card_move_quantity"
+msgid ""
+"To do the move \"%(move)s\", you must use exactly %(quantity)d gift card(s)."
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_gift_card_number_unique"
+msgid "The numbers for each company's gift cards must be unique."
+msgstr ""
+
+msgctxt "model:ir.rule.group,name:rule_group_gift_card_companies"
+msgid "User in companies"
+msgstr ""
+
+msgctxt "model:ir.sequence.type,name:sequence_type_gift_card"
+msgid "Gift Card"
+msgstr ""
+
+msgctxt "model:ir.ui.menu,name:menu_gift_card_form"
+msgid "Gift Cards"
+msgstr ""
+
+msgctxt "model:res.group,name:group_gift_card_admin"
+msgid "Gift Card Administration"
+msgstr ""
+
+msgctxt "model:sale.configuration.gift_card.sequence,name:"
+msgid "Gift Card Configuration Sequence"
+msgstr ""
+
+msgctxt "model:sale.gift_card,name:"
+msgid "Gift Card"
+msgstr ""
+
+msgctxt "report:sale.gift_card.email:"
+msgid "Gift Card"
+msgstr ""
+
+msgctxt "report:sale.gift_card.email:"
+msgid "Here is your code:"
+msgstr ""
+
+msgctxt "report:sale.gift_card.email:"
+msgid "You received a gift card of"
+msgstr ""
+
+msgctxt "report:sale.gift_card.email:"
+msgid "for"
+msgstr ""
+
+msgctxt "view:account.configuration:"
+msgid "Gift Card"
+msgstr ""
+
+msgctxt "view:sale.line:"
+msgid "Gift Cards"
+msgstr ""
diff --git a/modules/sale_gift_card/locale/fa.po b/modules/sale_gift_card/locale/fa.po
new file mode 100644
index 0000000000..bd14ca036a
--- /dev/null
+++ b/modules/sale_gift_card/locale/fa.po
@@ -0,0 +1,204 @@
+#
+msgid ""
+msgstr "Content-Type: text/plain; charset=utf-8\n"
+
+msgctxt "field:account.account.type,gift_card:"
+msgid "Gift Card"
+msgstr ""
+
+msgctxt "field:account.account.type.template,gift_card:"
+msgid "Gift Card"
+msgstr ""
+
+msgctxt "field:account.configuration,gift_card_account_expense:"
+msgid "Gift Card Expense"
+msgstr ""
+
+msgctxt "field:account.configuration,gift_card_account_revenue:"
+msgid "Gift Card Revenue"
+msgstr ""
+
+msgctxt "field:account.configuration.gift_card_account,company:"
+msgid "Company"
+msgstr ""
+
+msgctxt ""
+"field:account.configuration.gift_card_account,gift_card_account_expense:"
+msgid "Gift Card Expense"
+msgstr ""
+
+msgctxt ""
+"field:account.configuration.gift_card_account,gift_card_account_revenue:"
+msgid "Gift Card Revenue"
+msgstr ""
+
+msgctxt "field:product.product,gift_card:"
+msgid "Gift Card"
+msgstr ""
+
+msgctxt "field:product.template,gift_card:"
+msgid "Gift Card"
+msgstr ""
+
+msgctxt "field:sale.configuration,gift_card_sequence:"
+msgid "Gift Card Sequence"
+msgstr ""
+
+msgctxt "field:sale.configuration.gift_card.sequence,company:"
+msgid "Company"
+msgstr ""
+
+msgctxt "field:sale.configuration.gift_card.sequence,gift_card_sequence:"
+msgid "Gift Card Sequence"
+msgstr ""
+
+msgctxt "field:sale.gift_card,company:"
+msgid "Company"
+msgstr ""
+
+msgctxt "field:sale.gift_card,currency:"
+msgid "Currency"
+msgstr ""
+
+msgctxt "field:sale.gift_card,currency_digits:"
+msgid "Currency Digits"
+msgstr ""
+
+msgctxt "field:sale.gift_card,number:"
+msgid "Number"
+msgstr ""
+
+msgctxt "field:sale.gift_card,origin:"
+msgid "Origin"
+msgstr ""
+
+msgctxt "field:sale.gift_card,product:"
+msgid "Product"
+msgstr ""
+
+msgctxt "field:sale.gift_card,spent_on:"
+msgid "Spent On"
+msgstr ""
+
+msgctxt "field:sale.gift_card,value:"
+msgid "Value"
+msgstr ""
+
+msgctxt "field:sale.line,gift_card_email:"
+msgid "Gift Card Email"
+msgstr ""
+
+msgctxt "field:sale.line,gift_cards:"
+msgid "Gift Cards"
+msgstr ""
+
+msgctxt "field:sale.line,is_gift_card:"
+msgid "Is Gift Card"
+msgstr ""
+
+msgctxt "field:sale.line,is_gift_card_service:"
+msgid "Is Gift Card Service"
+msgstr ""
+
+msgctxt "field:sale.sale,gift_cards:"
+msgid "Gift Cards"
+msgstr ""
+
+msgctxt "field:stock.move,gift_cards:"
+msgid "Gift Cards"
+msgstr ""
+
+msgctxt "field:stock.move,gift_cards_required:"
+msgid "Gift Cards Required"
+msgstr ""
+
+msgctxt "help:sale.line,gift_card_email:"
+msgid "Leave empty for the customer email."
+msgstr ""
+
+msgctxt "model:account.configuration.gift_card_account,name:"
+msgid "Account Configuration Gift Card Account"
+msgstr ""
+
+msgctxt "model:ir.action,name:act_gift_card_form"
+msgid "Gift Cards"
+msgstr ""
+
+msgctxt "model:ir.action,name:report_gift_card_email"
+msgid "Gift Card"
+msgstr ""
+
+msgctxt "model:ir.action.act_window.domain,name:act_gift_card_form_domain_all"
+msgid "All"
+msgstr ""
+
+msgctxt ""
+"model:ir.action.act_window.domain,name:act_gift_card_form_domain_pending"
+msgid "Pending"
+msgstr ""
+
+msgctxt ""
+"model:ir.action.act_window.domain,name:act_gift_card_form_domain_sent"
+msgid "Sent"
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_gift_card_invalid_uom"
+msgid "The default UOM for the gift card \"%(template)s\" must be \"%(unit)s\"."
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_gift_card_move_quantity"
+msgid ""
+"To do the move \"%(move)s\", you must use exactly %(quantity)d gift card(s)."
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_gift_card_number_unique"
+msgid "The numbers for each company's gift cards must be unique."
+msgstr ""
+
+msgctxt "model:ir.rule.group,name:rule_group_gift_card_companies"
+msgid "User in companies"
+msgstr ""
+
+msgctxt "model:ir.sequence.type,name:sequence_type_gift_card"
+msgid "Gift Card"
+msgstr ""
+
+msgctxt "model:ir.ui.menu,name:menu_gift_card_form"
+msgid "Gift Cards"
+msgstr ""
+
+msgctxt "model:res.group,name:group_gift_card_admin"
+msgid "Gift Card Administration"
+msgstr ""
+
+msgctxt "model:sale.configuration.gift_card.sequence,name:"
+msgid "Gift Card Configuration Sequence"
+msgstr ""
+
+msgctxt "model:sale.gift_card,name:"
+msgid "Gift Card"
+msgstr ""
+
+msgctxt "report:sale.gift_card.email:"
+msgid "Gift Card"
+msgstr ""
+
+msgctxt "report:sale.gift_card.email:"
+msgid "Here is your code:"
+msgstr ""
+
+msgctxt "report:sale.gift_card.email:"
+msgid "You received a gift card of"
+msgstr ""
+
+msgctxt "report:sale.gift_card.email:"
+msgid "for"
+msgstr ""
+
+msgctxt "view:account.configuration:"
+msgid "Gift Card"
+msgstr ""
+
+msgctxt "view:sale.line:"
+msgid "Gift Cards"
+msgstr ""
diff --git a/modules/sale_gift_card/locale/fi.po b/modules/sale_gift_card/locale/fi.po
new file mode 100644
index 0000000000..bd14ca036a
--- /dev/null
+++ b/modules/sale_gift_card/locale/fi.po
@@ -0,0 +1,204 @@
+#
+msgid ""
+msgstr "Content-Type: text/plain; charset=utf-8\n"
+
+msgctxt "field:account.account.type,gift_card:"
+msgid "Gift Card"
+msgstr ""
+
+msgctxt "field:account.account.type.template,gift_card:"
+msgid "Gift Card"
+msgstr ""
+
+msgctxt "field:account.configuration,gift_card_account_expense:"
+msgid "Gift Card Expense"
+msgstr ""
+
+msgctxt "field:account.configuration,gift_card_account_revenue:"
+msgid "Gift Card Revenue"
+msgstr ""
+
+msgctxt "field:account.configuration.gift_card_account,company:"
+msgid "Company"
+msgstr ""
+
+msgctxt ""
+"field:account.configuration.gift_card_account,gift_card_account_expense:"
+msgid "Gift Card Expense"
+msgstr ""
+
+msgctxt ""
+"field:account.configuration.gift_card_account,gift_card_account_revenue:"
+msgid "Gift Card Revenue"
+msgstr ""
+
+msgctxt "field:product.product,gift_card:"
+msgid "Gift Card"
+msgstr ""
+
+msgctxt "field:product.template,gift_card:"
+msgid "Gift Card"
+msgstr ""
+
+msgctxt "field:sale.configuration,gift_card_sequence:"
+msgid "Gift Card Sequence"
+msgstr ""
+
+msgctxt "field:sale.configuration.gift_card.sequence,company:"
+msgid "Company"
+msgstr ""
+
+msgctxt "field:sale.configuration.gift_card.sequence,gift_card_sequence:"
+msgid "Gift Card Sequence"
+msgstr ""
+
+msgctxt "field:sale.gift_card,company:"
+msgid "Company"
+msgstr ""
+
+msgctxt "field:sale.gift_card,currency:"
+msgid "Currency"
+msgstr ""
+
+msgctxt "field:sale.gift_card,currency_digits:"
+msgid "Currency Digits"
+msgstr ""
+
+msgctxt "field:sale.gift_card,number:"
+msgid "Number"
+msgstr ""
+
+msgctxt "field:sale.gift_card,origin:"
+msgid "Origin"
+msgstr ""
+
+msgctxt "field:sale.gift_card,product:"
+msgid "Product"
+msgstr ""
+
+msgctxt "field:sale.gift_card,spent_on:"
+msgid "Spent On"
+msgstr ""
+
+msgctxt "field:sale.gift_card,value:"
+msgid "Value"
+msgstr ""
+
+msgctxt "field:sale.line,gift_card_email:"
+msgid "Gift Card Email"
+msgstr ""
+
+msgctxt "field:sale.line,gift_cards:"
+msgid "Gift Cards"
+msgstr ""
+
+msgctxt "field:sale.line,is_gift_card:"
+msgid "Is Gift Card"
+msgstr ""
+
+msgctxt "field:sale.line,is_gift_card_service:"
+msgid "Is Gift Card Service"
+msgstr ""
+
+msgctxt "field:sale.sale,gift_cards:"
+msgid "Gift Cards"
+msgstr ""
+
+msgctxt "field:stock.move,gift_cards:"
+msgid "Gift Cards"
+msgstr ""
+
+msgctxt "field:stock.move,gift_cards_required:"
+msgid "Gift Cards Required"
+msgstr ""
+
+msgctxt "help:sale.line,gift_card_email:"
+msgid "Leave empty for the customer email."
+msgstr ""
+
+msgctxt "model:account.configuration.gift_card_account,name:"
+msgid "Account Configuration Gift Card Account"
+msgstr ""
+
+msgctxt "model:ir.action,name:act_gift_card_form"
+msgid "Gift Cards"
+msgstr ""
+
+msgctxt "model:ir.action,name:report_gift_card_email"
+msgid "Gift Card"
+msgstr ""
+
+msgctxt "model:ir.action.act_window.domain,name:act_gift_card_form_domain_all"
+msgid "All"
+msgstr ""
+
+msgctxt ""
+"model:ir.action.act_window.domain,name:act_gift_card_form_domain_pending"
+msgid "Pending"
+msgstr ""
+
+msgctxt ""
+"model:ir.action.act_window.domain,name:act_gift_card_form_domain_sent"
+msgid "Sent"
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_gift_card_invalid_uom"
+msgid "The default UOM for the gift card \"%(template)s\" must be \"%(unit)s\"."
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_gift_card_move_quantity"
+msgid ""
+"To do the move \"%(move)s\", you must use exactly %(quantity)d gift card(s)."
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_gift_card_number_unique"
+msgid "The numbers for each company's gift cards must be unique."
+msgstr ""
+
+msgctxt "model:ir.rule.group,name:rule_group_gift_card_companies"
+msgid "User in companies"
+msgstr ""
+
+msgctxt "model:ir.sequence.type,name:sequence_type_gift_card"
+msgid "Gift Card"
+msgstr ""
+
+msgctxt "model:ir.ui.menu,name:menu_gift_card_form"
+msgid "Gift Cards"
+msgstr ""
+
+msgctxt "model:res.group,name:group_gift_card_admin"
+msgid "Gift Card Administration"
+msgstr ""
+
+msgctxt "model:sale.configuration.gift_card.sequence,name:"
+msgid "Gift Card Configuration Sequence"
+msgstr ""
+
+msgctxt "model:sale.gift_card,name:"
+msgid "Gift Card"
+msgstr ""
+
+msgctxt "report:sale.gift_card.email:"
+msgid "Gift Card"
+msgstr ""
+
+msgctxt "report:sale.gift_card.email:"
+msgid "Here is your code:"
+msgstr ""
+
+msgctxt "report:sale.gift_card.email:"
+msgid "You received a gift card of"
+msgstr ""
+
+msgctxt "report:sale.gift_card.email:"
+msgid "for"
+msgstr ""
+
+msgctxt "view:account.configuration:"
+msgid "Gift Card"
+msgstr ""
+
+msgctxt "view:sale.line:"
+msgid "Gift Cards"
+msgstr ""
diff --git a/modules/sale_gift_card/locale/fr.po b/modules/sale_gift_card/locale/fr.po
new file mode 100644
index 0000000000..8f10912c4d
--- /dev/null
+++ b/modules/sale_gift_card/locale/fr.po
@@ -0,0 +1,208 @@
+#
+msgid ""
+msgstr "Content-Type: text/plain; charset=utf-8\n"
+
+msgctxt "field:account.account.type,gift_card:"
+msgid "Gift Card"
+msgstr "Carte cadeau"
+
+msgctxt "field:account.account.type.template,gift_card:"
+msgid "Gift Card"
+msgstr "Carte cadeau"
+
+msgctxt "field:account.configuration,gift_card_account_expense:"
+msgid "Gift Card Expense"
+msgstr "Charges de carte cadeau"
+
+msgctxt "field:account.configuration,gift_card_account_revenue:"
+msgid "Gift Card Revenue"
+msgstr "Produits de carte cadeau"
+
+msgctxt "field:account.configuration.gift_card_account,company:"
+msgid "Company"
+msgstr "Société"
+
+msgctxt ""
+"field:account.configuration.gift_card_account,gift_card_account_expense:"
+msgid "Gift Card Expense"
+msgstr "Charges de carte cadeau"
+
+msgctxt ""
+"field:account.configuration.gift_card_account,gift_card_account_revenue:"
+msgid "Gift Card Revenue"
+msgstr "Produits de carte cadeau"
+
+msgctxt "field:product.product,gift_card:"
+msgid "Gift Card"
+msgstr "Carte cadeau"
+
+msgctxt "field:product.template,gift_card:"
+msgid "Gift Card"
+msgstr "Carte cadeau"
+
+msgctxt "field:sale.configuration,gift_card_sequence:"
+msgid "Gift Card Sequence"
+msgstr "Séquence de carte cadeau"
+
+msgctxt "field:sale.configuration.gift_card.sequence,company:"
+msgid "Company"
+msgstr "Société"
+
+msgctxt "field:sale.configuration.gift_card.sequence,gift_card_sequence:"
+msgid "Gift Card Sequence"
+msgstr "Séquence de carte cadeau"
+
+msgctxt "field:sale.gift_card,company:"
+msgid "Company"
+msgstr "Société"
+
+msgctxt "field:sale.gift_card,currency:"
+msgid "Currency"
+msgstr "Devise"
+
+msgctxt "field:sale.gift_card,currency_digits:"
+msgid "Currency Digits"
+msgstr "Décimales de la devise"
+
+msgctxt "field:sale.gift_card,number:"
+msgid "Number"
+msgstr "Numéro"
+
+msgctxt "field:sale.gift_card,origin:"
+msgid "Origin"
+msgstr "Origine"
+
+msgctxt "field:sale.gift_card,product:"
+msgid "Product"
+msgstr "Produit"
+
+msgctxt "field:sale.gift_card,spent_on:"
+msgid "Spent On"
+msgstr "Dépensé sur"
+
+msgctxt "field:sale.gift_card,value:"
+msgid "Value"
+msgstr "Valeur"
+
+msgctxt "field:sale.line,gift_card_email:"
+msgid "Gift Card Email"
+msgstr "E-mail de la carte cadeau"
+
+msgctxt "field:sale.line,gift_cards:"
+msgid "Gift Cards"
+msgstr "Cartes cadeaux"
+
+msgctxt "field:sale.line,is_gift_card:"
+msgid "Is Gift Card"
+msgstr "Est une carte cadeau"
+
+msgctxt "field:sale.line,is_gift_card_service:"
+msgid "Is Gift Card Service"
+msgstr "Est un service de carte cadeau"
+
+msgctxt "field:sale.sale,gift_cards:"
+msgid "Gift Cards"
+msgstr "Cartes cadeaux"
+
+msgctxt "field:stock.move,gift_cards:"
+msgid "Gift Cards"
+msgstr "Cartes cadeaux"
+
+msgctxt "field:stock.move,gift_cards_required:"
+msgid "Gift Cards Required"
+msgstr "Cartes cadeaux requises"
+
+msgctxt "help:sale.line,gift_card_email:"
+msgid "Leave empty for the customer email."
+msgstr "Laissez vide pour l'e-mail du client."
+
+msgctxt "model:account.configuration.gift_card_account,name:"
+msgid "Account Configuration Gift Card Account"
+msgstr "Configuration comptable Compte carte cadeau"
+
+msgctxt "model:ir.action,name:act_gift_card_form"
+msgid "Gift Cards"
+msgstr "Cartes cadeaux"
+
+msgctxt "model:ir.action,name:report_gift_card_email"
+msgid "Gift Card"
+msgstr "Carte cadeau"
+
+msgctxt "model:ir.action.act_window.domain,name:act_gift_card_form_domain_all"
+msgid "All"
+msgstr "Toutes"
+
+msgctxt ""
+"model:ir.action.act_window.domain,name:act_gift_card_form_domain_pending"
+msgid "Pending"
+msgstr "En attentes"
+
+msgctxt ""
+"model:ir.action.act_window.domain,name:act_gift_card_form_domain_sent"
+msgid "Sent"
+msgstr "Envoyées"
+
+msgctxt "model:ir.message,text:msg_gift_card_invalid_uom"
+msgid "The default UOM for the gift card \"%(template)s\" must be \"%(unit)s\"."
+msgstr ""
+"L'UdM par défaut de la carte cadeau « %(template)s » doit être « %(unit)s »."
+
+msgctxt "model:ir.message,text:msg_gift_card_move_quantity"
+msgid ""
+"To do the move \"%(move)s\", you must use exactly %(quantity)d gift card(s)."
+msgstr ""
+"Pour effectuer le mouvement « %(move)s », vous devez utiliser exactement "
+"%(quantity)d carte(s) cadeau(x)."
+
+msgctxt "model:ir.message,text:msg_gift_card_number_unique"
+msgid "The numbers for each company's gift cards must be unique."
+msgstr ""
+"Les numéros des cartes cadeaux de chaque entreprise doivent être uniques."
+
+msgctxt "model:ir.rule.group,name:rule_group_gift_card_companies"
+msgid "User in companies"
+msgstr "Utilisateur dans les sociétés"
+
+msgctxt "model:ir.sequence.type,name:sequence_type_gift_card"
+msgid "Gift Card"
+msgstr "Carte cadeau"
+
+msgctxt "model:ir.ui.menu,name:menu_gift_card_form"
+msgid "Gift Cards"
+msgstr "Cartes cadeaux"
+
+msgctxt "model:res.group,name:group_gift_card_admin"
+msgid "Gift Card Administration"
+msgstr "Administration des cartes cadeaux"
+
+msgctxt "model:sale.configuration.gift_card.sequence,name:"
+msgid "Gift Card Configuration Sequence"
+msgstr "Configuration de cartes cadeaux Séquence"
+
+msgctxt "model:sale.gift_card,name:"
+msgid "Gift Card"
+msgstr "Carte cadeau"
+
+msgctxt "report:sale.gift_card.email:"
+msgid "Gift Card"
+msgstr "Carte cadeau"
+
+msgctxt "report:sale.gift_card.email:"
+msgid "Here is your code:"
+msgstr "Voici votre code :"
+
+msgctxt "report:sale.gift_card.email:"
+msgid "You received a gift card of"
+msgstr "Vous avez reçu une carte cadeau de"
+
+msgctxt "report:sale.gift_card.email:"
+msgid "for"
+msgstr "pour"
+
+msgctxt "view:account.configuration:"
+msgid "Gift Card"
+msgstr "Carte cadeau"
+
+msgctxt "view:sale.line:"
+msgid "Gift Cards"
+msgstr "Cartes cadeaux"
diff --git a/modules/sale_gift_card/locale/hu.po b/modules/sale_gift_card/locale/hu.po
new file mode 100644
index 0000000000..bd14ca036a
--- /dev/null
+++ b/modules/sale_gift_card/locale/hu.po
@@ -0,0 +1,204 @@
+#
+msgid ""
+msgstr "Content-Type: text/plain; charset=utf-8\n"
+
+msgctxt "field:account.account.type,gift_card:"
+msgid "Gift Card"
+msgstr ""
+
+msgctxt "field:account.account.type.template,gift_card:"
+msgid "Gift Card"
+msgstr ""
+
+msgctxt "field:account.configuration,gift_card_account_expense:"
+msgid "Gift Card Expense"
+msgstr ""
+
+msgctxt "field:account.configuration,gift_card_account_revenue:"
+msgid "Gift Card Revenue"
+msgstr ""
+
+msgctxt "field:account.configuration.gift_card_account,company:"
+msgid "Company"
+msgstr ""
+
+msgctxt ""
+"field:account.configuration.gift_card_account,gift_card_account_expense:"
+msgid "Gift Card Expense"
+msgstr ""
+
+msgctxt ""
+"field:account.configuration.gift_card_account,gift_card_account_revenue:"
+msgid "Gift Card Revenue"
+msgstr ""
+
+msgctxt "field:product.product,gift_card:"
+msgid "Gift Card"
+msgstr ""
+
+msgctxt "field:product.template,gift_card:"
+msgid "Gift Card"
+msgstr ""
+
+msgctxt "field:sale.configuration,gift_card_sequence:"
+msgid "Gift Card Sequence"
+msgstr ""
+
+msgctxt "field:sale.configuration.gift_card.sequence,company:"
+msgid "Company"
+msgstr ""
+
+msgctxt "field:sale.configuration.gift_card.sequence,gift_card_sequence:"
+msgid "Gift Card Sequence"
+msgstr ""
+
+msgctxt "field:sale.gift_card,company:"
+msgid "Company"
+msgstr ""
+
+msgctxt "field:sale.gift_card,currency:"
+msgid "Currency"
+msgstr ""
+
+msgctxt "field:sale.gift_card,currency_digits:"
+msgid "Currency Digits"
+msgstr ""
+
+msgctxt "field:sale.gift_card,number:"
+msgid "Number"
+msgstr ""
+
+msgctxt "field:sale.gift_card,origin:"
+msgid "Origin"
+msgstr ""
+
+msgctxt "field:sale.gift_card,product:"
+msgid "Product"
+msgstr ""
+
+msgctxt "field:sale.gift_card,spent_on:"
+msgid "Spent On"
+msgstr ""
+
+msgctxt "field:sale.gift_card,value:"
+msgid "Value"
+msgstr ""
+
+msgctxt "field:sale.line,gift_card_email:"
+msgid "Gift Card Email"
+msgstr ""
+
+msgctxt "field:sale.line,gift_cards:"
+msgid "Gift Cards"
+msgstr ""
+
+msgctxt "field:sale.line,is_gift_card:"
+msgid "Is Gift Card"
+msgstr ""
+
+msgctxt "field:sale.line,is_gift_card_service:"
+msgid "Is Gift Card Service"
+msgstr ""
+
+msgctxt "field:sale.sale,gift_cards:"
+msgid "Gift Cards"
+msgstr ""
+
+msgctxt "field:stock.move,gift_cards:"
+msgid "Gift Cards"
+msgstr ""
+
+msgctxt "field:stock.move,gift_cards_required:"
+msgid "Gift Cards Required"
+msgstr ""
+
+msgctxt "help:sale.line,gift_card_email:"
+msgid "Leave empty for the customer email."
+msgstr ""
+
+msgctxt "model:account.configuration.gift_card_account,name:"
+msgid "Account Configuration Gift Card Account"
+msgstr ""
+
+msgctxt "model:ir.action,name:act_gift_card_form"
+msgid "Gift Cards"
+msgstr ""
+
+msgctxt "model:ir.action,name:report_gift_card_email"
+msgid "Gift Card"
+msgstr ""
+
+msgctxt "model:ir.action.act_window.domain,name:act_gift_card_form_domain_all"
+msgid "All"
+msgstr ""
+
+msgctxt ""
+"model:ir.action.act_window.domain,name:act_gift_card_form_domain_pending"
+msgid "Pending"
+msgstr ""
+
+msgctxt ""
+"model:ir.action.act_window.domain,name:act_gift_card_form_domain_sent"
+msgid "Sent"
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_gift_card_invalid_uom"
+msgid "The default UOM for the gift card \"%(template)s\" must be \"%(unit)s\"."
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_gift_card_move_quantity"
+msgid ""
+"To do the move \"%(move)s\", you must use exactly %(quantity)d gift card(s)."
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_gift_card_number_unique"
+msgid "The numbers for each company's gift cards must be unique."
+msgstr ""
+
+msgctxt "model:ir.rule.group,name:rule_group_gift_card_companies"
+msgid "User in companies"
+msgstr ""
+
+msgctxt "model:ir.sequence.type,name:sequence_type_gift_card"
+msgid "Gift Card"
+msgstr ""
+
+msgctxt "model:ir.ui.menu,name:menu_gift_card_form"
+msgid "Gift Cards"
+msgstr ""
+
+msgctxt "model:res.group,name:group_gift_card_admin"
+msgid "Gift Card Administration"
+msgstr ""
+
+msgctxt "model:sale.configuration.gift_card.sequence,name:"
+msgid "Gift Card Configuration Sequence"
+msgstr ""
+
+msgctxt "model:sale.gift_card,name:"
+msgid "Gift Card"
+msgstr ""
+
+msgctxt "report:sale.gift_card.email:"
+msgid "Gift Card"
+msgstr ""
+
+msgctxt "report:sale.gift_card.email:"
+msgid "Here is your code:"
+msgstr ""
+
+msgctxt "report:sale.gift_card.email:"
+msgid "You received a gift card of"
+msgstr ""
+
+msgctxt "report:sale.gift_card.email:"
+msgid "for"
+msgstr ""
+
+msgctxt "view:account.configuration:"
+msgid "Gift Card"
+msgstr ""
+
+msgctxt "view:sale.line:"
+msgid "Gift Cards"
+msgstr ""
diff --git a/modules/sale_gift_card/locale/id.po b/modules/sale_gift_card/locale/id.po
new file mode 100644
index 0000000000..bd14ca036a
--- /dev/null
+++ b/modules/sale_gift_card/locale/id.po
@@ -0,0 +1,204 @@
+#
+msgid ""
+msgstr "Content-Type: text/plain; charset=utf-8\n"
+
+msgctxt "field:account.account.type,gift_card:"
+msgid "Gift Card"
+msgstr ""
+
+msgctxt "field:account.account.type.template,gift_card:"
+msgid "Gift Card"
+msgstr ""
+
+msgctxt "field:account.configuration,gift_card_account_expense:"
+msgid "Gift Card Expense"
+msgstr ""
+
+msgctxt "field:account.configuration,gift_card_account_revenue:"
+msgid "Gift Card Revenue"
+msgstr ""
+
+msgctxt "field:account.configuration.gift_card_account,company:"
+msgid "Company"
+msgstr ""
+
+msgctxt ""
+"field:account.configuration.gift_card_account,gift_card_account_expense:"
+msgid "Gift Card Expense"
+msgstr ""
+
+msgctxt ""
+"field:account.configuration.gift_card_account,gift_card_account_revenue:"
+msgid "Gift Card Revenue"
+msgstr ""
+
+msgctxt "field:product.product,gift_card:"
+msgid "Gift Card"
+msgstr ""
+
+msgctxt "field:product.template,gift_card:"
+msgid "Gift Card"
+msgstr ""
+
+msgctxt "field:sale.configuration,gift_card_sequence:"
+msgid "Gift Card Sequence"
+msgstr ""
+
+msgctxt "field:sale.configuration.gift_card.sequence,company:"
+msgid "Company"
+msgstr ""
+
+msgctxt "field:sale.configuration.gift_card.sequence,gift_card_sequence:"
+msgid "Gift Card Sequence"
+msgstr ""
+
+msgctxt "field:sale.gift_card,company:"
+msgid "Company"
+msgstr ""
+
+msgctxt "field:sale.gift_card,currency:"
+msgid "Currency"
+msgstr ""
+
+msgctxt "field:sale.gift_card,currency_digits:"
+msgid "Currency Digits"
+msgstr ""
+
+msgctxt "field:sale.gift_card,number:"
+msgid "Number"
+msgstr ""
+
+msgctxt "field:sale.gift_card,origin:"
+msgid "Origin"
+msgstr ""
+
+msgctxt "field:sale.gift_card,product:"
+msgid "Product"
+msgstr ""
+
+msgctxt "field:sale.gift_card,spent_on:"
+msgid "Spent On"
+msgstr ""
+
+msgctxt "field:sale.gift_card,value:"
+msgid "Value"
+msgstr ""
+
+msgctxt "field:sale.line,gift_card_email:"
+msgid "Gift Card Email"
+msgstr ""
+
+msgctxt "field:sale.line,gift_cards:"
+msgid "Gift Cards"
+msgstr ""
+
+msgctxt "field:sale.line,is_gift_card:"
+msgid "Is Gift Card"
+msgstr ""
+
+msgctxt "field:sale.line,is_gift_card_service:"
+msgid "Is Gift Card Service"
+msgstr ""
+
+msgctxt "field:sale.sale,gift_cards:"
+msgid "Gift Cards"
+msgstr ""
+
+msgctxt "field:stock.move,gift_cards:"
+msgid "Gift Cards"
+msgstr ""
+
+msgctxt "field:stock.move,gift_cards_required:"
+msgid "Gift Cards Required"
+msgstr ""
+
+msgctxt "help:sale.line,gift_card_email:"
+msgid "Leave empty for the customer email."
+msgstr ""
+
+msgctxt "model:account.configuration.gift_card_account,name:"
+msgid "Account Configuration Gift Card Account"
+msgstr ""
+
+msgctxt "model:ir.action,name:act_gift_card_form"
+msgid "Gift Cards"
+msgstr ""
+
+msgctxt "model:ir.action,name:report_gift_card_email"
+msgid "Gift Card"
+msgstr ""
+
+msgctxt "model:ir.action.act_window.domain,name:act_gift_card_form_domain_all"
+msgid "All"
+msgstr ""
+
+msgctxt ""
+"model:ir.action.act_window.domain,name:act_gift_card_form_domain_pending"
+msgid "Pending"
+msgstr ""
+
+msgctxt ""
+"model:ir.action.act_window.domain,name:act_gift_card_form_domain_sent"
+msgid "Sent"
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_gift_card_invalid_uom"
+msgid "The default UOM for the gift card \"%(template)s\" must be \"%(unit)s\"."
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_gift_card_move_quantity"
+msgid ""
+"To do the move \"%(move)s\", you must use exactly %(quantity)d gift card(s)."
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_gift_card_number_unique"
+msgid "The numbers for each company's gift cards must be unique."
+msgstr ""
+
+msgctxt "model:ir.rule.group,name:rule_group_gift_card_companies"
+msgid "User in companies"
+msgstr ""
+
+msgctxt "model:ir.sequence.type,name:sequence_type_gift_card"
+msgid "Gift Card"
+msgstr ""
+
+msgctxt "model:ir.ui.menu,name:menu_gift_card_form"
+msgid "Gift Cards"
+msgstr ""
+
+msgctxt "model:res.group,name:group_gift_card_admin"
+msgid "Gift Card Administration"
+msgstr ""
+
+msgctxt "model:sale.configuration.gift_card.sequence,name:"
+msgid "Gift Card Configuration Sequence"
+msgstr ""
+
+msgctxt "model:sale.gift_card,name:"
+msgid "Gift Card"
+msgstr ""
+
+msgctxt "report:sale.gift_card.email:"
+msgid "Gift Card"
+msgstr ""
+
+msgctxt "report:sale.gift_card.email:"
+msgid "Here is your code:"
+msgstr ""
+
+msgctxt "report:sale.gift_card.email:"
+msgid "You received a gift card of"
+msgstr ""
+
+msgctxt "report:sale.gift_card.email:"
+msgid "for"
+msgstr ""
+
+msgctxt "view:account.configuration:"
+msgid "Gift Card"
+msgstr ""
+
+msgctxt "view:sale.line:"
+msgid "Gift Cards"
+msgstr ""
diff --git a/modules/sale_gift_card/locale/it.po b/modules/sale_gift_card/locale/it.po
new file mode 100644
index 0000000000..bd14ca036a
--- /dev/null
+++ b/modules/sale_gift_card/locale/it.po
@@ -0,0 +1,204 @@
+#
+msgid ""
+msgstr "Content-Type: text/plain; charset=utf-8\n"
+
+msgctxt "field:account.account.type,gift_card:"
+msgid "Gift Card"
+msgstr ""
+
+msgctxt "field:account.account.type.template,gift_card:"
+msgid "Gift Card"
+msgstr ""
+
+msgctxt "field:account.configuration,gift_card_account_expense:"
+msgid "Gift Card Expense"
+msgstr ""
+
+msgctxt "field:account.configuration,gift_card_account_revenue:"
+msgid "Gift Card Revenue"
+msgstr ""
+
+msgctxt "field:account.configuration.gift_card_account,company:"
+msgid "Company"
+msgstr ""
+
+msgctxt ""
+"field:account.configuration.gift_card_account,gift_card_account_expense:"
+msgid "Gift Card Expense"
+msgstr ""
+
+msgctxt ""
+"field:account.configuration.gift_card_account,gift_card_account_revenue:"
+msgid "Gift Card Revenue"
+msgstr ""
+
+msgctxt "field:product.product,gift_card:"
+msgid "Gift Card"
+msgstr ""
+
+msgctxt "field:product.template,gift_card:"
+msgid "Gift Card"
+msgstr ""
+
+msgctxt "field:sale.configuration,gift_card_sequence:"
+msgid "Gift Card Sequence"
+msgstr ""
+
+msgctxt "field:sale.configuration.gift_card.sequence,company:"
+msgid "Company"
+msgstr ""
+
+msgctxt "field:sale.configuration.gift_card.sequence,gift_card_sequence:"
+msgid "Gift Card Sequence"
+msgstr ""
+
+msgctxt "field:sale.gift_card,company:"
+msgid "Company"
+msgstr ""
+
+msgctxt "field:sale.gift_card,currency:"
+msgid "Currency"
+msgstr ""
+
+msgctxt "field:sale.gift_card,currency_digits:"
+msgid "Currency Digits"
+msgstr ""
+
+msgctxt "field:sale.gift_card,number:"
+msgid "Number"
+msgstr ""
+
+msgctxt "field:sale.gift_card,origin:"
+msgid "Origin"
+msgstr ""
+
+msgctxt "field:sale.gift_card,product:"
+msgid "Product"
+msgstr ""
+
+msgctxt "field:sale.gift_card,spent_on:"
+msgid "Spent On"
+msgstr ""
+
+msgctxt "field:sale.gift_card,value:"
+msgid "Value"
+msgstr ""
+
+msgctxt "field:sale.line,gift_card_email:"
+msgid "Gift Card Email"
+msgstr ""
+
+msgctxt "field:sale.line,gift_cards:"
+msgid "Gift Cards"
+msgstr ""
+
+msgctxt "field:sale.line,is_gift_card:"
+msgid "Is Gift Card"
+msgstr ""
+
+msgctxt "field:sale.line,is_gift_card_service:"
+msgid "Is Gift Card Service"
+msgstr ""
+
+msgctxt "field:sale.sale,gift_cards:"
+msgid "Gift Cards"
+msgstr ""
+
+msgctxt "field:stock.move,gift_cards:"
+msgid "Gift Cards"
+msgstr ""
+
+msgctxt "field:stock.move,gift_cards_required:"
+msgid "Gift Cards Required"
+msgstr ""
+
+msgctxt "help:sale.line,gift_card_email:"
+msgid "Leave empty for the customer email."
+msgstr ""
+
+msgctxt "model:account.configuration.gift_card_account,name:"
+msgid "Account Configuration Gift Card Account"
+msgstr ""
+
+msgctxt "model:ir.action,name:act_gift_card_form"
+msgid "Gift Cards"
+msgstr ""
+
+msgctxt "model:ir.action,name:report_gift_card_email"
+msgid "Gift Card"
+msgstr ""
+
+msgctxt "model:ir.action.act_window.domain,name:act_gift_card_form_domain_all"
+msgid "All"
+msgstr ""
+
+msgctxt ""
+"model:ir.action.act_window.domain,name:act_gift_card_form_domain_pending"
+msgid "Pending"
+msgstr ""
+
+msgctxt ""
+"model:ir.action.act_window.domain,name:act_gift_card_form_domain_sent"
+msgid "Sent"
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_gift_card_invalid_uom"
+msgid "The default UOM for the gift card \"%(template)s\" must be \"%(unit)s\"."
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_gift_card_move_quantity"
+msgid ""
+"To do the move \"%(move)s\", you must use exactly %(quantity)d gift card(s)."
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_gift_card_number_unique"
+msgid "The numbers for each company's gift cards must be unique."
+msgstr ""
+
+msgctxt "model:ir.rule.group,name:rule_group_gift_card_companies"
+msgid "User in companies"
+msgstr ""
+
+msgctxt "model:ir.sequence.type,name:sequence_type_gift_card"
+msgid "Gift Card"
+msgstr ""
+
+msgctxt "model:ir.ui.menu,name:menu_gift_card_form"
+msgid "Gift Cards"
+msgstr ""
+
+msgctxt "model:res.group,name:group_gift_card_admin"
+msgid "Gift Card Administration"
+msgstr ""
+
+msgctxt "model:sale.configuration.gift_card.sequence,name:"
+msgid "Gift Card Configuration Sequence"
+msgstr ""
+
+msgctxt "model:sale.gift_card,name:"
+msgid "Gift Card"
+msgstr ""
+
+msgctxt "report:sale.gift_card.email:"
+msgid "Gift Card"
+msgstr ""
+
+msgctxt "report:sale.gift_card.email:"
+msgid "Here is your code:"
+msgstr ""
+
+msgctxt "report:sale.gift_card.email:"
+msgid "You received a gift card of"
+msgstr ""
+
+msgctxt "report:sale.gift_card.email:"
+msgid "for"
+msgstr ""
+
+msgctxt "view:account.configuration:"
+msgid "Gift Card"
+msgstr ""
+
+msgctxt "view:sale.line:"
+msgid "Gift Cards"
+msgstr ""
diff --git a/modules/sale_gift_card/locale/lo.po b/modules/sale_gift_card/locale/lo.po
new file mode 100644
index 0000000000..bd14ca036a
--- /dev/null
+++ b/modules/sale_gift_card/locale/lo.po
@@ -0,0 +1,204 @@
+#
+msgid ""
+msgstr "Content-Type: text/plain; charset=utf-8\n"
+
+msgctxt "field:account.account.type,gift_card:"
+msgid "Gift Card"
+msgstr ""
+
+msgctxt "field:account.account.type.template,gift_card:"
+msgid "Gift Card"
+msgstr ""
+
+msgctxt "field:account.configuration,gift_card_account_expense:"
+msgid "Gift Card Expense"
+msgstr ""
+
+msgctxt "field:account.configuration,gift_card_account_revenue:"
+msgid "Gift Card Revenue"
+msgstr ""
+
+msgctxt "field:account.configuration.gift_card_account,company:"
+msgid "Company"
+msgstr ""
+
+msgctxt ""
+"field:account.configuration.gift_card_account,gift_card_account_expense:"
+msgid "Gift Card Expense"
+msgstr ""
+
+msgctxt ""
+"field:account.configuration.gift_card_account,gift_card_account_revenue:"
+msgid "Gift Card Revenue"
+msgstr ""
+
+msgctxt "field:product.product,gift_card:"
+msgid "Gift Card"
+msgstr ""
+
+msgctxt "field:product.template,gift_card:"
+msgid "Gift Card"
+msgstr ""
+
+msgctxt "field:sale.configuration,gift_card_sequence:"
+msgid "Gift Card Sequence"
+msgstr ""
+
+msgctxt "field:sale.configuration.gift_card.sequence,company:"
+msgid "Company"
+msgstr ""
+
+msgctxt "field:sale.configuration.gift_card.sequence,gift_card_sequence:"
+msgid "Gift Card Sequence"
+msgstr ""
+
+msgctxt "field:sale.gift_card,company:"
+msgid "Company"
+msgstr ""
+
+msgctxt "field:sale.gift_card,currency:"
+msgid "Currency"
+msgstr ""
+
+msgctxt "field:sale.gift_card,currency_digits:"
+msgid "Currency Digits"
+msgstr ""
+
+msgctxt "field:sale.gift_card,number:"
+msgid "Number"
+msgstr ""
+
+msgctxt "field:sale.gift_card,origin:"
+msgid "Origin"
+msgstr ""
+
+msgctxt "field:sale.gift_card,product:"
+msgid "Product"
+msgstr ""
+
+msgctxt "field:sale.gift_card,spent_on:"
+msgid "Spent On"
+msgstr ""
+
+msgctxt "field:sale.gift_card,value:"
+msgid "Value"
+msgstr ""
+
+msgctxt "field:sale.line,gift_card_email:"
+msgid "Gift Card Email"
+msgstr ""
+
+msgctxt "field:sale.line,gift_cards:"
+msgid "Gift Cards"
+msgstr ""
+
+msgctxt "field:sale.line,is_gift_card:"
+msgid "Is Gift Card"
+msgstr ""
+
+msgctxt "field:sale.line,is_gift_card_service:"
+msgid "Is Gift Card Service"
+msgstr ""
+
+msgctxt "field:sale.sale,gift_cards:"
+msgid "Gift Cards"
+msgstr ""
+
+msgctxt "field:stock.move,gift_cards:"
+msgid "Gift Cards"
+msgstr ""
+
+msgctxt "field:stock.move,gift_cards_required:"
+msgid "Gift Cards Required"
+msgstr ""
+
+msgctxt "help:sale.line,gift_card_email:"
+msgid "Leave empty for the customer email."
+msgstr ""
+
+msgctxt "model:account.configuration.gift_card_account,name:"
+msgid "Account Configuration Gift Card Account"
+msgstr ""
+
+msgctxt "model:ir.action,name:act_gift_card_form"
+msgid "Gift Cards"
+msgstr ""
+
+msgctxt "model:ir.action,name:report_gift_card_email"
+msgid "Gift Card"
+msgstr ""
+
+msgctxt "model:ir.action.act_window.domain,name:act_gift_card_form_domain_all"
+msgid "All"
+msgstr ""
+
+msgctxt ""
+"model:ir.action.act_window.domain,name:act_gift_card_form_domain_pending"
+msgid "Pending"
+msgstr ""
+
+msgctxt ""
+"model:ir.action.act_window.domain,name:act_gift_card_form_domain_sent"
+msgid "Sent"
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_gift_card_invalid_uom"
+msgid "The default UOM for the gift card \"%(template)s\" must be \"%(unit)s\"."
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_gift_card_move_quantity"
+msgid ""
+"To do the move \"%(move)s\", you must use exactly %(quantity)d gift card(s)."
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_gift_card_number_unique"
+msgid "The numbers for each company's gift cards must be unique."
+msgstr ""
+
+msgctxt "model:ir.rule.group,name:rule_group_gift_card_companies"
+msgid "User in companies"
+msgstr ""
+
+msgctxt "model:ir.sequence.type,name:sequence_type_gift_card"
+msgid "Gift Card"
+msgstr ""
+
+msgctxt "model:ir.ui.menu,name:menu_gift_card_form"
+msgid "Gift Cards"
+msgstr ""
+
+msgctxt "model:res.group,name:group_gift_card_admin"
+msgid "Gift Card Administration"
+msgstr ""
+
+msgctxt "model:sale.configuration.gift_card.sequence,name:"
+msgid "Gift Card Configuration Sequence"
+msgstr ""
+
+msgctxt "model:sale.gift_card,name:"
+msgid "Gift Card"
+msgstr ""
+
+msgctxt "report:sale.gift_card.email:"
+msgid "Gift Card"
+msgstr ""
+
+msgctxt "report:sale.gift_card.email:"
+msgid "Here is your code:"
+msgstr ""
+
+msgctxt "report:sale.gift_card.email:"
+msgid "You received a gift card of"
+msgstr ""
+
+msgctxt "report:sale.gift_card.email:"
+msgid "for"
+msgstr ""
+
+msgctxt "view:account.configuration:"
+msgid "Gift Card"
+msgstr ""
+
+msgctxt "view:sale.line:"
+msgid "Gift Cards"
+msgstr ""
diff --git a/modules/sale_gift_card/locale/lt.po b/modules/sale_gift_card/locale/lt.po
new file mode 100644
index 0000000000..bd14ca036a
--- /dev/null
+++ b/modules/sale_gift_card/locale/lt.po
@@ -0,0 +1,204 @@
+#
+msgid ""
+msgstr "Content-Type: text/plain; charset=utf-8\n"
+
+msgctxt "field:account.account.type,gift_card:"
+msgid "Gift Card"
+msgstr ""
+
+msgctxt "field:account.account.type.template,gift_card:"
+msgid "Gift Card"
+msgstr ""
+
+msgctxt "field:account.configuration,gift_card_account_expense:"
+msgid "Gift Card Expense"
+msgstr ""
+
+msgctxt "field:account.configuration,gift_card_account_revenue:"
+msgid "Gift Card Revenue"
+msgstr ""
+
+msgctxt "field:account.configuration.gift_card_account,company:"
+msgid "Company"
+msgstr ""
+
+msgctxt ""
+"field:account.configuration.gift_card_account,gift_card_account_expense:"
+msgid "Gift Card Expense"
+msgstr ""
+
+msgctxt ""
+"field:account.configuration.gift_card_account,gift_card_account_revenue:"
+msgid "Gift Card Revenue"
+msgstr ""
+
+msgctxt "field:product.product,gift_card:"
+msgid "Gift Card"
+msgstr ""
+
+msgctxt "field:product.template,gift_card:"
+msgid "Gift Card"
+msgstr ""
+
+msgctxt "field:sale.configuration,gift_card_sequence:"
+msgid "Gift Card Sequence"
+msgstr ""
+
+msgctxt "field:sale.configuration.gift_card.sequence,company:"
+msgid "Company"
+msgstr ""
+
+msgctxt "field:sale.configuration.gift_card.sequence,gift_card_sequence:"
+msgid "Gift Card Sequence"
+msgstr ""
+
+msgctxt "field:sale.gift_card,company:"
+msgid "Company"
+msgstr ""
+
+msgctxt "field:sale.gift_card,currency:"
+msgid "Currency"
+msgstr ""
+
+msgctxt "field:sale.gift_card,currency_digits:"
+msgid "Currency Digits"
+msgstr ""
+
+msgctxt "field:sale.gift_card,number:"
+msgid "Number"
+msgstr ""
+
+msgctxt "field:sale.gift_card,origin:"
+msgid "Origin"
+msgstr ""
+
+msgctxt "field:sale.gift_card,product:"
+msgid "Product"
+msgstr ""
+
+msgctxt "field:sale.gift_card,spent_on:"
+msgid "Spent On"
+msgstr ""
+
+msgctxt "field:sale.gift_card,value:"
+msgid "Value"
+msgstr ""
+
+msgctxt "field:sale.line,gift_card_email:"
+msgid "Gift Card Email"
+msgstr ""
+
+msgctxt "field:sale.line,gift_cards:"
+msgid "Gift Cards"
+msgstr ""
+
+msgctxt "field:sale.line,is_gift_card:"
+msgid "Is Gift Card"
+msgstr ""
+
+msgctxt "field:sale.line,is_gift_card_service:"
+msgid "Is Gift Card Service"
+msgstr ""
+
+msgctxt "field:sale.sale,gift_cards:"
+msgid "Gift Cards"
+msgstr ""
+
+msgctxt "field:stock.move,gift_cards:"
+msgid "Gift Cards"
+msgstr ""
+
+msgctxt "field:stock.move,gift_cards_required:"
+msgid "Gift Cards Required"
+msgstr ""
+
+msgctxt "help:sale.line,gift_card_email:"
+msgid "Leave empty for the customer email."
+msgstr ""
+
+msgctxt "model:account.configuration.gift_card_account,name:"
+msgid "Account Configuration Gift Card Account"
+msgstr ""
+
+msgctxt "model:ir.action,name:act_gift_card_form"
+msgid "Gift Cards"
+msgstr ""
+
+msgctxt "model:ir.action,name:report_gift_card_email"
+msgid "Gift Card"
+msgstr ""
+
+msgctxt "model:ir.action.act_window.domain,name:act_gift_card_form_domain_all"
+msgid "All"
+msgstr ""
+
+msgctxt ""
+"model:ir.action.act_window.domain,name:act_gift_card_form_domain_pending"
+msgid "Pending"
+msgstr ""
+
+msgctxt ""
+"model:ir.action.act_window.domain,name:act_gift_card_form_domain_sent"
+msgid "Sent"
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_gift_card_invalid_uom"
+msgid "The default UOM for the gift card \"%(template)s\" must be \"%(unit)s\"."
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_gift_card_move_quantity"
+msgid ""
+"To do the move \"%(move)s\", you must use exactly %(quantity)d gift card(s)."
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_gift_card_number_unique"
+msgid "The numbers for each company's gift cards must be unique."
+msgstr ""
+
+msgctxt "model:ir.rule.group,name:rule_group_gift_card_companies"
+msgid "User in companies"
+msgstr ""
+
+msgctxt "model:ir.sequence.type,name:sequence_type_gift_card"
+msgid "Gift Card"
+msgstr ""
+
+msgctxt "model:ir.ui.menu,name:menu_gift_card_form"
+msgid "Gift Cards"
+msgstr ""
+
+msgctxt "model:res.group,name:group_gift_card_admin"
+msgid "Gift Card Administration"
+msgstr ""
+
+msgctxt "model:sale.configuration.gift_card.sequence,name:"
+msgid "Gift Card Configuration Sequence"
+msgstr ""
+
+msgctxt "model:sale.gift_card,name:"
+msgid "Gift Card"
+msgstr ""
+
+msgctxt "report:sale.gift_card.email:"
+msgid "Gift Card"
+msgstr ""
+
+msgctxt "report:sale.gift_card.email:"
+msgid "Here is your code:"
+msgstr ""
+
+msgctxt "report:sale.gift_card.email:"
+msgid "You received a gift card of"
+msgstr ""
+
+msgctxt "report:sale.gift_card.email:"
+msgid "for"
+msgstr ""
+
+msgctxt "view:account.configuration:"
+msgid "Gift Card"
+msgstr ""
+
+msgctxt "view:sale.line:"
+msgid "Gift Cards"
+msgstr ""
diff --git a/modules/sale_gift_card/locale/nl.po b/modules/sale_gift_card/locale/nl.po
new file mode 100644
index 0000000000..bd14ca036a
--- /dev/null
+++ b/modules/sale_gift_card/locale/nl.po
@@ -0,0 +1,204 @@
+#
+msgid ""
+msgstr "Content-Type: text/plain; charset=utf-8\n"
+
+msgctxt "field:account.account.type,gift_card:"
+msgid "Gift Card"
+msgstr ""
+
+msgctxt "field:account.account.type.template,gift_card:"
+msgid "Gift Card"
+msgstr ""
+
+msgctxt "field:account.configuration,gift_card_account_expense:"
+msgid "Gift Card Expense"
+msgstr ""
+
+msgctxt "field:account.configuration,gift_card_account_revenue:"
+msgid "Gift Card Revenue"
+msgstr ""
+
+msgctxt "field:account.configuration.gift_card_account,company:"
+msgid "Company"
+msgstr ""
+
+msgctxt ""
+"field:account.configuration.gift_card_account,gift_card_account_expense:"
+msgid "Gift Card Expense"
+msgstr ""
+
+msgctxt ""
+"field:account.configuration.gift_card_account,gift_card_account_revenue:"
+msgid "Gift Card Revenue"
+msgstr ""
+
+msgctxt "field:product.product,gift_card:"
+msgid "Gift Card"
+msgstr ""
+
+msgctxt "field:product.template,gift_card:"
+msgid "Gift Card"
+msgstr ""
+
+msgctxt "field:sale.configuration,gift_card_sequence:"
+msgid "Gift Card Sequence"
+msgstr ""
+
+msgctxt "field:sale.configuration.gift_card.sequence,company:"
+msgid "Company"
+msgstr ""
+
+msgctxt "field:sale.configuration.gift_card.sequence,gift_card_sequence:"
+msgid "Gift Card Sequence"
+msgstr ""
+
+msgctxt "field:sale.gift_card,company:"
+msgid "Company"
+msgstr ""
+
+msgctxt "field:sale.gift_card,currency:"
+msgid "Currency"
+msgstr ""
+
+msgctxt "field:sale.gift_card,currency_digits:"
+msgid "Currency Digits"
+msgstr ""
+
+msgctxt "field:sale.gift_card,number:"
+msgid "Number"
+msgstr ""
+
+msgctxt "field:sale.gift_card,origin:"
+msgid "Origin"
+msgstr ""
+
+msgctxt "field:sale.gift_card,product:"
+msgid "Product"
+msgstr ""
+
+msgctxt "field:sale.gift_card,spent_on:"
+msgid "Spent On"
+msgstr ""
+
+msgctxt "field:sale.gift_card,value:"
+msgid "Value"
+msgstr ""
+
+msgctxt "field:sale.line,gift_card_email:"
+msgid "Gift Card Email"
+msgstr ""
+
+msgctxt "field:sale.line,gift_cards:"
+msgid "Gift Cards"
+msgstr ""
+
+msgctxt "field:sale.line,is_gift_card:"
+msgid "Is Gift Card"
+msgstr ""
+
+msgctxt "field:sale.line,is_gift_card_service:"
+msgid "Is Gift Card Service"
+msgstr ""
+
+msgctxt "field:sale.sale,gift_cards:"
+msgid "Gift Cards"
+msgstr ""
+
+msgctxt "field:stock.move,gift_cards:"
+msgid "Gift Cards"
+msgstr ""
+
+msgctxt "field:stock.move,gift_cards_required:"
+msgid "Gift Cards Required"
+msgstr ""
+
+msgctxt "help:sale.line,gift_card_email:"
+msgid "Leave empty for the customer email."
+msgstr ""
+
+msgctxt "model:account.configuration.gift_card_account,name:"
+msgid "Account Configuration Gift Card Account"
+msgstr ""
+
+msgctxt "model:ir.action,name:act_gift_card_form"
+msgid "Gift Cards"
+msgstr ""
+
+msgctxt "model:ir.action,name:report_gift_card_email"
+msgid "Gift Card"
+msgstr ""
+
+msgctxt "model:ir.action.act_window.domain,name:act_gift_card_form_domain_all"
+msgid "All"
+msgstr ""
+
+msgctxt ""
+"model:ir.action.act_window.domain,name:act_gift_card_form_domain_pending"
+msgid "Pending"
+msgstr ""
+
+msgctxt ""
+"model:ir.action.act_window.domain,name:act_gift_card_form_domain_sent"
+msgid "Sent"
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_gift_card_invalid_uom"
+msgid "The default UOM for the gift card \"%(template)s\" must be \"%(unit)s\"."
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_gift_card_move_quantity"
+msgid ""
+"To do the move \"%(move)s\", you must use exactly %(quantity)d gift card(s)."
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_gift_card_number_unique"
+msgid "The numbers for each company's gift cards must be unique."
+msgstr ""
+
+msgctxt "model:ir.rule.group,name:rule_group_gift_card_companies"
+msgid "User in companies"
+msgstr ""
+
+msgctxt "model:ir.sequence.type,name:sequence_type_gift_card"
+msgid "Gift Card"
+msgstr ""
+
+msgctxt "model:ir.ui.menu,name:menu_gift_card_form"
+msgid "Gift Cards"
+msgstr ""
+
+msgctxt "model:res.group,name:group_gift_card_admin"
+msgid "Gift Card Administration"
+msgstr ""
+
+msgctxt "model:sale.configuration.gift_card.sequence,name:"
+msgid "Gift Card Configuration Sequence"
+msgstr ""
+
+msgctxt "model:sale.gift_card,name:"
+msgid "Gift Card"
+msgstr ""
+
+msgctxt "report:sale.gift_card.email:"
+msgid "Gift Card"
+msgstr ""
+
+msgctxt "report:sale.gift_card.email:"
+msgid "Here is your code:"
+msgstr ""
+
+msgctxt "report:sale.gift_card.email:"
+msgid "You received a gift card of"
+msgstr ""
+
+msgctxt "report:sale.gift_card.email:"
+msgid "for"
+msgstr ""
+
+msgctxt "view:account.configuration:"
+msgid "Gift Card"
+msgstr ""
+
+msgctxt "view:sale.line:"
+msgid "Gift Cards"
+msgstr ""
diff --git a/modules/sale_gift_card/locale/pl.po b/modules/sale_gift_card/locale/pl.po
new file mode 100644
index 0000000000..bd14ca036a
--- /dev/null
+++ b/modules/sale_gift_card/locale/pl.po
@@ -0,0 +1,204 @@
+#
+msgid ""
+msgstr "Content-Type: text/plain; charset=utf-8\n"
+
+msgctxt "field:account.account.type,gift_card:"
+msgid "Gift Card"
+msgstr ""
+
+msgctxt "field:account.account.type.template,gift_card:"
+msgid "Gift Card"
+msgstr ""
+
+msgctxt "field:account.configuration,gift_card_account_expense:"
+msgid "Gift Card Expense"
+msgstr ""
+
+msgctxt "field:account.configuration,gift_card_account_revenue:"
+msgid "Gift Card Revenue"
+msgstr ""
+
+msgctxt "field:account.configuration.gift_card_account,company:"
+msgid "Company"
+msgstr ""
+
+msgctxt ""
+"field:account.configuration.gift_card_account,gift_card_account_expense:"
+msgid "Gift Card Expense"
+msgstr ""
+
+msgctxt ""
+"field:account.configuration.gift_card_account,gift_card_account_revenue:"
+msgid "Gift Card Revenue"
+msgstr ""
+
+msgctxt "field:product.product,gift_card:"
+msgid "Gift Card"
+msgstr ""
+
+msgctxt "field:product.template,gift_card:"
+msgid "Gift Card"
+msgstr ""
+
+msgctxt "field:sale.configuration,gift_card_sequence:"
+msgid "Gift Card Sequence"
+msgstr ""
+
+msgctxt "field:sale.configuration.gift_card.sequence,company:"
+msgid "Company"
+msgstr ""
+
+msgctxt "field:sale.configuration.gift_card.sequence,gift_card_sequence:"
+msgid "Gift Card Sequence"
+msgstr ""
+
+msgctxt "field:sale.gift_card,company:"
+msgid "Company"
+msgstr ""
+
+msgctxt "field:sale.gift_card,currency:"
+msgid "Currency"
+msgstr ""
+
+msgctxt "field:sale.gift_card,currency_digits:"
+msgid "Currency Digits"
+msgstr ""
+
+msgctxt "field:sale.gift_card,number:"
+msgid "Number"
+msgstr ""
+
+msgctxt "field:sale.gift_card,origin:"
+msgid "Origin"
+msgstr ""
+
+msgctxt "field:sale.gift_card,product:"
+msgid "Product"
+msgstr ""
+
+msgctxt "field:sale.gift_card,spent_on:"
+msgid "Spent On"
+msgstr ""
+
+msgctxt "field:sale.gift_card,value:"
+msgid "Value"
+msgstr ""
+
+msgctxt "field:sale.line,gift_card_email:"
+msgid "Gift Card Email"
+msgstr ""
+
+msgctxt "field:sale.line,gift_cards:"
+msgid "Gift Cards"
+msgstr ""
+
+msgctxt "field:sale.line,is_gift_card:"
+msgid "Is Gift Card"
+msgstr ""
+
+msgctxt "field:sale.line,is_gift_card_service:"
+msgid "Is Gift Card Service"
+msgstr ""
+
+msgctxt "field:sale.sale,gift_cards:"
+msgid "Gift Cards"
+msgstr ""
+
+msgctxt "field:stock.move,gift_cards:"
+msgid "Gift Cards"
+msgstr ""
+
+msgctxt "field:stock.move,gift_cards_required:"
+msgid "Gift Cards Required"
+msgstr ""
+
+msgctxt "help:sale.line,gift_card_email:"
+msgid "Leave empty for the customer email."
+msgstr ""
+
+msgctxt "model:account.configuration.gift_card_account,name:"
+msgid "Account Configuration Gift Card Account"
+msgstr ""
+
+msgctxt "model:ir.action,name:act_gift_card_form"
+msgid "Gift Cards"
+msgstr ""
+
+msgctxt "model:ir.action,name:report_gift_card_email"
+msgid "Gift Card"
+msgstr ""
+
+msgctxt "model:ir.action.act_window.domain,name:act_gift_card_form_domain_all"
+msgid "All"
+msgstr ""
+
+msgctxt ""
+"model:ir.action.act_window.domain,name:act_gift_card_form_domain_pending"
+msgid "Pending"
+msgstr ""
+
+msgctxt ""
+"model:ir.action.act_window.domain,name:act_gift_card_form_domain_sent"
+msgid "Sent"
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_gift_card_invalid_uom"
+msgid "The default UOM for the gift card \"%(template)s\" must be \"%(unit)s\"."
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_gift_card_move_quantity"
+msgid ""
+"To do the move \"%(move)s\", you must use exactly %(quantity)d gift card(s)."
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_gift_card_number_unique"
+msgid "The numbers for each company's gift cards must be unique."
+msgstr ""
+
+msgctxt "model:ir.rule.group,name:rule_group_gift_card_companies"
+msgid "User in companies"
+msgstr ""
+
+msgctxt "model:ir.sequence.type,name:sequence_type_gift_card"
+msgid "Gift Card"
+msgstr ""
+
+msgctxt "model:ir.ui.menu,name:menu_gift_card_form"
+msgid "Gift Cards"
+msgstr ""
+
+msgctxt "model:res.group,name:group_gift_card_admin"
+msgid "Gift Card Administration"
+msgstr ""
+
+msgctxt "model:sale.configuration.gift_card.sequence,name:"
+msgid "Gift Card Configuration Sequence"
+msgstr ""
+
+msgctxt "model:sale.gift_card,name:"
+msgid "Gift Card"
+msgstr ""
+
+msgctxt "report:sale.gift_card.email:"
+msgid "Gift Card"
+msgstr ""
+
+msgctxt "report:sale.gift_card.email:"
+msgid "Here is your code:"
+msgstr ""
+
+msgctxt "report:sale.gift_card.email:"
+msgid "You received a gift card of"
+msgstr ""
+
+msgctxt "report:sale.gift_card.email:"
+msgid "for"
+msgstr ""
+
+msgctxt "view:account.configuration:"
+msgid "Gift Card"
+msgstr ""
+
+msgctxt "view:sale.line:"
+msgid "Gift Cards"
+msgstr ""
diff --git a/modules/sale_gift_card/locale/pt.po b/modules/sale_gift_card/locale/pt.po
new file mode 100644
index 0000000000..bd14ca036a
--- /dev/null
+++ b/modules/sale_gift_card/locale/pt.po
@@ -0,0 +1,204 @@
+#
+msgid ""
+msgstr "Content-Type: text/plain; charset=utf-8\n"
+
+msgctxt "field:account.account.type,gift_card:"
+msgid "Gift Card"
+msgstr ""
+
+msgctxt "field:account.account.type.template,gift_card:"
+msgid "Gift Card"
+msgstr ""
+
+msgctxt "field:account.configuration,gift_card_account_expense:"
+msgid "Gift Card Expense"
+msgstr ""
+
+msgctxt "field:account.configuration,gift_card_account_revenue:"
+msgid "Gift Card Revenue"
+msgstr ""
+
+msgctxt "field:account.configuration.gift_card_account,company:"
+msgid "Company"
+msgstr ""
+
+msgctxt ""
+"field:account.configuration.gift_card_account,gift_card_account_expense:"
+msgid "Gift Card Expense"
+msgstr ""
+
+msgctxt ""
+"field:account.configuration.gift_card_account,gift_card_account_revenue:"
+msgid "Gift Card Revenue"
+msgstr ""
+
+msgctxt "field:product.product,gift_card:"
+msgid "Gift Card"
+msgstr ""
+
+msgctxt "field:product.template,gift_card:"
+msgid "Gift Card"
+msgstr ""
+
+msgctxt "field:sale.configuration,gift_card_sequence:"
+msgid "Gift Card Sequence"
+msgstr ""
+
+msgctxt "field:sale.configuration.gift_card.sequence,company:"
+msgid "Company"
+msgstr ""
+
+msgctxt "field:sale.configuration.gift_card.sequence,gift_card_sequence:"
+msgid "Gift Card Sequence"
+msgstr ""
+
+msgctxt "field:sale.gift_card,company:"
+msgid "Company"
+msgstr ""
+
+msgctxt "field:sale.gift_card,currency:"
+msgid "Currency"
+msgstr ""
+
+msgctxt "field:sale.gift_card,currency_digits:"
+msgid "Currency Digits"
+msgstr ""
+
+msgctxt "field:sale.gift_card,number:"
+msgid "Number"
+msgstr ""
+
+msgctxt "field:sale.gift_card,origin:"
+msgid "Origin"
+msgstr ""
+
+msgctxt "field:sale.gift_card,product:"
+msgid "Product"
+msgstr ""
+
+msgctxt "field:sale.gift_card,spent_on:"
+msgid "Spent On"
+msgstr ""
+
+msgctxt "field:sale.gift_card,value:"
+msgid "Value"
+msgstr ""
+
+msgctxt "field:sale.line,gift_card_email:"
+msgid "Gift Card Email"
+msgstr ""
+
+msgctxt "field:sale.line,gift_cards:"
+msgid "Gift Cards"
+msgstr ""
+
+msgctxt "field:sale.line,is_gift_card:"
+msgid "Is Gift Card"
+msgstr ""
+
+msgctxt "field:sale.line,is_gift_card_service:"
+msgid "Is Gift Card Service"
+msgstr ""
+
+msgctxt "field:sale.sale,gift_cards:"
+msgid "Gift Cards"
+msgstr ""
+
+msgctxt "field:stock.move,gift_cards:"
+msgid "Gift Cards"
+msgstr ""
+
+msgctxt "field:stock.move,gift_cards_required:"
+msgid "Gift Cards Required"
+msgstr ""
+
+msgctxt "help:sale.line,gift_card_email:"
+msgid "Leave empty for the customer email."
+msgstr ""
+
+msgctxt "model:account.configuration.gift_card_account,name:"
+msgid "Account Configuration Gift Card Account"
+msgstr ""
+
+msgctxt "model:ir.action,name:act_gift_card_form"
+msgid "Gift Cards"
+msgstr ""
+
+msgctxt "model:ir.action,name:report_gift_card_email"
+msgid "Gift Card"
+msgstr ""
+
+msgctxt "model:ir.action.act_window.domain,name:act_gift_card_form_domain_all"
+msgid "All"
+msgstr ""
+
+msgctxt ""
+"model:ir.action.act_window.domain,name:act_gift_card_form_domain_pending"
+msgid "Pending"
+msgstr ""
+
+msgctxt ""
+"model:ir.action.act_window.domain,name:act_gift_card_form_domain_sent"
+msgid "Sent"
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_gift_card_invalid_uom"
+msgid "The default UOM for the gift card \"%(template)s\" must be \"%(unit)s\"."
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_gift_card_move_quantity"
+msgid ""
+"To do the move \"%(move)s\", you must use exactly %(quantity)d gift card(s)."
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_gift_card_number_unique"
+msgid "The numbers for each company's gift cards must be unique."
+msgstr ""
+
+msgctxt "model:ir.rule.group,name:rule_group_gift_card_companies"
+msgid "User in companies"
+msgstr ""
+
+msgctxt "model:ir.sequence.type,name:sequence_type_gift_card"
+msgid "Gift Card"
+msgstr ""
+
+msgctxt "model:ir.ui.menu,name:menu_gift_card_form"
+msgid "Gift Cards"
+msgstr ""
+
+msgctxt "model:res.group,name:group_gift_card_admin"
+msgid "Gift Card Administration"
+msgstr ""
+
+msgctxt "model:sale.configuration.gift_card.sequence,name:"
+msgid "Gift Card Configuration Sequence"
+msgstr ""
+
+msgctxt "model:sale.gift_card,name:"
+msgid "Gift Card"
+msgstr ""
+
+msgctxt "report:sale.gift_card.email:"
+msgid "Gift Card"
+msgstr ""
+
+msgctxt "report:sale.gift_card.email:"
+msgid "Here is your code:"
+msgstr ""
+
+msgctxt "report:sale.gift_card.email:"
+msgid "You received a gift card of"
+msgstr ""
+
+msgctxt "report:sale.gift_card.email:"
+msgid "for"
+msgstr ""
+
+msgctxt "view:account.configuration:"
+msgid "Gift Card"
+msgstr ""
+
+msgctxt "view:sale.line:"
+msgid "Gift Cards"
+msgstr ""
diff --git a/modules/sale_gift_card/locale/ro.po b/modules/sale_gift_card/locale/ro.po
new file mode 100644
index 0000000000..bd14ca036a
--- /dev/null
+++ b/modules/sale_gift_card/locale/ro.po
@@ -0,0 +1,204 @@
+#
+msgid ""
+msgstr "Content-Type: text/plain; charset=utf-8\n"
+
+msgctxt "field:account.account.type,gift_card:"
+msgid "Gift Card"
+msgstr ""
+
+msgctxt "field:account.account.type.template,gift_card:"
+msgid "Gift Card"
+msgstr ""
+
+msgctxt "field:account.configuration,gift_card_account_expense:"
+msgid "Gift Card Expense"
+msgstr ""
+
+msgctxt "field:account.configuration,gift_card_account_revenue:"
+msgid "Gift Card Revenue"
+msgstr ""
+
+msgctxt "field:account.configuration.gift_card_account,company:"
+msgid "Company"
+msgstr ""
+
+msgctxt ""
+"field:account.configuration.gift_card_account,gift_card_account_expense:"
+msgid "Gift Card Expense"
+msgstr ""
+
+msgctxt ""
+"field:account.configuration.gift_card_account,gift_card_account_revenue:"
+msgid "Gift Card Revenue"
+msgstr ""
+
+msgctxt "field:product.product,gift_card:"
+msgid "Gift Card"
+msgstr ""
+
+msgctxt "field:product.template,gift_card:"
+msgid "Gift Card"
+msgstr ""
+
+msgctxt "field:sale.configuration,gift_card_sequence:"
+msgid "Gift Card Sequence"
+msgstr ""
+
+msgctxt "field:sale.configuration.gift_card.sequence,company:"
+msgid "Company"
+msgstr ""
+
+msgctxt "field:sale.configuration.gift_card.sequence,gift_card_sequence:"
+msgid "Gift Card Sequence"
+msgstr ""
+
+msgctxt "field:sale.gift_card,company:"
+msgid "Company"
+msgstr ""
+
+msgctxt "field:sale.gift_card,currency:"
+msgid "Currency"
+msgstr ""
+
+msgctxt "field:sale.gift_card,currency_digits:"
+msgid "Currency Digits"
+msgstr ""
+
+msgctxt "field:sale.gift_card,number:"
+msgid "Number"
+msgstr ""
+
+msgctxt "field:sale.gift_card,origin:"
+msgid "Origin"
+msgstr ""
+
+msgctxt "field:sale.gift_card,product:"
+msgid "Product"
+msgstr ""
+
+msgctxt "field:sale.gift_card,spent_on:"
+msgid "Spent On"
+msgstr ""
+
+msgctxt "field:sale.gift_card,value:"
+msgid "Value"
+msgstr ""
+
+msgctxt "field:sale.line,gift_card_email:"
+msgid "Gift Card Email"
+msgstr ""
+
+msgctxt "field:sale.line,gift_cards:"
+msgid "Gift Cards"
+msgstr ""
+
+msgctxt "field:sale.line,is_gift_card:"
+msgid "Is Gift Card"
+msgstr ""
+
+msgctxt "field:sale.line,is_gift_card_service:"
+msgid "Is Gift Card Service"
+msgstr ""
+
+msgctxt "field:sale.sale,gift_cards:"
+msgid "Gift Cards"
+msgstr ""
+
+msgctxt "field:stock.move,gift_cards:"
+msgid "Gift Cards"
+msgstr ""
+
+msgctxt "field:stock.move,gift_cards_required:"
+msgid "Gift Cards Required"
+msgstr ""
+
+msgctxt "help:sale.line,gift_card_email:"
+msgid "Leave empty for the customer email."
+msgstr ""
+
+msgctxt "model:account.configuration.gift_card_account,name:"
+msgid "Account Configuration Gift Card Account"
+msgstr ""
+
+msgctxt "model:ir.action,name:act_gift_card_form"
+msgid "Gift Cards"
+msgstr ""
+
+msgctxt "model:ir.action,name:report_gift_card_email"
+msgid "Gift Card"
+msgstr ""
+
+msgctxt "model:ir.action.act_window.domain,name:act_gift_card_form_domain_all"
+msgid "All"
+msgstr ""
+
+msgctxt ""
+"model:ir.action.act_window.domain,name:act_gift_card_form_domain_pending"
+msgid "Pending"
+msgstr ""
+
+msgctxt ""
+"model:ir.action.act_window.domain,name:act_gift_card_form_domain_sent"
+msgid "Sent"
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_gift_card_invalid_uom"
+msgid "The default UOM for the gift card \"%(template)s\" must be \"%(unit)s\"."
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_gift_card_move_quantity"
+msgid ""
+"To do the move \"%(move)s\", you must use exactly %(quantity)d gift card(s)."
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_gift_card_number_unique"
+msgid "The numbers for each company's gift cards must be unique."
+msgstr ""
+
+msgctxt "model:ir.rule.group,name:rule_group_gift_card_companies"
+msgid "User in companies"
+msgstr ""
+
+msgctxt "model:ir.sequence.type,name:sequence_type_gift_card"
+msgid "Gift Card"
+msgstr ""
+
+msgctxt "model:ir.ui.menu,name:menu_gift_card_form"
+msgid "Gift Cards"
+msgstr ""
+
+msgctxt "model:res.group,name:group_gift_card_admin"
+msgid "Gift Card Administration"
+msgstr ""
+
+msgctxt "model:sale.configuration.gift_card.sequence,name:"
+msgid "Gift Card Configuration Sequence"
+msgstr ""
+
+msgctxt "model:sale.gift_card,name:"
+msgid "Gift Card"
+msgstr ""
+
+msgctxt "report:sale.gift_card.email:"
+msgid "Gift Card"
+msgstr ""
+
+msgctxt "report:sale.gift_card.email:"
+msgid "Here is your code:"
+msgstr ""
+
+msgctxt "report:sale.gift_card.email:"
+msgid "You received a gift card of"
+msgstr ""
+
+msgctxt "report:sale.gift_card.email:"
+msgid "for"
+msgstr ""
+
+msgctxt "view:account.configuration:"
+msgid "Gift Card"
+msgstr ""
+
+msgctxt "view:sale.line:"
+msgid "Gift Cards"
+msgstr ""
diff --git a/modules/sale_gift_card/locale/ru.po b/modules/sale_gift_card/locale/ru.po
new file mode 100644
index 0000000000..bd14ca036a
--- /dev/null
+++ b/modules/sale_gift_card/locale/ru.po
@@ -0,0 +1,204 @@
+#
+msgid ""
+msgstr "Content-Type: text/plain; charset=utf-8\n"
+
+msgctxt "field:account.account.type,gift_card:"
+msgid "Gift Card"
+msgstr ""
+
+msgctxt "field:account.account.type.template,gift_card:"
+msgid "Gift Card"
+msgstr ""
+
+msgctxt "field:account.configuration,gift_card_account_expense:"
+msgid "Gift Card Expense"
+msgstr ""
+
+msgctxt "field:account.configuration,gift_card_account_revenue:"
+msgid "Gift Card Revenue"
+msgstr ""
+
+msgctxt "field:account.configuration.gift_card_account,company:"
+msgid "Company"
+msgstr ""
+
+msgctxt ""
+"field:account.configuration.gift_card_account,gift_card_account_expense:"
+msgid "Gift Card Expense"
+msgstr ""
+
+msgctxt ""
+"field:account.configuration.gift_card_account,gift_card_account_revenue:"
+msgid "Gift Card Revenue"
+msgstr ""
+
+msgctxt "field:product.product,gift_card:"
+msgid "Gift Card"
+msgstr ""
+
+msgctxt "field:product.template,gift_card:"
+msgid "Gift Card"
+msgstr ""
+
+msgctxt "field:sale.configuration,gift_card_sequence:"
+msgid "Gift Card Sequence"
+msgstr ""
+
+msgctxt "field:sale.configuration.gift_card.sequence,company:"
+msgid "Company"
+msgstr ""
+
+msgctxt "field:sale.configuration.gift_card.sequence,gift_card_sequence:"
+msgid "Gift Card Sequence"
+msgstr ""
+
+msgctxt "field:sale.gift_card,company:"
+msgid "Company"
+msgstr ""
+
+msgctxt "field:sale.gift_card,currency:"
+msgid "Currency"
+msgstr ""
+
+msgctxt "field:sale.gift_card,currency_digits:"
+msgid "Currency Digits"
+msgstr ""
+
+msgctxt "field:sale.gift_card,number:"
+msgid "Number"
+msgstr ""
+
+msgctxt "field:sale.gift_card,origin:"
+msgid "Origin"
+msgstr ""
+
+msgctxt "field:sale.gift_card,product:"
+msgid "Product"
+msgstr ""
+
+msgctxt "field:sale.gift_card,spent_on:"
+msgid "Spent On"
+msgstr ""
+
+msgctxt "field:sale.gift_card,value:"
+msgid "Value"
+msgstr ""
+
+msgctxt "field:sale.line,gift_card_email:"
+msgid "Gift Card Email"
+msgstr ""
+
+msgctxt "field:sale.line,gift_cards:"
+msgid "Gift Cards"
+msgstr ""
+
+msgctxt "field:sale.line,is_gift_card:"
+msgid "Is Gift Card"
+msgstr ""
+
+msgctxt "field:sale.line,is_gift_card_service:"
+msgid "Is Gift Card Service"
+msgstr ""
+
+msgctxt "field:sale.sale,gift_cards:"
+msgid "Gift Cards"
+msgstr ""
+
+msgctxt "field:stock.move,gift_cards:"
+msgid "Gift Cards"
+msgstr ""
+
+msgctxt "field:stock.move,gift_cards_required:"
+msgid "Gift Cards Required"
+msgstr ""
+
+msgctxt "help:sale.line,gift_card_email:"
+msgid "Leave empty for the customer email."
+msgstr ""
+
+msgctxt "model:account.configuration.gift_card_account,name:"
+msgid "Account Configuration Gift Card Account"
+msgstr ""
+
+msgctxt "model:ir.action,name:act_gift_card_form"
+msgid "Gift Cards"
+msgstr ""
+
+msgctxt "model:ir.action,name:report_gift_card_email"
+msgid "Gift Card"
+msgstr ""
+
+msgctxt "model:ir.action.act_window.domain,name:act_gift_card_form_domain_all"
+msgid "All"
+msgstr ""
+
+msgctxt ""
+"model:ir.action.act_window.domain,name:act_gift_card_form_domain_pending"
+msgid "Pending"
+msgstr ""
+
+msgctxt ""
+"model:ir.action.act_window.domain,name:act_gift_card_form_domain_sent"
+msgid "Sent"
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_gift_card_invalid_uom"
+msgid "The default UOM for the gift card \"%(template)s\" must be \"%(unit)s\"."
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_gift_card_move_quantity"
+msgid ""
+"To do the move \"%(move)s\", you must use exactly %(quantity)d gift card(s)."
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_gift_card_number_unique"
+msgid "The numbers for each company's gift cards must be unique."
+msgstr ""
+
+msgctxt "model:ir.rule.group,name:rule_group_gift_card_companies"
+msgid "User in companies"
+msgstr ""
+
+msgctxt "model:ir.sequence.type,name:sequence_type_gift_card"
+msgid "Gift Card"
+msgstr ""
+
+msgctxt "model:ir.ui.menu,name:menu_gift_card_form"
+msgid "Gift Cards"
+msgstr ""
+
+msgctxt "model:res.group,name:group_gift_card_admin"
+msgid "Gift Card Administration"
+msgstr ""
+
+msgctxt "model:sale.configuration.gift_card.sequence,name:"
+msgid "Gift Card Configuration Sequence"
+msgstr ""
+
+msgctxt "model:sale.gift_card,name:"
+msgid "Gift Card"
+msgstr ""
+
+msgctxt "report:sale.gift_card.email:"
+msgid "Gift Card"
+msgstr ""
+
+msgctxt "report:sale.gift_card.email:"
+msgid "Here is your code:"
+msgstr ""
+
+msgctxt "report:sale.gift_card.email:"
+msgid "You received a gift card of"
+msgstr ""
+
+msgctxt "report:sale.gift_card.email:"
+msgid "for"
+msgstr ""
+
+msgctxt "view:account.configuration:"
+msgid "Gift Card"
+msgstr ""
+
+msgctxt "view:sale.line:"
+msgid "Gift Cards"
+msgstr ""
diff --git a/modules/sale_gift_card/locale/sl.po b/modules/sale_gift_card/locale/sl.po
new file mode 100644
index 0000000000..bd14ca036a
--- /dev/null
+++ b/modules/sale_gift_card/locale/sl.po
@@ -0,0 +1,204 @@
+#
+msgid ""
+msgstr "Content-Type: text/plain; charset=utf-8\n"
+
+msgctxt "field:account.account.type,gift_card:"
+msgid "Gift Card"
+msgstr ""
+
+msgctxt "field:account.account.type.template,gift_card:"
+msgid "Gift Card"
+msgstr ""
+
+msgctxt "field:account.configuration,gift_card_account_expense:"
+msgid "Gift Card Expense"
+msgstr ""
+
+msgctxt "field:account.configuration,gift_card_account_revenue:"
+msgid "Gift Card Revenue"
+msgstr ""
+
+msgctxt "field:account.configuration.gift_card_account,company:"
+msgid "Company"
+msgstr ""
+
+msgctxt ""
+"field:account.configuration.gift_card_account,gift_card_account_expense:"
+msgid "Gift Card Expense"
+msgstr ""
+
+msgctxt ""
+"field:account.configuration.gift_card_account,gift_card_account_revenue:"
+msgid "Gift Card Revenue"
+msgstr ""
+
+msgctxt "field:product.product,gift_card:"
+msgid "Gift Card"
+msgstr ""
+
+msgctxt "field:product.template,gift_card:"
+msgid "Gift Card"
+msgstr ""
+
+msgctxt "field:sale.configuration,gift_card_sequence:"
+msgid "Gift Card Sequence"
+msgstr ""
+
+msgctxt "field:sale.configuration.gift_card.sequence,company:"
+msgid "Company"
+msgstr ""
+
+msgctxt "field:sale.configuration.gift_card.sequence,gift_card_sequence:"
+msgid "Gift Card Sequence"
+msgstr ""
+
+msgctxt "field:sale.gift_card,company:"
+msgid "Company"
+msgstr ""
+
+msgctxt "field:sale.gift_card,currency:"
+msgid "Currency"
+msgstr ""
+
+msgctxt "field:sale.gift_card,currency_digits:"
+msgid "Currency Digits"
+msgstr ""
+
+msgctxt "field:sale.gift_card,number:"
+msgid "Number"
+msgstr ""
+
+msgctxt "field:sale.gift_card,origin:"
+msgid "Origin"
+msgstr ""
+
+msgctxt "field:sale.gift_card,product:"
+msgid "Product"
+msgstr ""
+
+msgctxt "field:sale.gift_card,spent_on:"
+msgid "Spent On"
+msgstr ""
+
+msgctxt "field:sale.gift_card,value:"
+msgid "Value"
+msgstr ""
+
+msgctxt "field:sale.line,gift_card_email:"
+msgid "Gift Card Email"
+msgstr ""
+
+msgctxt "field:sale.line,gift_cards:"
+msgid "Gift Cards"
+msgstr ""
+
+msgctxt "field:sale.line,is_gift_card:"
+msgid "Is Gift Card"
+msgstr ""
+
+msgctxt "field:sale.line,is_gift_card_service:"
+msgid "Is Gift Card Service"
+msgstr ""
+
+msgctxt "field:sale.sale,gift_cards:"
+msgid "Gift Cards"
+msgstr ""
+
+msgctxt "field:stock.move,gift_cards:"
+msgid "Gift Cards"
+msgstr ""
+
+msgctxt "field:stock.move,gift_cards_required:"
+msgid "Gift Cards Required"
+msgstr ""
+
+msgctxt "help:sale.line,gift_card_email:"
+msgid "Leave empty for the customer email."
+msgstr ""
+
+msgctxt "model:account.configuration.gift_card_account,name:"
+msgid "Account Configuration Gift Card Account"
+msgstr ""
+
+msgctxt "model:ir.action,name:act_gift_card_form"
+msgid "Gift Cards"
+msgstr ""
+
+msgctxt "model:ir.action,name:report_gift_card_email"
+msgid "Gift Card"
+msgstr ""
+
+msgctxt "model:ir.action.act_window.domain,name:act_gift_card_form_domain_all"
+msgid "All"
+msgstr ""
+
+msgctxt ""
+"model:ir.action.act_window.domain,name:act_gift_card_form_domain_pending"
+msgid "Pending"
+msgstr ""
+
+msgctxt ""
+"model:ir.action.act_window.domain,name:act_gift_card_form_domain_sent"
+msgid "Sent"
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_gift_card_invalid_uom"
+msgid "The default UOM for the gift card \"%(template)s\" must be \"%(unit)s\"."
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_gift_card_move_quantity"
+msgid ""
+"To do the move \"%(move)s\", you must use exactly %(quantity)d gift card(s)."
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_gift_card_number_unique"
+msgid "The numbers for each company's gift cards must be unique."
+msgstr ""
+
+msgctxt "model:ir.rule.group,name:rule_group_gift_card_companies"
+msgid "User in companies"
+msgstr ""
+
+msgctxt "model:ir.sequence.type,name:sequence_type_gift_card"
+msgid "Gift Card"
+msgstr ""
+
+msgctxt "model:ir.ui.menu,name:menu_gift_card_form"
+msgid "Gift Cards"
+msgstr ""
+
+msgctxt "model:res.group,name:group_gift_card_admin"
+msgid "Gift Card Administration"
+msgstr ""
+
+msgctxt "model:sale.configuration.gift_card.sequence,name:"
+msgid "Gift Card Configuration Sequence"
+msgstr ""
+
+msgctxt "model:sale.gift_card,name:"
+msgid "Gift Card"
+msgstr ""
+
+msgctxt "report:sale.gift_card.email:"
+msgid "Gift Card"
+msgstr ""
+
+msgctxt "report:sale.gift_card.email:"
+msgid "Here is your code:"
+msgstr ""
+
+msgctxt "report:sale.gift_card.email:"
+msgid "You received a gift card of"
+msgstr ""
+
+msgctxt "report:sale.gift_card.email:"
+msgid "for"
+msgstr ""
+
+msgctxt "view:account.configuration:"
+msgid "Gift Card"
+msgstr ""
+
+msgctxt "view:sale.line:"
+msgid "Gift Cards"
+msgstr ""
diff --git a/modules/sale_gift_card/locale/tr.po b/modules/sale_gift_card/locale/tr.po
new file mode 100644
index 0000000000..bd14ca036a
--- /dev/null
+++ b/modules/sale_gift_card/locale/tr.po
@@ -0,0 +1,204 @@
+#
+msgid ""
+msgstr "Content-Type: text/plain; charset=utf-8\n"
+
+msgctxt "field:account.account.type,gift_card:"
+msgid "Gift Card"
+msgstr ""
+
+msgctxt "field:account.account.type.template,gift_card:"
+msgid "Gift Card"
+msgstr ""
+
+msgctxt "field:account.configuration,gift_card_account_expense:"
+msgid "Gift Card Expense"
+msgstr ""
+
+msgctxt "field:account.configuration,gift_card_account_revenue:"
+msgid "Gift Card Revenue"
+msgstr ""
+
+msgctxt "field:account.configuration.gift_card_account,company:"
+msgid "Company"
+msgstr ""
+
+msgctxt ""
+"field:account.configuration.gift_card_account,gift_card_account_expense:"
+msgid "Gift Card Expense"
+msgstr ""
+
+msgctxt ""
+"field:account.configuration.gift_card_account,gift_card_account_revenue:"
+msgid "Gift Card Revenue"
+msgstr ""
+
+msgctxt "field:product.product,gift_card:"
+msgid "Gift Card"
+msgstr ""
+
+msgctxt "field:product.template,gift_card:"
+msgid "Gift Card"
+msgstr ""
+
+msgctxt "field:sale.configuration,gift_card_sequence:"
+msgid "Gift Card Sequence"
+msgstr ""
+
+msgctxt "field:sale.configuration.gift_card.sequence,company:"
+msgid "Company"
+msgstr ""
+
+msgctxt "field:sale.configuration.gift_card.sequence,gift_card_sequence:"
+msgid "Gift Card Sequence"
+msgstr ""
+
+msgctxt "field:sale.gift_card,company:"
+msgid "Company"
+msgstr ""
+
+msgctxt "field:sale.gift_card,currency:"
+msgid "Currency"
+msgstr ""
+
+msgctxt "field:sale.gift_card,currency_digits:"
+msgid "Currency Digits"
+msgstr ""
+
+msgctxt "field:sale.gift_card,number:"
+msgid "Number"
+msgstr ""
+
+msgctxt "field:sale.gift_card,origin:"
+msgid "Origin"
+msgstr ""
+
+msgctxt "field:sale.gift_card,product:"
+msgid "Product"
+msgstr ""
+
+msgctxt "field:sale.gift_card,spent_on:"
+msgid "Spent On"
+msgstr ""
+
+msgctxt "field:sale.gift_card,value:"
+msgid "Value"
+msgstr ""
+
+msgctxt "field:sale.line,gift_card_email:"
+msgid "Gift Card Email"
+msgstr ""
+
+msgctxt "field:sale.line,gift_cards:"
+msgid "Gift Cards"
+msgstr ""
+
+msgctxt "field:sale.line,is_gift_card:"
+msgid "Is Gift Card"
+msgstr ""
+
+msgctxt "field:sale.line,is_gift_card_service:"
+msgid "Is Gift Card Service"
+msgstr ""
+
+msgctxt "field:sale.sale,gift_cards:"
+msgid "Gift Cards"
+msgstr ""
+
+msgctxt "field:stock.move,gift_cards:"
+msgid "Gift Cards"
+msgstr ""
+
+msgctxt "field:stock.move,gift_cards_required:"
+msgid "Gift Cards Required"
+msgstr ""
+
+msgctxt "help:sale.line,gift_card_email:"
+msgid "Leave empty for the customer email."
+msgstr ""
+
+msgctxt "model:account.configuration.gift_card_account,name:"
+msgid "Account Configuration Gift Card Account"
+msgstr ""
+
+msgctxt "model:ir.action,name:act_gift_card_form"
+msgid "Gift Cards"
+msgstr ""
+
+msgctxt "model:ir.action,name:report_gift_card_email"
+msgid "Gift Card"
+msgstr ""
+
+msgctxt "model:ir.action.act_window.domain,name:act_gift_card_form_domain_all"
+msgid "All"
+msgstr ""
+
+msgctxt ""
+"model:ir.action.act_window.domain,name:act_gift_card_form_domain_pending"
+msgid "Pending"
+msgstr ""
+
+msgctxt ""
+"model:ir.action.act_window.domain,name:act_gift_card_form_domain_sent"
+msgid "Sent"
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_gift_card_invalid_uom"
+msgid "The default UOM for the gift card \"%(template)s\" must be \"%(unit)s\"."
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_gift_card_move_quantity"
+msgid ""
+"To do the move \"%(move)s\", you must use exactly %(quantity)d gift card(s)."
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_gift_card_number_unique"
+msgid "The numbers for each company's gift cards must be unique."
+msgstr ""
+
+msgctxt "model:ir.rule.group,name:rule_group_gift_card_companies"
+msgid "User in companies"
+msgstr ""
+
+msgctxt "model:ir.sequence.type,name:sequence_type_gift_card"
+msgid "Gift Card"
+msgstr ""
+
+msgctxt "model:ir.ui.menu,name:menu_gift_card_form"
+msgid "Gift Cards"
+msgstr ""
+
+msgctxt "model:res.group,name:group_gift_card_admin"
+msgid "Gift Card Administration"
+msgstr ""
+
+msgctxt "model:sale.configuration.gift_card.sequence,name:"
+msgid "Gift Card Configuration Sequence"
+msgstr ""
+
+msgctxt "model:sale.gift_card,name:"
+msgid "Gift Card"
+msgstr ""
+
+msgctxt "report:sale.gift_card.email:"
+msgid "Gift Card"
+msgstr ""
+
+msgctxt "report:sale.gift_card.email:"
+msgid "Here is your code:"
+msgstr ""
+
+msgctxt "report:sale.gift_card.email:"
+msgid "You received a gift card of"
+msgstr ""
+
+msgctxt "report:sale.gift_card.email:"
+msgid "for"
+msgstr ""
+
+msgctxt "view:account.configuration:"
+msgid "Gift Card"
+msgstr ""
+
+msgctxt "view:sale.line:"
+msgid "Gift Cards"
+msgstr ""
diff --git a/modules/sale_gift_card/locale/zh_CN.po b/modules/sale_gift_card/locale/zh_CN.po
new file mode 100644
index 0000000000..bd14ca036a
--- /dev/null
+++ b/modules/sale_gift_card/locale/zh_CN.po
@@ -0,0 +1,204 @@
+#
+msgid ""
+msgstr "Content-Type: text/plain; charset=utf-8\n"
+
+msgctxt "field:account.account.type,gift_card:"
+msgid "Gift Card"
+msgstr ""
+
+msgctxt "field:account.account.type.template,gift_card:"
+msgid "Gift Card"
+msgstr ""
+
+msgctxt "field:account.configuration,gift_card_account_expense:"
+msgid "Gift Card Expense"
+msgstr ""
+
+msgctxt "field:account.configuration,gift_card_account_revenue:"
+msgid "Gift Card Revenue"
+msgstr ""
+
+msgctxt "field:account.configuration.gift_card_account,company:"
+msgid "Company"
+msgstr ""
+
+msgctxt ""
+"field:account.configuration.gift_card_account,gift_card_account_expense:"
+msgid "Gift Card Expense"
+msgstr ""
+
+msgctxt ""
+"field:account.configuration.gift_card_account,gift_card_account_revenue:"
+msgid "Gift Card Revenue"
+msgstr ""
+
+msgctxt "field:product.product,gift_card:"
+msgid "Gift Card"
+msgstr ""
+
+msgctxt "field:product.template,gift_card:"
+msgid "Gift Card"
+msgstr ""
+
+msgctxt "field:sale.configuration,gift_card_sequence:"
+msgid "Gift Card Sequence"
+msgstr ""
+
+msgctxt "field:sale.configuration.gift_card.sequence,company:"
+msgid "Company"
+msgstr ""
+
+msgctxt "field:sale.configuration.gift_card.sequence,gift_card_sequence:"
+msgid "Gift Card Sequence"
+msgstr ""
+
+msgctxt "field:sale.gift_card,company:"
+msgid "Company"
+msgstr ""
+
+msgctxt "field:sale.gift_card,currency:"
+msgid "Currency"
+msgstr ""
+
+msgctxt "field:sale.gift_card,currency_digits:"
+msgid "Currency Digits"
+msgstr ""
+
+msgctxt "field:sale.gift_card,number:"
+msgid "Number"
+msgstr ""
+
+msgctxt "field:sale.gift_card,origin:"
+msgid "Origin"
+msgstr ""
+
+msgctxt "field:sale.gift_card,product:"
+msgid "Product"
+msgstr ""
+
+msgctxt "field:sale.gift_card,spent_on:"
+msgid "Spent On"
+msgstr ""
+
+msgctxt "field:sale.gift_card,value:"
+msgid "Value"
+msgstr ""
+
+msgctxt "field:sale.line,gift_card_email:"
+msgid "Gift Card Email"
+msgstr ""
+
+msgctxt "field:sale.line,gift_cards:"
+msgid "Gift Cards"
+msgstr ""
+
+msgctxt "field:sale.line,is_gift_card:"
+msgid "Is Gift Card"
+msgstr ""
+
+msgctxt "field:sale.line,is_gift_card_service:"
+msgid "Is Gift Card Service"
+msgstr ""
+
+msgctxt "field:sale.sale,gift_cards:"
+msgid "Gift Cards"
+msgstr ""
+
+msgctxt "field:stock.move,gift_cards:"
+msgid "Gift Cards"
+msgstr ""
+
+msgctxt "field:stock.move,gift_cards_required:"
+msgid "Gift Cards Required"
+msgstr ""
+
+msgctxt "help:sale.line,gift_card_email:"
+msgid "Leave empty for the customer email."
+msgstr ""
+
+msgctxt "model:account.configuration.gift_card_account,name:"
+msgid "Account Configuration Gift Card Account"
+msgstr ""
+
+msgctxt "model:ir.action,name:act_gift_card_form"
+msgid "Gift Cards"
+msgstr ""
+
+msgctxt "model:ir.action,name:report_gift_card_email"
+msgid "Gift Card"
+msgstr ""
+
+msgctxt "model:ir.action.act_window.domain,name:act_gift_card_form_domain_all"
+msgid "All"
+msgstr ""
+
+msgctxt ""
+"model:ir.action.act_window.domain,name:act_gift_card_form_domain_pending"
+msgid "Pending"
+msgstr ""
+
+msgctxt ""
+"model:ir.action.act_window.domain,name:act_gift_card_form_domain_sent"
+msgid "Sent"
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_gift_card_invalid_uom"
+msgid "The default UOM for the gift card \"%(template)s\" must be \"%(unit)s\"."
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_gift_card_move_quantity"
+msgid ""
+"To do the move \"%(move)s\", you must use exactly %(quantity)d gift card(s)."
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_gift_card_number_unique"
+msgid "The numbers for each company's gift cards must be unique."
+msgstr ""
+
+msgctxt "model:ir.rule.group,name:rule_group_gift_card_companies"
+msgid "User in companies"
+msgstr ""
+
+msgctxt "model:ir.sequence.type,name:sequence_type_gift_card"
+msgid "Gift Card"
+msgstr ""
+
+msgctxt "model:ir.ui.menu,name:menu_gift_card_form"
+msgid "Gift Cards"
+msgstr ""
+
+msgctxt "model:res.group,name:group_gift_card_admin"
+msgid "Gift Card Administration"
+msgstr ""
+
+msgctxt "model:sale.configuration.gift_card.sequence,name:"
+msgid "Gift Card Configuration Sequence"
+msgstr ""
+
+msgctxt "model:sale.gift_card,name:"
+msgid "Gift Card"
+msgstr ""
+
+msgctxt "report:sale.gift_card.email:"
+msgid "Gift Card"
+msgstr ""
+
+msgctxt "report:sale.gift_card.email:"
+msgid "Here is your code:"
+msgstr ""
+
+msgctxt "report:sale.gift_card.email:"
+msgid "You received a gift card of"
+msgstr ""
+
+msgctxt "report:sale.gift_card.email:"
+msgid "for"
+msgstr ""
+
+msgctxt "view:account.configuration:"
+msgid "Gift Card"
+msgstr ""
+
+msgctxt "view:sale.line:"
+msgid "Gift Cards"
+msgstr ""
diff --git a/modules/sale_gift_card/message.xml b/modules/sale_gift_card/message.xml
new file mode 100644
index 0000000000..022ecb0d4f
--- /dev/null
+++ b/modules/sale_gift_card/message.xml
@@ -0,0 +1,16 @@
+
+
+
+
+
+ The numbers for each company's gift cards must be unique.
+
+
+ The default UOM for the gift card "%(template)s" must be "%(unit)s".
+
+
+ To do the move "%(move)s", you must use exactly %(quantity)d gift card(s).
+
+
+
diff --git a/modules/sale_gift_card/product.py b/modules/sale_gift_card/product.py
new file mode 100644
index 0000000000..0b87493127
--- /dev/null
+++ b/modules/sale_gift_card/product.py
@@ -0,0 +1,69 @@
+# This file is part of Tryton. The COPYRIGHT file at the top level of
+# this repository contains the full copyright notices and license terms.
+from trytond.i18n import gettext
+from trytond.model import fields
+from trytond.pool import PoolMeta, Pool
+from trytond.pyson import Eval
+from trytond.transaction import Transaction
+
+from .exceptions import GiftCardValidationError
+
+
+class Template(metaclass=PoolMeta):
+ __name__ = 'product.template'
+
+ gift_card = fields.Boolean(
+ "Gift Card",
+ states={
+ 'invisible': ~Eval('type').in_(['service', 'goods']),
+ },
+ depends=['type'])
+
+ @fields.depends('gift_card')
+ def on_change_gift_card(self):
+ pool = Pool()
+ ModelData = pool.get('ir.model.data')
+ if self.gift_card:
+ self.default_uom = ModelData.get_id('product', 'uom_unit')
+
+ @classmethod
+ def validate(cls, templates):
+ pool = Pool()
+ ModelData = pool.get('ir.model.data')
+ UoM = pool.get('product.uom')
+ super().validate(templates)
+ unit = UoM(ModelData.get_id('product', 'uom_unit'))
+ for template in templates:
+ if template.gift_card and template.default_uom != unit:
+ raise GiftCardValidationError(
+ gettext('sale_gift_card.msg_gift_card_invalid_uom',
+ template=template.rec_name,
+ unit=unit.rec_name))
+
+ @property
+ def account_expense_used(self):
+ pool = Pool()
+ Config = pool.get('account.configuration')
+ if self.gift_card:
+ transaction = Transaction()
+ with transaction.reset_context(), \
+ transaction.set_context(self._context):
+ config = Config(1)
+ return config.gift_card_account_expense
+ return super().account_expense_used
+
+ @property
+ def account_revenue_used(self):
+ pool = Pool()
+ Config = pool.get('account.configuration')
+ if self.gift_card:
+ transaction = Transaction()
+ with transaction.reset_context(), \
+ transaction.set_context(self._context):
+ config = Config(1)
+ return config.gift_card_account_revenue
+ return super().account_revenue_used
+
+
+class Product(metaclass=PoolMeta):
+ __name__ = 'product.product'
diff --git a/modules/sale_gift_card/product.xml b/modules/sale_gift_card/product.xml
new file mode 100644
index 0000000000..70184cd889
--- /dev/null
+++ b/modules/sale_gift_card/product.xml
@@ -0,0 +1,12 @@
+
+
+
+
+
+ product.template
+
+ template_form
+
+
+
diff --git a/modules/sale_gift_card/sale.py b/modules/sale_gift_card/sale.py
new file mode 100644
index 0000000000..54e4b73333
--- /dev/null
+++ b/modules/sale_gift_card/sale.py
@@ -0,0 +1,348 @@
+# This file is part of Tryton. The COPYRIGHT file at the top level of
+# this repository contains the full copyright notices and license terms.
+from email.header import Header
+
+from sql import Null
+from sql.operators import Equal
+
+from trytond.config import config
+from trytond.model import ModelSQL, ModelView, Workflow, Exclude, fields
+from trytond.pool import PoolMeta, Pool
+from trytond.pyson import Eval, Bool, Id
+from trytond.report import Report, get_email
+from trytond.sendmail import sendmail_transactional
+from trytond.transaction import Transaction
+
+from trytond.modules.company.model import CompanyValueMixin
+
+
+class Configuration(metaclass=PoolMeta):
+ __name__ = 'sale.configuration'
+
+ gift_card_sequence = fields.MultiValue(fields.Many2One(
+ 'ir.sequence', "Gift Card Sequence",
+ domain=[
+ ('company', 'in', [
+ Eval('context', {}).get('company', -1), None]),
+ ('sequence_type', '=', Id(
+ 'sale_gift_card', 'sequence_type_gift_card')),
+ ]))
+
+ @classmethod
+ def multivalue_model(cls, field):
+ pool = Pool()
+ if field == 'gift_card_sequence':
+ return pool.get('sale.configuration.gift_card.sequence')
+ return super().multivalue_model(field)
+
+
+class ConfigurationGiftCardSequence(ModelSQL, CompanyValueMixin):
+ "Gift Card Configuration Sequence"
+ __name__ = 'sale.configuration.gift_card.sequence'
+ gift_card_sequence = fields.Many2One(
+ 'ir.sequence', "Gift Card Sequence",
+ domain=[
+ ('company', 'in', [Eval('company', -1), None]),
+ ('sequence_type', '=', Id(
+ 'sale_gift_card', 'sequence_type_gift_card')),
+ ],
+ depends=['company'])
+
+
+class GiftCard(ModelSQL, ModelView):
+ "Gift Card"
+ __name__ = 'sale.gift_card'
+ _rec_name = 'number'
+
+ _states = {
+ 'readonly': Bool(Eval('origin')) | Bool(Eval('spent_on')),
+ }
+ _depends = ['origin']
+
+ number = fields.Char(
+ "Number", required=True, states=_states, depends=_depends)
+ company = fields.Many2One(
+ 'company.company', "Company", required=True,
+ states=_states, depends=_depends)
+ product = fields.Many2One(
+ 'product.product', "Product", required=True,
+ domain=[
+ ('gift_card', '=', True),
+ ],
+ context={
+ 'company': Eval('company', -1),
+ },
+ states=_states, depends=_depends + ['company'])
+ value = fields.Numeric(
+ "Value", digits=(16, Eval('currency_digits', 2)), required=True,
+ states=_states, depends=_depends + ['currency_digits'])
+ currency = fields.Many2One(
+ 'currency.currency', "Currency", required=True,
+ states=_states, depends=_depends)
+
+ origin = fields.Reference(
+ "Origin", selection='get_origin', select=True, readonly=True)
+ spent_on = fields.Reference(
+ "Spent On", selection='get_spent_on', select=True, readonly=True)
+
+ currency_digits = fields.Function(
+ fields.Integer("Currency Digits"), 'on_change_with_currency_digits')
+
+ del _states
+ del _depends
+
+ @classmethod
+ def __setup__(cls):
+ super().__setup__()
+ t = cls.__table__()
+ cls._sql_constraints = [
+ ('number_exclude',
+ Exclude(t, (t.number, Equal), (t.company, Equal),
+ where=(t.spent_on == Null)),
+ 'sale_gift_card.msg_gift_card_number_unique'),
+ ]
+ cls._order.insert(0, ('number', 'ASC'))
+
+ @classmethod
+ def default_company(cls):
+ return Transaction().context.get('company')
+
+ @fields.depends('currency')
+ def on_change_with_currency_digits(self, name=None):
+ if self.currency:
+ return self.currency.digits
+
+ @classmethod
+ def _get_origin(cls):
+ return ['sale.line', 'stock.move']
+
+ @classmethod
+ def get_origin(cls):
+ pool = Pool()
+ Model = pool.get('ir.model')
+ return [(None, '')] + [
+ (m, Model.get_name(m)) for m in cls._get_origin()]
+
+ @fields.depends('origin', 'value', 'currency')
+ def on_change_origin(self):
+ pool = Pool()
+ SaleLine = pool.get('sale.line')
+ StockMove = pool.get('stock.move')
+ UoM = pool.get('product.uom')
+ if isinstance(self.origin, SaleLine):
+ line = self.origin
+ self.company = line.sale.company
+ self.product = line.product
+ if line.unit and line.unit_price and line.product:
+ self.value = UoM.compute_price(
+ line.unit, line.unit_price, line.product.default_uom)
+ self.currency = line.sale.currency
+ elif isinstance(self.origin, StockMove):
+ move = self.origin
+ self.company = move.company
+ self.product = move.product
+ if move.uom and move.unit_price:
+ self.value = UoM.compute_price(
+ move.uom, move.unit_price, move.product.default_uom)
+ self.currency = move.currency
+ if self.value and self.currency:
+ self.value = self.currency.round(self.value)
+
+ @classmethod
+ def _get_spent_on(cls):
+ return ['sale.sale']
+
+ @classmethod
+ def get_spent_on(cls):
+ pool = Pool()
+ Model = pool.get('ir.model')
+ return [(None, '')] + [
+ (m, Model.get_name(m)) for m in cls._get_spent_on()]
+
+ def get_rec_name(self, name):
+ if not self.number:
+ name = '(%d)' % self.id
+ else:
+ name = self.number
+ return name
+
+ @property
+ def _email(self):
+ pool = Pool()
+ SaleLine = pool.get('sale.line')
+ if isinstance(self.origin, SaleLine):
+ return self.origin.gift_card_email or self.origin.sale.party.email
+
+ @property
+ def _languages(self):
+ pool = Pool()
+ SaleLine = pool.get('sale.line')
+ languages = []
+ if isinstance(self.origin, SaleLine):
+ lang = self.origin.sale.party.lang
+ if lang:
+ languages.append(lang)
+ return languages
+
+ @classmethod
+ def send(cls, gift_cards, from_=None):
+ pool = Pool()
+ Lang = pool.get('ir.lang')
+ if from_ is None:
+ from_ = config.get('email', 'from')
+ for gift_card in gift_cards:
+ email = gift_card._email
+ languages = gift_card._languages
+ if not languages:
+ languages.append(Lang.get())
+ msg, title = get_email(
+ 'sale.gift_card.email', gift_card, languages)
+ msg['From'] = from_
+ msg['To'] = email
+ msg['Subject'] = Header(title, 'utf-8')
+ sendmail_transactional(from_, [email], msg)
+
+
+class GiftCardEmail(Report):
+ __name__ = 'sale.gift_card.email'
+
+
+class Sale(metaclass=PoolMeta):
+ __name__ = 'sale.sale'
+
+ gift_cards = fields.One2Many(
+ 'sale.gift_card', 'spent_on', "Gift Cards",
+ domain=[
+ ('company', '=', Eval('company', -1)),
+ ('currency', '=', Eval('currency', -1)),
+ ],
+ add_remove=[
+ ('spent_on', '=', None),
+ ],
+ states={
+ 'readonly': Eval('state') != 'draft',
+ },
+ depends=['state', 'company', 'currency'])
+
+ @classmethod
+ @ModelView.button
+ @Workflow.transition('quotation')
+ def quote(cls, sales):
+ for sale in sales:
+ sale.add_return_gift_cards()
+ cls.save(sales)
+ super().quote(sales)
+
+ def add_return_gift_cards(self):
+ lines = list(self.lines)
+ for line in self.lines:
+ if line.is_gift_card and line.quantity < 0:
+ lines.remove(line)
+ for gift_card in self.gift_cards:
+ lines.append(self.get_return_gift_card_line(gift_card))
+ self.lines = lines
+
+ def get_return_gift_card_line(self, gift_card):
+ pool = Pool()
+ Line = pool.get('sale.line')
+ sequence = None
+ if self.lines:
+ last_line = self.lines[-1]
+ if last_line.sequence is not None:
+ sequence = last_line.sequence + 1
+ return Line(
+ sale=self,
+ sequence=sequence,
+ type='line',
+ product=gift_card.product,
+ quantity=-1,
+ unit=gift_card.product.default_uom,
+ unit_price=gift_card.value,
+ )
+
+ @classmethod
+ @ModelView.button
+ def process(cls, sales):
+ pool = Pool()
+ GiftCard = pool.get('sale.gift_card')
+ cls.lock(sales)
+ gift_cards = []
+ for sale in sales:
+ for line in sale.lines:
+ cards = line.get_gift_cards()
+ if cards:
+ gift_cards.extend(cards)
+ GiftCard.save(gift_cards)
+ GiftCard.send(gift_cards)
+ super().process(sales)
+
+
+class Line(metaclass=PoolMeta):
+ __name__ = 'sale.line'
+
+ gift_cards = fields.One2Many(
+ 'sale.gift_card', 'origin', "Gift Cards", readonly=True,
+ states={
+ 'invisible': ~Eval('gift_cards', []),
+ })
+ is_gift_card = fields.Function(
+ fields.Boolean("Is Gift Card"), 'on_change_with_is_gift_card')
+ is_gift_card_service = fields.Function(
+ fields.Boolean("Is Gift Card Service"),
+ 'on_change_with_is_gift_card_service')
+ gift_card_email = fields.Char(
+ "Gift Card Email",
+ states={
+ 'invisible': ~Eval('is_gift_card_service', False),
+ },
+ depends=['is_gift_card_service'],
+ help="Leave empty for the customer email.")
+
+ @fields.depends('product')
+ def on_change_with_is_gift_card(self, name=None):
+ return self.product and self.product.gift_card
+
+ @fields.depends('product', methods=['on_change_with_is_gift_card'])
+ def on_change_with_is_gift_card_service(self, name=None):
+ return (self.on_change_with_is_gift_card()
+ and self.product.type == 'service')
+
+ @classmethod
+ def view_attributes(cls):
+ return super().view_attributes() + [
+ ('//page[@id="gift_cards"]', 'states', {
+ 'invisible': ~Eval('is_gift_card_service', False),
+ }, ['is_gift_card_service']),
+ ]
+
+ def get_gift_cards(self):
+ if (not self.is_gift_card_service
+ or self.quantity < 0
+ or self.gift_cards):
+ return
+ pool = Pool()
+ GiftCard = pool.get('sale.gift_card')
+ UoM = pool.get('product.uom')
+ Config = pool.get('sale.configuration')
+ config = Config(1)
+ cards = []
+ quantity = UoM.compute_qty(
+ self.unit, self.quantity, self.product.default_uom)
+ quantity -= len(self.gift_cards)
+ quantity = max(quantity, 0)
+ unit_price = UoM.compute_price(
+ self.unit, self.unit_price, self.product.default_uom)
+ unit_price = self.sale.currency.round(unit_price)
+ for _ in range(int(quantity)):
+ card = GiftCard()
+ card.company = self.sale.company
+ sequence = config.get_multivalue(
+ 'gift_card_sequence', company=card.company.id)
+ if sequence:
+ card.number = sequence.get()
+ card.product = self.product
+ card.value = unit_price
+ card.currency = self.sale.currency
+ card.origin = self
+ cards.append(card)
+ return cards
diff --git a/modules/sale_gift_card/sale.xml b/modules/sale_gift_card/sale.xml
new file mode 100644
index 0000000000..569487d8ab
--- /dev/null
+++ b/modules/sale_gift_card/sale.xml
@@ -0,0 +1,128 @@
+
+
+
+
+
+ Gift Card Administration
+
+
+
+
+
+
+
+ Gift Card
+
+
+
+
+
+
+
+ sale.configuration
+
+ configuration_form
+
+
+
+ sale.gift_card
+ form
+ gift_card_form
+
+
+
+ sale.gift_card
+ tree
+ gift_card_list
+
+
+
+ Gift Cards
+ sale.gift_card
+
+
+
+
+
+
+
+
+
+
+
+
+ Pending
+
+
+
+
+
+
+ Sent
+
+
+
+
+
+
+ All
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ User in companies
+
+
+
+
+
+
+
+
+
+ Gift Card
+ sale.gift_card
+ sale.gift_card.email
+ sale_gift_card/email.html
+ html
+
+
+
+ sale.sale
+
+ sale_form
+
+
+
+ sale.line
+
+ sale_line_form
+
+
+
diff --git a/modules/sale_gift_card/setup.py b/modules/sale_gift_card/setup.py
new file mode 100755
index 0000000000..1172bb1315
--- /dev/null
+++ b/modules/sale_gift_card/setup.py
@@ -0,0 +1,153 @@
+#!/usr/bin/env python3
+# This file is part of Tryton. The COPYRIGHT file at the top level of
+# this repository contains the full copyright notices and license terms.
+
+import io
+import os
+import re
+from configparser import ConfigParser
+from setuptools import setup, find_packages
+
+
+def read(fname):
+ content = io.open(
+ os.path.join(os.path.dirname(__file__), fname),
+ 'r', encoding='utf-8').read()
+ content = re.sub(
+ r'(?m)^\.\. toctree::\r?\n((^$|^\s.*$)\r?\n)*', '', content)
+ return content
+
+
+def get_require_version(name):
+ if minor_version % 2:
+ require = '%s >= %s.%s.dev0, < %s.%s'
+ else:
+ require = '%s >= %s.%s, < %s.%s'
+ require %= (name, major_version, minor_version,
+ major_version, minor_version + 1)
+ return require
+
+
+config = ConfigParser()
+config.read_file(open(os.path.join(os.path.dirname(__file__), 'tryton.cfg')))
+info = dict(config.items('tryton'))
+for key in ('depends', 'extras_depend', 'xml'):
+ if key in info:
+ info[key] = info[key].strip().splitlines()
+version = info.get('version', '0.0.1')
+major_version, minor_version, _ = version.split('.', 2)
+major_version = int(major_version)
+minor_version = int(minor_version)
+name = 'trytond_sale_gift_card'
+
+download_url = 'http://downloads.tryton.org/%s.%s/' % (
+ major_version, minor_version)
+if minor_version % 2:
+ version = '%s.%s.dev0' % (major_version, minor_version)
+ download_url = (
+ 'hg+http://hg.tryton.org/modules/%s#egg=%s-%s' % (
+ name[8:], name, version))
+local_version = []
+if os.environ.get('CI_JOB_ID'):
+ local_version.append(os.environ['CI_JOB_ID'])
+else:
+ for build in ['CI_BUILD_NUMBER', 'CI_JOB_NUMBER']:
+ if os.environ.get(build):
+ local_version.append(os.environ[build])
+ else:
+ local_version = []
+ break
+if local_version:
+ version += '+' + '.'.join(local_version)
+
+requires = []
+for dep in info.get('depends', []):
+ if not re.match(r'(ir|res)(\W|$)', dep):
+ requires.append(get_require_version('trytond_%s' % dep))
+requires.append(get_require_version('trytond'))
+
+tests_require = [get_require_version('proteus')]
+dependency_links = []
+if minor_version % 2:
+ dependency_links.append(
+ 'https://trydevpi.tryton.org/?local_version='
+ + '.'.join(local_version))
+
+setup(name=name,
+ version=version,
+ description="Tryton module to manage gift cards",
+ long_description=read('README.rst'),
+ author='Tryton',
+ author_email='bugs@tryton.org',
+ url='http://www.tryton.org/',
+ download_url=download_url,
+ project_urls={
+ "Bug Tracker": 'https://bugs.tryton.org/',
+ "Documentation": 'https://docs.tryton.org/',
+ "Forum": 'https://www.tryton.org/forum',
+ "Source Code": 'https://hg.tryton.org/modules/sale_gift_card',
+ },
+ keywords='tryton sale gift card',
+ package_dir={'trytond.modules.sale_gift_card': '.'},
+ packages=(
+ ['trytond.modules.sale_gift_card']
+ + ['trytond.modules.sale_gift_card.%s' % p
+ for p in find_packages()]
+ ),
+ package_data={
+ 'trytond.modules.sale_gift_card': (info.get('xml', [])
+ + ['tryton.cfg', 'view/*.xml', 'locale/*.po', '*.fodt', '*.html',
+ 'icons/*.svg', 'tests/*.rst']),
+ },
+ classifiers=[
+ 'Development Status :: 5 - Production/Stable',
+ 'Environment :: Plugins',
+ 'Framework :: Tryton',
+ 'Intended Audience :: Developers',
+ 'Intended Audience :: Financial and Insurance Industry',
+ 'Intended Audience :: Legal Industry',
+ 'License :: OSI Approved :: '
+ 'GNU General Public License v3 or later (GPLv3+)',
+ 'Natural Language :: Bulgarian',
+ 'Natural Language :: Catalan',
+ 'Natural Language :: Chinese (Simplified)',
+ 'Natural Language :: Czech',
+ 'Natural Language :: Dutch',
+ 'Natural Language :: English',
+ 'Natural Language :: Finnish',
+ 'Natural Language :: French',
+ 'Natural Language :: German',
+ 'Natural Language :: Hungarian',
+ 'Natural Language :: Indonesian',
+ 'Natural Language :: Italian',
+ 'Natural Language :: Persian',
+ 'Natural Language :: Polish',
+ 'Natural Language :: Portuguese (Brazilian)',
+ 'Natural Language :: Romanian',
+ 'Natural Language :: Russian',
+ 'Natural Language :: Slovenian',
+ 'Natural Language :: Spanish',
+ 'Natural Language :: Turkish',
+ 'Operating System :: OS Independent',
+ 'Programming Language :: Python :: 3',
+ 'Programming Language :: Python :: 3.6',
+ 'Programming Language :: Python :: 3.7',
+ 'Programming Language :: Python :: 3.8',
+ 'Programming Language :: Python :: 3.9',
+ 'Programming Language :: Python :: Implementation :: CPython',
+ 'Programming Language :: Python :: Implementation :: PyPy',
+ 'Topic :: Office/Business',
+ ],
+ license='GPL-3',
+ python_requires='>=3.6',
+ install_requires=requires,
+ dependency_links=dependency_links,
+ zip_safe=False,
+ entry_points="""
+ [trytond.modules]
+ sale_gift_card = trytond.modules.sale_gift_card
+ """, # noqa: E501
+ test_suite='tests',
+ test_loader='trytond.test_loader:Loader',
+ tests_require=tests_require,
+ )
diff --git a/modules/sale_gift_card/stock.py b/modules/sale_gift_card/stock.py
new file mode 100644
index 0000000000..76ac58186a
--- /dev/null
+++ b/modules/sale_gift_card/stock.py
@@ -0,0 +1,57 @@
+# This file is part of Tryton. The COPYRIGHT file at the top level of
+# this repository contains the full copyright notices and license terms.
+from trytond.i18n import gettext
+from trytond.model import ModelView, Workflow, fields
+from trytond.pool import PoolMeta
+from trytond.pyson import Eval, If
+
+from .exceptions import MoveGiftCardValidationError
+
+
+class Move(metaclass=PoolMeta):
+ __name__ = 'stock.move'
+
+ gift_cards = fields.One2Many(
+ 'sale.gift_card', 'origin', "Gift Cards",
+ size=If(Eval('gift_cards_required'),
+ Eval('internal_quantity', 0), 0),
+ add_remove=[
+ ('origin', '=', None),
+ ],
+ domain=[
+ ('company', '=', Eval('company', -1)),
+ ('product', '=', Eval('product', -1)),
+ ],
+ states={
+ 'invisible': ~Eval('gift_cards_required', []),
+ 'required': (
+ Eval('gift_cards_required', False)
+ & (Eval('state') == 'done')),
+ 'readonly': Eval('state').in_(['cancel', 'done']),
+ },
+ depends=[
+ 'gift_cards_required', 'internal_quantity', 'company', 'product',
+ 'state'])
+ gift_cards_required = fields.Function(
+ fields.Boolean("Gift Cards Required"),
+ 'on_change_with_gift_cards_required')
+
+ @fields.depends('product', 'to_location')
+ def on_change_with_gift_cards_required(self, name=None):
+ return (
+ self.product and self.product.gift_card
+ and self.to_location and self.to_location.type == 'customer')
+
+ @classmethod
+ @ModelView.button
+ @Workflow.transition('done')
+ def do(cls, moves):
+ for move in moves:
+ if not move.gift_cards_required:
+ continue
+ if len(move.gift_cards) != move.internal_quantity:
+ raise MoveGiftCardValidationError(
+ gettext('sale_gift_card.msg_gift_card_move_quantity',
+ move=move.rec_name,
+ quantity=move.internal_quantity))
+ super().do(moves)
diff --git a/modules/sale_gift_card/stock.xml b/modules/sale_gift_card/stock.xml
new file mode 100644
index 0000000000..73d6fed0bd
--- /dev/null
+++ b/modules/sale_gift_card/stock.xml
@@ -0,0 +1,12 @@
+
+
+
+
+
+ stock.move
+
+ move_form
+
+
+
diff --git a/modules/sale_gift_card/tests/__init__.py b/modules/sale_gift_card/tests/__init__.py
new file mode 100644
index 0000000000..243eb5f080
--- /dev/null
+++ b/modules/sale_gift_card/tests/__init__.py
@@ -0,0 +1,9 @@
+# This file is part of Tryton. The COPYRIGHT file at the top level of
+# this repository contains the full copyright notices and license terms.
+
+try:
+ from trytond.modules.sale_gift_card.tests.test_sale_gift_card import suite # noqa: E501
+except ImportError:
+ from .test_sale_gift_card import suite
+
+__all__ = ['suite']
diff --git a/modules/sale_gift_card/tests/scenario_sale_gift_card.rst b/modules/sale_gift_card/tests/scenario_sale_gift_card.rst
new file mode 100644
index 0000000000..7fcaa77558
--- /dev/null
+++ b/modules/sale_gift_card/tests/scenario_sale_gift_card.rst
@@ -0,0 +1,193 @@
+=======================
+Sale Gift Card Scenario
+=======================
+
+Imports::
+
+ >>> import re
+ >>> from decimal import Decimal
+ >>> from proteus import Model
+ >>> from trytond.tests.tools import activate_modules
+ >>> from trytond.modules.company.tests.tools import (
+ ... create_company, get_company)
+ >>> from trytond.modules.account.tests.tools import (
+ ... create_fiscalyear, create_chart, get_accounts)
+
+Patch sendmail_transactional::
+
+ >>> from unittest.mock import patch
+ >>> from trytond.modules.sale_gift_card import sale
+ >>> smtp_calls = patch.object(
+ ... sale, 'sendmail_transactional').start()
+
+Activate modules::
+
+ >>> config = activate_modules('sale_gift_card')
+
+ >>> Account = Model.get('account.account')
+ >>> AccountConfig = Model.get('account.configuration')
+ >>> GiftCard = Model.get('sale.gift_card')
+ >>> Party = Model.get('party.party')
+ >>> ProductCategory = Model.get('product.category')
+ >>> ProductTemplate = Model.get('product.template')
+ >>> ProductUoM = Model.get('product.uom')
+ >>> Sale = Model.get('sale.sale')
+ >>> SaleConfig = Model.get('sale.configuration')
+ >>> Sequence = Model.get('ir.sequence')
+ >>> SequenceType = Model.get('ir.sequence.type')
+
+Create company::
+
+ >>> _ = create_company()
+ >>> company = get_company()
+
+Create chart of accounts::
+
+ >>> _ = create_chart(company)
+ >>> accounts = get_accounts(company)
+
+Setup gift card accounting::
+
+ >>> gift_card_type, = accounts['payable'].type.duplicate(
+ ... {'gift_card': True})
+ >>> gift_card_revenue = Account(name="Gift Card")
+ >>> gift_card_revenue.type = gift_card_type
+ >>> gift_card_revenue.deferral = True
+ >>> gift_card_revenue.save()
+ >>> account_config = AccountConfig(1)
+ >>> account_config.gift_card_account_revenue = gift_card_revenue
+ >>> account_config.save()
+
+Set gift card sequence::
+
+ >>> sale_config = SaleConfig(1)
+ >>> gift_card_sequence = Sequence(name="Gift Card")
+ >>> gift_card_sequence.sequence_type, = SequenceType.find([
+ ... ('name', '=', "Gift Card"),
+ ... ])
+ >>> gift_card_sequence.type = 'hexadecimal timestamp'
+ >>> gift_card_sequence.save()
+ >>> sale_config.gift_card_sequence = gift_card_sequence
+ >>> sale_config.save()
+
+Create gift card product::
+
+ >>> unit, = ProductUoM.find([('name', '=', "Unit")])
+
+ >>> template = ProductTemplate()
+ >>> template.name = "Gift Card"
+ >>> template.type = 'service'
+ >>> template.default_uom = unit
+ >>> template.salable = True
+ >>> template.gift_card = True
+ >>> template.list_price = Decimal('50')
+ >>> template.save()
+ >>> gift_card, = template.products
+
+Create account category::
+
+ >>> account_category = ProductCategory(name="Account Category")
+ >>> account_category.accounting = True
+ >>> account_category.account_expense = accounts['expense']
+ >>> account_category.account_revenue = accounts['revenue']
+ >>> account_category.save()
+
+Create a product::
+
+ >>> template = ProductTemplate()
+ >>> template.name = "Product"
+ >>> template.default_uom = unit
+ >>> template.salable = True
+ >>> template.list_price = Decimal('100')
+ >>> template.account_category = account_category
+ >>> template.save()
+ >>> product, = template.products
+
+Create parties::
+
+ >>> customer1 = Party(name='Customer 1')
+ >>> customer1.save()
+ >>> customer2 = Party(name='Customer 2')
+ >>> customer2.save()
+
+Sell 2 gift cards::
+
+ >>> sale = Sale()
+ >>> sale.party = customer1
+ >>> line = sale.lines.new()
+ >>> line.product = gift_card
+ >>> line.quantity = 2
+ >>> line.gift_card_email = "customer@example.com"
+ >>> sale.click('quote')
+ >>> sale.click('confirm')
+ >>> sale.state
+ 'processing'
+
+Check gift cards::
+
+ >>> cards = GiftCard.find([])
+ >>> len(cards)
+ 2
+ >>> card = cards[-1]
+ >>> card.product == gift_card
+ True
+ >>> card.value
+ Decimal('50.00')
+ >>> bool(card.origin)
+ True
+ >>> bool(card.spent_on)
+ False
+ >>> smtp_calls.call_count
+ 2
+ >>> from_, to, msg = smtp_calls.call_args[0]
+ >>> to
+ ['customer@example.com']
+ >>> msg = msg.get_payload(0).get_payload(decode=True).decode('utf-8')
+ >>> card.number in msg
+ True
+
+Check invoice::
+
+ >>> invoice, = sale.invoices
+ >>> line, = invoice.lines
+ >>> line.account == gift_card_revenue
+ True
+
+Redeem a gift card to buy a product::
+
+ >>> sale = Sale()
+ >>> sale.party = customer2
+ >>> line = sale.lines.new()
+ >>> line.product = product
+ >>> line.quantity = 1
+ >>> sale.gift_cards.append(GiftCard(card.id))
+ >>> sale.save()
+ >>> sale.total_amount
+ Decimal('100.00')
+ >>> sale.click('quote')
+ >>> len(sale.lines)
+ 2
+ >>> sale.total_amount
+ Decimal('50.00')
+ >>> sale.click('confirm')
+ >>> sale.state
+ 'processing'
+
+Check gift card::
+
+ >>> card.reload()
+ >>> card.spent_on == sale
+ True
+
+Check the invoice::
+
+ >>> invoice, = sale.invoices
+ >>> len(invoice.lines)
+ 2
+ >>> invoice.total_amount
+ Decimal('50.00')
+ >>> gift_card_line, = [l for l in invoice.lines if l.product == gift_card]
+ >>> gift_card_line.quantity
+ -1.0
+ >>> gift_card_line.account == gift_card_revenue
+ True
diff --git a/modules/sale_gift_card/tests/scenario_sale_gift_card_goods.rst b/modules/sale_gift_card/tests/scenario_sale_gift_card_goods.rst
new file mode 100644
index 0000000000..f4101fbf69
--- /dev/null
+++ b/modules/sale_gift_card/tests/scenario_sale_gift_card_goods.rst
@@ -0,0 +1,131 @@
+=============================
+Sale Gift Card Goods Scenario
+=============================
+
+Imports::
+
+ >>> from decimal import Decimal
+ >>> from proteus import Model
+ >>> from trytond.tests.tools import activate_modules
+ >>> from trytond.modules.company.tests.tools import (
+ ... create_company, get_company)
+ >>> from trytond.modules.account.tests.tools import (
+ ... create_fiscalyear, create_chart, get_accounts)
+
+Activate modules::
+
+ >>> config = activate_modules('sale_gift_card')
+
+ >>> Account = Model.get('account.account')
+ >>> AccountConfig = Model.get('account.configuration')
+ >>> GiftCard = Model.get('sale.gift_card')
+ >>> Party = Model.get('party.party')
+ >>> ProductCategory = Model.get('product.category')
+ >>> ProductTemplate = Model.get('product.template')
+ >>> ProductUoM = Model.get('product.uom')
+ >>> Sale = Model.get('sale.sale')
+
+Create company::
+
+ >>> _ = create_company()
+ >>> company = get_company()
+
+Create chart of accounts::
+
+ >>> _ = create_chart(company)
+ >>> accounts = get_accounts(company)
+
+Setup gift card accounting::
+
+ >>> gift_card_type, = accounts['payable'].type.duplicate(
+ ... {'gift_card': True})
+ >>> gift_card_revenue = Account(name="Gift Card")
+ >>> gift_card_revenue.type = gift_card_type
+ >>> gift_card_revenue.deferral = True
+ >>> gift_card_revenue.save()
+ >>> account_config = AccountConfig(1)
+ >>> account_config.gift_card_account_revenue = gift_card_revenue
+ >>> account_config.save()
+
+Create gift card product::
+
+ >>> unit, = ProductUoM.find([('name', '=', "Unit")])
+
+ >>> template = ProductTemplate()
+ >>> template.name = "Gift Card"
+ >>> template.type = 'goods'
+ >>> template.default_uom = unit
+ >>> template.salable = True
+ >>> template.gift_card = True
+ >>> template.list_price = Decimal('20')
+ >>> template.save()
+ >>> gift_card, = template.products
+
+Create account category::
+
+ >>> account_category = ProductCategory(name="Account Category")
+ >>> account_category.accounting = True
+ >>> account_category.account_expense = accounts['expense']
+ >>> account_category.account_revenue = accounts['revenue']
+ >>> account_category.save()
+
+Create a product::
+
+ >>> template = ProductTemplate()
+ >>> template.name = "Product"
+ >>> template.default_uom = unit
+ >>> template.salable = True
+ >>> template.list_price = Decimal('100')
+ >>> template.account_category = account_category
+ >>> template.save()
+ >>> product, = template.products
+
+Create parties::
+
+ >>> customer1 = Party(name='Customer 1')
+ >>> customer1.save()
+ >>> customer2 = Party(name='Customer 2')
+ >>> customer2.save()
+
+Sell 1 gift cards::
+
+ >>> sale = Sale()
+ >>> sale.party = customer1
+ >>> line = sale.lines.new()
+ >>> line.product = gift_card
+ >>> line.quantity = 1
+ >>> sale.click('quote')
+ >>> sale.click('confirm')
+ >>> sale.state
+ 'processing'
+
+Check gift cards::
+
+ >>> cards = GiftCard.find([])
+ >>> len(cards)
+ 0
+
+Check invoice::
+
+ >>> invoice, = sale.invoices
+ >>> line, = invoice.lines
+ >>> line.account == gift_card_revenue
+ True
+
+Ship the gift card::
+
+ >>> shipment, = sale.shipments
+ >>> shipment.click('assign_force')
+ >>> shipment.click('pick')
+ >>> shipment.click('pack')
+ >>> shipment.click('done') # doctest: +IGNORE_EXCEPTION_DETAIL
+ Traceback (most recent call last):
+ ...
+ MoveGiftCardValidationError: ...
+ >>> move, = shipment.outgoing_moves
+ >>> gift_card = move.gift_cards.new(product=gift_card)
+ >>> gift_card.number = "1234"
+ >>> gift_card.value
+ Decimal('20.00')
+ >>> move.save()
+ >>> shipment.click('done')
diff --git a/modules/sale_gift_card/tests/test_sale_gift_card.py b/modules/sale_gift_card/tests/test_sale_gift_card.py
new file mode 100644
index 0000000000..e57739500a
--- /dev/null
+++ b/modules/sale_gift_card/tests/test_sale_gift_card.py
@@ -0,0 +1,35 @@
+# This file is part of Tryton. The COPYRIGHT file at the top level of
+# this repository contains the full copyright notices and license terms.
+
+import unittest
+
+import doctest
+
+from trytond.tests.test_tryton import ModuleTestCase
+from trytond.tests.test_tryton import suite as test_suite
+from trytond.tests.test_tryton import doctest_teardown
+from trytond.tests.test_tryton import doctest_checker
+
+from trytond.modules.company.tests import CompanyTestMixin
+
+
+class SaleGiftCardTestCase(CompanyTestMixin, ModuleTestCase):
+ 'Test Sale Gift Card module'
+ module = 'sale_gift_card'
+
+
+def suite():
+ suite = test_suite()
+ suite.addTests(unittest.TestLoader().loadTestsFromTestCase(
+ SaleGiftCardTestCase))
+ suite.addTests(doctest.DocFileSuite(
+ 'scenario_sale_gift_card.rst',
+ tearDown=doctest_teardown, encoding='utf-8',
+ checker=doctest_checker,
+ optionflags=doctest.REPORT_ONLY_FIRST_FAILURE))
+ suite.addTests(doctest.DocFileSuite(
+ 'scenario_sale_gift_card_goods.rst',
+ tearDown=doctest_teardown, encoding='utf-8',
+ checker=doctest_checker,
+ optionflags=doctest.REPORT_ONLY_FIRST_FAILURE))
+ return suite
diff --git a/modules/sale_gift_card/tox.ini b/modules/sale_gift_card/tox.ini
new file mode 100644
index 0000000000..197496c0cb
--- /dev/null
+++ b/modules/sale_gift_card/tox.ini
@@ -0,0 +1,15 @@
+[tox]
+envlist = {py36,py37,py38,py39}-{sqlite,postgresql},pypy3-{sqlite,postgresql}
+
+[testenv]
+commands = {envpython} setup.py test
+deps =
+ {py36,py37,py38,py39}-postgresql: psycopg2 >= 2.5
+ pypy3-postgresql: psycopg2cffi >= 2.5
+ py36-sqlite: sqlitebck
+setenv =
+ sqlite: TRYTOND_DATABASE_URI={env:SQLITE_URI:sqlite://}
+ postgresql: TRYTOND_DATABASE_URI={env:POSTGRESQL_URI:postgresql://}
+ sqlite: DB_NAME={env:SQLITE_NAME::memory:}
+ postgresql: DB_NAME={env:POSTGRESQL_NAME:test}
+install_command = pip install --pre --find-links https://trydevpi.tryton.org/?local_version={env:CI_JOB_ID:{env:CI_BUILD_NUMBER}.{env:CI_JOB_NUMBER}} {opts} {packages}
diff --git a/modules/sale_gift_card/tryton.cfg b/modules/sale_gift_card/tryton.cfg
new file mode 100644
index 0000000000..128c8b5fc9
--- /dev/null
+++ b/modules/sale_gift_card/tryton.cfg
@@ -0,0 +1,16 @@
+[tryton]
+version=6.0.5
+depends:
+ account
+ account_invoice
+ company
+ ir
+ product
+ sale
+ stock
+xml:
+ account.xml
+ product.xml
+ sale.xml
+ stock.xml
+ message.xml
diff --git a/modules/sale_gift_card/view/account_configuration_form.xml b/modules/sale_gift_card/view/account_configuration_form.xml
new file mode 100644
index 0000000000..d1f3a0c9d9
--- /dev/null
+++ b/modules/sale_gift_card/view/account_configuration_form.xml
@@ -0,0 +1,12 @@
+
+
+
+
+
+
+
+
+
+
+
diff --git a/modules/sale_gift_card/view/account_type_form.xml b/modules/sale_gift_card/view/account_type_form.xml
new file mode 100644
index 0000000000..36ba22e0c1
--- /dev/null
+++ b/modules/sale_gift_card/view/account_type_form.xml
@@ -0,0 +1,9 @@
+
+
+
+
+
+
+
+
diff --git a/modules/sale_gift_card/view/configuration_form.xml b/modules/sale_gift_card/view/configuration_form.xml
new file mode 100644
index 0000000000..004efeaa6a
--- /dev/null
+++ b/modules/sale_gift_card/view/configuration_form.xml
@@ -0,0 +1,9 @@
+
+
+
+
+
+
+
+
diff --git a/modules/sale_gift_card/view/gift_card_form.xml b/modules/sale_gift_card/view/gift_card_form.xml
new file mode 100644
index 0000000000..6c78b78118
--- /dev/null
+++ b/modules/sale_gift_card/view/gift_card_form.xml
@@ -0,0 +1,23 @@
+
+
+
diff --git a/modules/sale_gift_card/view/gift_card_list.xml b/modules/sale_gift_card/view/gift_card_list.xml
new file mode 100644
index 0000000000..87bd2fd5fe
--- /dev/null
+++ b/modules/sale_gift_card/view/gift_card_list.xml
@@ -0,0 +1,10 @@
+
+
+
+
+
+
+
+
+
diff --git a/modules/sale_gift_card/view/move_form.xml b/modules/sale_gift_card/view/move_form.xml
new file mode 100644
index 0000000000..42a7b10a4f
--- /dev/null
+++ b/modules/sale_gift_card/view/move_form.xml
@@ -0,0 +1,8 @@
+
+
+
+
+
+
+
diff --git a/modules/sale_gift_card/view/sale_form.xml b/modules/sale_gift_card/view/sale_form.xml
new file mode 100644
index 0000000000..c651731afc
--- /dev/null
+++ b/modules/sale_gift_card/view/sale_form.xml
@@ -0,0 +1,10 @@
+
+
+
+
+
+
+
+
+
diff --git a/modules/sale_gift_card/view/sale_line_form.xml b/modules/sale_gift_card/view/sale_line_form.xml
new file mode 100644
index 0000000000..3cdf6f61fe
--- /dev/null
+++ b/modules/sale_gift_card/view/sale_line_form.xml
@@ -0,0 +1,12 @@
+
+
+
+
+
+
+
+
+
+
+
diff --git a/modules/sale_gift_card/view/template_form.xml b/modules/sale_gift_card/view/template_form.xml
new file mode 100644
index 0000000000..7c39ad037c
--- /dev/null
+++ b/modules/sale_gift_card/view/template_form.xml
@@ -0,0 +1,9 @@
+
+
+
+
+
+
+
+
diff --git a/modules/sale_history/.drone.yml b/modules/sale_history/.drone.yml
new file mode 100644
index 0000000000..2049d30a49
--- /dev/null
+++ b/modules/sale_history/.drone.yml
@@ -0,0 +1,68 @@
+clone:
+ hg:
+ image: plugins/hg
+ environment:
+ - HG_SHARE_POOL=/root/.cache/hg
+ volumes:
+ - cache:/root/.cache
+
+pipeline:
+ tox:
+ image: ${IMAGE}
+ environment:
+ - CFLAGS=-O0
+ - DB_CACHE=/cache
+ - TOX_TESTENV_PASSENV=CFLAGS DB_CACHE CI_BUILD_NUMBER CI_JOB_NUMBER CI_JOB_ID
+ - POSTGRESQL_URI=postgresql://postgres@postgresql:5432/
+ commands:
+ - echo "[extensions]" >> /root/.hgrc
+ - echo "hgext.share =" >> /root/.hgrc
+ - echo "[share]" >> /root/.hgrc
+ - echo "pool = /root/.cache/hg" >> /root/.hgrc
+ - pip install tox
+ - tox -e "${TOXENV}-${DATABASE}"
+ volumes:
+ - cache:/root/.cache
+ check_dist:
+ image: ${IMAGE}
+ commands:
+ - pip install twine
+ - python setup.py sdist
+ - twine check dist/*
+
+services:
+ postgresql:
+ image: postgres
+ environment:
+ - POSTGRES_HOST_AUTH_METHOD=trust
+ command: "-c fsync=off -c synchronous_commit=off -c full_page_writes=off"
+ when:
+ matrix:
+ DATABASE: postgresql
+
+matrix:
+ include:
+ - IMAGE: python:3.6
+ TOXENV: py36
+ DATABASE: sqlite
+ - IMAGE: python:3.6
+ TOXENV: py36
+ DATABASE: postgresql
+ - IMAGE: python:3.7
+ TOXENV: py37
+ DATABASE: sqlite
+ - IMAGE: python:3.7
+ TOXENV: py37
+ DATABASE: postgresql
+ - IMAGE: python:3.8
+ TOXENV: py38
+ DATABASE: sqlite
+ - IMAGE: python:3.8
+ TOXENV: py38
+ DATABASE: postgresql
+ - IMAGE: python:3.9
+ TOXENV: py39
+ DATABASE: sqlite
+ - IMAGE: python:3.9
+ TOXENV: py39
+ DATABASE: postgresql
diff --git a/modules/sale_history/.flake8 b/modules/sale_history/.flake8
new file mode 100644
index 0000000000..fa6b4f66d1
--- /dev/null
+++ b/modules/sale_history/.flake8
@@ -0,0 +1,2 @@
+[flake8]
+ignore=E123,E124,E126,E128,E741,W503
diff --git a/modules/sale_history/CHANGELOG b/modules/sale_history/CHANGELOG
new file mode 100644
index 0000000000..aa4a76f66d
--- /dev/null
+++ b/modules/sale_history/CHANGELOG
@@ -0,0 +1,12 @@
+Version 6.0.0 - 2021-05-03
+* Bug fixes (see mercurial logs for details)
+
+Version 5.8.0 - 2020-11-02
+* Bug fixes (see mercurial logs for details)
+* Remove support for Python 3.5
+
+Version 5.6.0 - 2020-05-04
+* Bug fixes (see mercurial logs for details)
+
+Version 5.4.0 - 2019-11-04
+* Initial release
diff --git a/modules/sale_history/COPYRIGHT b/modules/sale_history/COPYRIGHT
new file mode 100644
index 0000000000..19132a3810
--- /dev/null
+++ b/modules/sale_history/COPYRIGHT
@@ -0,0 +1,15 @@
+Copyright (C) 2019-2021 B2CK
+Copyright (C) 2019-2021 Cédric Krier
+
+This program is free software: you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation, either version 3 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program. If not, see .
diff --git a/modules/sale_history/LICENSE b/modules/sale_history/LICENSE
new file mode 100644
index 0000000000..94a9ed024d
--- /dev/null
+++ b/modules/sale_history/LICENSE
@@ -0,0 +1,674 @@
+ GNU GENERAL PUBLIC LICENSE
+ Version 3, 29 June 2007
+
+ Copyright (C) 2007 Free Software Foundation, Inc.
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+ Preamble
+
+ The GNU General Public License is a free, copyleft license for
+software and other kinds of works.
+
+ The licenses for most software and other practical works are designed
+to take away your freedom to share and change the works. By contrast,
+the GNU General Public License is intended to guarantee your freedom to
+share and change all versions of a program--to make sure it remains free
+software for all its users. We, the Free Software Foundation, use the
+GNU General Public License for most of our software; it applies also to
+any other work released this way by its authors. You can apply it to
+your programs, too.
+
+ When we speak of free software, we are referring to freedom, not
+price. Our General Public Licenses are designed to make sure that you
+have the freedom to distribute copies of free software (and charge for
+them if you wish), that you receive source code or can get it if you
+want it, that you can change the software or use pieces of it in new
+free programs, and that you know you can do these things.
+
+ To protect your rights, we need to prevent others from denying you
+these rights or asking you to surrender the rights. Therefore, you have
+certain responsibilities if you distribute copies of the software, or if
+you modify it: responsibilities to respect the freedom of others.
+
+ For example, if you distribute copies of such a program, whether
+gratis or for a fee, you must pass on to the recipients the same
+freedoms that you received. You must make sure that they, too, receive
+or can get the source code. And you must show them these terms so they
+know their rights.
+
+ Developers that use the GNU GPL protect your rights with two steps:
+(1) assert copyright on the software, and (2) offer you this License
+giving you legal permission to copy, distribute and/or modify it.
+
+ For the developers' and authors' protection, the GPL clearly explains
+that there is no warranty for this free software. For both users' and
+authors' sake, the GPL requires that modified versions be marked as
+changed, so that their problems will not be attributed erroneously to
+authors of previous versions.
+
+ Some devices are designed to deny users access to install or run
+modified versions of the software inside them, although the manufacturer
+can do so. This is fundamentally incompatible with the aim of
+protecting users' freedom to change the software. The systematic
+pattern of such abuse occurs in the area of products for individuals to
+use, which is precisely where it is most unacceptable. Therefore, we
+have designed this version of the GPL to prohibit the practice for those
+products. If such problems arise substantially in other domains, we
+stand ready to extend this provision to those domains in future versions
+of the GPL, as needed to protect the freedom of users.
+
+ Finally, every program is threatened constantly by software patents.
+States should not allow patents to restrict development and use of
+software on general-purpose computers, but in those that do, we wish to
+avoid the special danger that patents applied to a free program could
+make it effectively proprietary. To prevent this, the GPL assures that
+patents cannot be used to render the program non-free.
+
+ The precise terms and conditions for copying, distribution and
+modification follow.
+
+ TERMS AND CONDITIONS
+
+ 0. Definitions.
+
+ "This License" refers to version 3 of the GNU General Public License.
+
+ "Copyright" also means copyright-like laws that apply to other kinds of
+works, such as semiconductor masks.
+
+ "The Program" refers to any copyrightable work licensed under this
+License. Each licensee is addressed as "you". "Licensees" and
+"recipients" may be individuals or organizations.
+
+ To "modify" a work means to copy from or adapt all or part of the work
+in a fashion requiring copyright permission, other than the making of an
+exact copy. The resulting work is called a "modified version" of the
+earlier work or a work "based on" the earlier work.
+
+ A "covered work" means either the unmodified Program or a work based
+on the Program.
+
+ To "propagate" a work means to do anything with it that, without
+permission, would make you directly or secondarily liable for
+infringement under applicable copyright law, except executing it on a
+computer or modifying a private copy. Propagation includes copying,
+distribution (with or without modification), making available to the
+public, and in some countries other activities as well.
+
+ To "convey" a work means any kind of propagation that enables other
+parties to make or receive copies. Mere interaction with a user through
+a computer network, with no transfer of a copy, is not conveying.
+
+ An interactive user interface displays "Appropriate Legal Notices"
+to the extent that it includes a convenient and prominently visible
+feature that (1) displays an appropriate copyright notice, and (2)
+tells the user that there is no warranty for the work (except to the
+extent that warranties are provided), that licensees may convey the
+work under this License, and how to view a copy of this License. If
+the interface presents a list of user commands or options, such as a
+menu, a prominent item in the list meets this criterion.
+
+ 1. Source Code.
+
+ The "source code" for a work means the preferred form of the work
+for making modifications to it. "Object code" means any non-source
+form of a work.
+
+ A "Standard Interface" means an interface that either is an official
+standard defined by a recognized standards body, or, in the case of
+interfaces specified for a particular programming language, one that
+is widely used among developers working in that language.
+
+ The "System Libraries" of an executable work include anything, other
+than the work as a whole, that (a) is included in the normal form of
+packaging a Major Component, but which is not part of that Major
+Component, and (b) serves only to enable use of the work with that
+Major Component, or to implement a Standard Interface for which an
+implementation is available to the public in source code form. A
+"Major Component", in this context, means a major essential component
+(kernel, window system, and so on) of the specific operating system
+(if any) on which the executable work runs, or a compiler used to
+produce the work, or an object code interpreter used to run it.
+
+ The "Corresponding Source" for a work in object code form means all
+the source code needed to generate, install, and (for an executable
+work) run the object code and to modify the work, including scripts to
+control those activities. However, it does not include the work's
+System Libraries, or general-purpose tools or generally available free
+programs which are used unmodified in performing those activities but
+which are not part of the work. For example, Corresponding Source
+includes interface definition files associated with source files for
+the work, and the source code for shared libraries and dynamically
+linked subprograms that the work is specifically designed to require,
+such as by intimate data communication or control flow between those
+subprograms and other parts of the work.
+
+ The Corresponding Source need not include anything that users
+can regenerate automatically from other parts of the Corresponding
+Source.
+
+ The Corresponding Source for a work in source code form is that
+same work.
+
+ 2. Basic Permissions.
+
+ All rights granted under this License are granted for the term of
+copyright on the Program, and are irrevocable provided the stated
+conditions are met. This License explicitly affirms your unlimited
+permission to run the unmodified Program. The output from running a
+covered work is covered by this License only if the output, given its
+content, constitutes a covered work. This License acknowledges your
+rights of fair use or other equivalent, as provided by copyright law.
+
+ You may make, run and propagate covered works that you do not
+convey, without conditions so long as your license otherwise remains
+in force. You may convey covered works to others for the sole purpose
+of having them make modifications exclusively for you, or provide you
+with facilities for running those works, provided that you comply with
+the terms of this License in conveying all material for which you do
+not control copyright. Those thus making or running the covered works
+for you must do so exclusively on your behalf, under your direction
+and control, on terms that prohibit them from making any copies of
+your copyrighted material outside their relationship with you.
+
+ Conveying under any other circumstances is permitted solely under
+the conditions stated below. Sublicensing is not allowed; section 10
+makes it unnecessary.
+
+ 3. Protecting Users' Legal Rights From Anti-Circumvention Law.
+
+ No covered work shall be deemed part of an effective technological
+measure under any applicable law fulfilling obligations under article
+11 of the WIPO copyright treaty adopted on 20 December 1996, or
+similar laws prohibiting or restricting circumvention of such
+measures.
+
+ When you convey a covered work, you waive any legal power to forbid
+circumvention of technological measures to the extent such circumvention
+is effected by exercising rights under this License with respect to
+the covered work, and you disclaim any intention to limit operation or
+modification of the work as a means of enforcing, against the work's
+users, your or third parties' legal rights to forbid circumvention of
+technological measures.
+
+ 4. Conveying Verbatim Copies.
+
+ You may convey verbatim copies of the Program's source code as you
+receive it, in any medium, provided that you conspicuously and
+appropriately publish on each copy an appropriate copyright notice;
+keep intact all notices stating that this License and any
+non-permissive terms added in accord with section 7 apply to the code;
+keep intact all notices of the absence of any warranty; and give all
+recipients a copy of this License along with the Program.
+
+ You may charge any price or no price for each copy that you convey,
+and you may offer support or warranty protection for a fee.
+
+ 5. Conveying Modified Source Versions.
+
+ You may convey a work based on the Program, or the modifications to
+produce it from the Program, in the form of source code under the
+terms of section 4, provided that you also meet all of these conditions:
+
+ a) The work must carry prominent notices stating that you modified
+ it, and giving a relevant date.
+
+ b) The work must carry prominent notices stating that it is
+ released under this License and any conditions added under section
+ 7. This requirement modifies the requirement in section 4 to
+ "keep intact all notices".
+
+ c) You must license the entire work, as a whole, under this
+ License to anyone who comes into possession of a copy. This
+ License will therefore apply, along with any applicable section 7
+ additional terms, to the whole of the work, and all its parts,
+ regardless of how they are packaged. This License gives no
+ permission to license the work in any other way, but it does not
+ invalidate such permission if you have separately received it.
+
+ d) If the work has interactive user interfaces, each must display
+ Appropriate Legal Notices; however, if the Program has interactive
+ interfaces that do not display Appropriate Legal Notices, your
+ work need not make them do so.
+
+ A compilation of a covered work with other separate and independent
+works, which are not by their nature extensions of the covered work,
+and which are not combined with it such as to form a larger program,
+in or on a volume of a storage or distribution medium, is called an
+"aggregate" if the compilation and its resulting copyright are not
+used to limit the access or legal rights of the compilation's users
+beyond what the individual works permit. Inclusion of a covered work
+in an aggregate does not cause this License to apply to the other
+parts of the aggregate.
+
+ 6. Conveying Non-Source Forms.
+
+ You may convey a covered work in object code form under the terms
+of sections 4 and 5, provided that you also convey the
+machine-readable Corresponding Source under the terms of this License,
+in one of these ways:
+
+ a) Convey the object code in, or embodied in, a physical product
+ (including a physical distribution medium), accompanied by the
+ Corresponding Source fixed on a durable physical medium
+ customarily used for software interchange.
+
+ b) Convey the object code in, or embodied in, a physical product
+ (including a physical distribution medium), accompanied by a
+ written offer, valid for at least three years and valid for as
+ long as you offer spare parts or customer support for that product
+ model, to give anyone who possesses the object code either (1) a
+ copy of the Corresponding Source for all the software in the
+ product that is covered by this License, on a durable physical
+ medium customarily used for software interchange, for a price no
+ more than your reasonable cost of physically performing this
+ conveying of source, or (2) access to copy the
+ Corresponding Source from a network server at no charge.
+
+ c) Convey individual copies of the object code with a copy of the
+ written offer to provide the Corresponding Source. This
+ alternative is allowed only occasionally and noncommercially, and
+ only if you received the object code with such an offer, in accord
+ with subsection 6b.
+
+ d) Convey the object code by offering access from a designated
+ place (gratis or for a charge), and offer equivalent access to the
+ Corresponding Source in the same way through the same place at no
+ further charge. You need not require recipients to copy the
+ Corresponding Source along with the object code. If the place to
+ copy the object code is a network server, the Corresponding Source
+ may be on a different server (operated by you or a third party)
+ that supports equivalent copying facilities, provided you maintain
+ clear directions next to the object code saying where to find the
+ Corresponding Source. Regardless of what server hosts the
+ Corresponding Source, you remain obligated to ensure that it is
+ available for as long as needed to satisfy these requirements.
+
+ e) Convey the object code using peer-to-peer transmission, provided
+ you inform other peers where the object code and Corresponding
+ Source of the work are being offered to the general public at no
+ charge under subsection 6d.
+
+ A separable portion of the object code, whose source code is excluded
+from the Corresponding Source as a System Library, need not be
+included in conveying the object code work.
+
+ A "User Product" is either (1) a "consumer product", which means any
+tangible personal property which is normally used for personal, family,
+or household purposes, or (2) anything designed or sold for incorporation
+into a dwelling. In determining whether a product is a consumer product,
+doubtful cases shall be resolved in favor of coverage. For a particular
+product received by a particular user, "normally used" refers to a
+typical or common use of that class of product, regardless of the status
+of the particular user or of the way in which the particular user
+actually uses, or expects or is expected to use, the product. A product
+is a consumer product regardless of whether the product has substantial
+commercial, industrial or non-consumer uses, unless such uses represent
+the only significant mode of use of the product.
+
+ "Installation Information" for a User Product means any methods,
+procedures, authorization keys, or other information required to install
+and execute modified versions of a covered work in that User Product from
+a modified version of its Corresponding Source. The information must
+suffice to ensure that the continued functioning of the modified object
+code is in no case prevented or interfered with solely because
+modification has been made.
+
+ If you convey an object code work under this section in, or with, or
+specifically for use in, a User Product, and the conveying occurs as
+part of a transaction in which the right of possession and use of the
+User Product is transferred to the recipient in perpetuity or for a
+fixed term (regardless of how the transaction is characterized), the
+Corresponding Source conveyed under this section must be accompanied
+by the Installation Information. But this requirement does not apply
+if neither you nor any third party retains the ability to install
+modified object code on the User Product (for example, the work has
+been installed in ROM).
+
+ The requirement to provide Installation Information does not include a
+requirement to continue to provide support service, warranty, or updates
+for a work that has been modified or installed by the recipient, or for
+the User Product in which it has been modified or installed. Access to a
+network may be denied when the modification itself materially and
+adversely affects the operation of the network or violates the rules and
+protocols for communication across the network.
+
+ Corresponding Source conveyed, and Installation Information provided,
+in accord with this section must be in a format that is publicly
+documented (and with an implementation available to the public in
+source code form), and must require no special password or key for
+unpacking, reading or copying.
+
+ 7. Additional Terms.
+
+ "Additional permissions" are terms that supplement the terms of this
+License by making exceptions from one or more of its conditions.
+Additional permissions that are applicable to the entire Program shall
+be treated as though they were included in this License, to the extent
+that they are valid under applicable law. If additional permissions
+apply only to part of the Program, that part may be used separately
+under those permissions, but the entire Program remains governed by
+this License without regard to the additional permissions.
+
+ When you convey a copy of a covered work, you may at your option
+remove any additional permissions from that copy, or from any part of
+it. (Additional permissions may be written to require their own
+removal in certain cases when you modify the work.) You may place
+additional permissions on material, added by you to a covered work,
+for which you have or can give appropriate copyright permission.
+
+ Notwithstanding any other provision of this License, for material you
+add to a covered work, you may (if authorized by the copyright holders of
+that material) supplement the terms of this License with terms:
+
+ a) Disclaiming warranty or limiting liability differently from the
+ terms of sections 15 and 16 of this License; or
+
+ b) Requiring preservation of specified reasonable legal notices or
+ author attributions in that material or in the Appropriate Legal
+ Notices displayed by works containing it; or
+
+ c) Prohibiting misrepresentation of the origin of that material, or
+ requiring that modified versions of such material be marked in
+ reasonable ways as different from the original version; or
+
+ d) Limiting the use for publicity purposes of names of licensors or
+ authors of the material; or
+
+ e) Declining to grant rights under trademark law for use of some
+ trade names, trademarks, or service marks; or
+
+ f) Requiring indemnification of licensors and authors of that
+ material by anyone who conveys the material (or modified versions of
+ it) with contractual assumptions of liability to the recipient, for
+ any liability that these contractual assumptions directly impose on
+ those licensors and authors.
+
+ All other non-permissive additional terms are considered "further
+restrictions" within the meaning of section 10. If the Program as you
+received it, or any part of it, contains a notice stating that it is
+governed by this License along with a term that is a further
+restriction, you may remove that term. If a license document contains
+a further restriction but permits relicensing or conveying under this
+License, you may add to a covered work material governed by the terms
+of that license document, provided that the further restriction does
+not survive such relicensing or conveying.
+
+ If you add terms to a covered work in accord with this section, you
+must place, in the relevant source files, a statement of the
+additional terms that apply to those files, or a notice indicating
+where to find the applicable terms.
+
+ Additional terms, permissive or non-permissive, may be stated in the
+form of a separately written license, or stated as exceptions;
+the above requirements apply either way.
+
+ 8. Termination.
+
+ You may not propagate or modify a covered work except as expressly
+provided under this License. Any attempt otherwise to propagate or
+modify it is void, and will automatically terminate your rights under
+this License (including any patent licenses granted under the third
+paragraph of section 11).
+
+ However, if you cease all violation of this License, then your
+license from a particular copyright holder is reinstated (a)
+provisionally, unless and until the copyright holder explicitly and
+finally terminates your license, and (b) permanently, if the copyright
+holder fails to notify you of the violation by some reasonable means
+prior to 60 days after the cessation.
+
+ Moreover, your license from a particular copyright holder is
+reinstated permanently if the copyright holder notifies you of the
+violation by some reasonable means, this is the first time you have
+received notice of violation of this License (for any work) from that
+copyright holder, and you cure the violation prior to 30 days after
+your receipt of the notice.
+
+ Termination of your rights under this section does not terminate the
+licenses of parties who have received copies or rights from you under
+this License. If your rights have been terminated and not permanently
+reinstated, you do not qualify to receive new licenses for the same
+material under section 10.
+
+ 9. Acceptance Not Required for Having Copies.
+
+ You are not required to accept this License in order to receive or
+run a copy of the Program. Ancillary propagation of a covered work
+occurring solely as a consequence of using peer-to-peer transmission
+to receive a copy likewise does not require acceptance. However,
+nothing other than this License grants you permission to propagate or
+modify any covered work. These actions infringe copyright if you do
+not accept this License. Therefore, by modifying or propagating a
+covered work, you indicate your acceptance of this License to do so.
+
+ 10. Automatic Licensing of Downstream Recipients.
+
+ Each time you convey a covered work, the recipient automatically
+receives a license from the original licensors, to run, modify and
+propagate that work, subject to this License. You are not responsible
+for enforcing compliance by third parties with this License.
+
+ An "entity transaction" is a transaction transferring control of an
+organization, or substantially all assets of one, or subdividing an
+organization, or merging organizations. If propagation of a covered
+work results from an entity transaction, each party to that
+transaction who receives a copy of the work also receives whatever
+licenses to the work the party's predecessor in interest had or could
+give under the previous paragraph, plus a right to possession of the
+Corresponding Source of the work from the predecessor in interest, if
+the predecessor has it or can get it with reasonable efforts.
+
+ You may not impose any further restrictions on the exercise of the
+rights granted or affirmed under this License. For example, you may
+not impose a license fee, royalty, or other charge for exercise of
+rights granted under this License, and you may not initiate litigation
+(including a cross-claim or counterclaim in a lawsuit) alleging that
+any patent claim is infringed by making, using, selling, offering for
+sale, or importing the Program or any portion of it.
+
+ 11. Patents.
+
+ A "contributor" is a copyright holder who authorizes use under this
+License of the Program or a work on which the Program is based. The
+work thus licensed is called the contributor's "contributor version".
+
+ A contributor's "essential patent claims" are all patent claims
+owned or controlled by the contributor, whether already acquired or
+hereafter acquired, that would be infringed by some manner, permitted
+by this License, of making, using, or selling its contributor version,
+but do not include claims that would be infringed only as a
+consequence of further modification of the contributor version. For
+purposes of this definition, "control" includes the right to grant
+patent sublicenses in a manner consistent with the requirements of
+this License.
+
+ Each contributor grants you a non-exclusive, worldwide, royalty-free
+patent license under the contributor's essential patent claims, to
+make, use, sell, offer for sale, import and otherwise run, modify and
+propagate the contents of its contributor version.
+
+ In the following three paragraphs, a "patent license" is any express
+agreement or commitment, however denominated, not to enforce a patent
+(such as an express permission to practice a patent or covenant not to
+sue for patent infringement). To "grant" such a patent license to a
+party means to make such an agreement or commitment not to enforce a
+patent against the party.
+
+ If you convey a covered work, knowingly relying on a patent license,
+and the Corresponding Source of the work is not available for anyone
+to copy, free of charge and under the terms of this License, through a
+publicly available network server or other readily accessible means,
+then you must either (1) cause the Corresponding Source to be so
+available, or (2) arrange to deprive yourself of the benefit of the
+patent license for this particular work, or (3) arrange, in a manner
+consistent with the requirements of this License, to extend the patent
+license to downstream recipients. "Knowingly relying" means you have
+actual knowledge that, but for the patent license, your conveying the
+covered work in a country, or your recipient's use of the covered work
+in a country, would infringe one or more identifiable patents in that
+country that you have reason to believe are valid.
+
+ If, pursuant to or in connection with a single transaction or
+arrangement, you convey, or propagate by procuring conveyance of, a
+covered work, and grant a patent license to some of the parties
+receiving the covered work authorizing them to use, propagate, modify
+or convey a specific copy of the covered work, then the patent license
+you grant is automatically extended to all recipients of the covered
+work and works based on it.
+
+ A patent license is "discriminatory" if it does not include within
+the scope of its coverage, prohibits the exercise of, or is
+conditioned on the non-exercise of one or more of the rights that are
+specifically granted under this License. You may not convey a covered
+work if you are a party to an arrangement with a third party that is
+in the business of distributing software, under which you make payment
+to the third party based on the extent of your activity of conveying
+the work, and under which the third party grants, to any of the
+parties who would receive the covered work from you, a discriminatory
+patent license (a) in connection with copies of the covered work
+conveyed by you (or copies made from those copies), or (b) primarily
+for and in connection with specific products or compilations that
+contain the covered work, unless you entered into that arrangement,
+or that patent license was granted, prior to 28 March 2007.
+
+ Nothing in this License shall be construed as excluding or limiting
+any implied license or other defenses to infringement that may
+otherwise be available to you under applicable patent law.
+
+ 12. No Surrender of Others' Freedom.
+
+ If conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License. If you cannot convey a
+covered work so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you may
+not convey it at all. For example, if you agree to terms that obligate you
+to collect a royalty for further conveying from those to whom you convey
+the Program, the only way you could satisfy both those terms and this
+License would be to refrain entirely from conveying the Program.
+
+ 13. Use with the GNU Affero General Public License.
+
+ Notwithstanding any other provision of this License, you have
+permission to link or combine any covered work with a work licensed
+under version 3 of the GNU Affero General Public License into a single
+combined work, and to convey the resulting work. The terms of this
+License will continue to apply to the part which is the covered work,
+but the special requirements of the GNU Affero General Public License,
+section 13, concerning interaction through a network will apply to the
+combination as such.
+
+ 14. Revised Versions of this License.
+
+ The Free Software Foundation may publish revised and/or new versions of
+the GNU General Public License from time to time. Such new versions will
+be similar in spirit to the present version, but may differ in detail to
+address new problems or concerns.
+
+ Each version is given a distinguishing version number. If the
+Program specifies that a certain numbered version of the GNU General
+Public License "or any later version" applies to it, you have the
+option of following the terms and conditions either of that numbered
+version or of any later version published by the Free Software
+Foundation. If the Program does not specify a version number of the
+GNU General Public License, you may choose any version ever published
+by the Free Software Foundation.
+
+ If the Program specifies that a proxy can decide which future
+versions of the GNU General Public License can be used, that proxy's
+public statement of acceptance of a version permanently authorizes you
+to choose that version for the Program.
+
+ Later license versions may give you additional or different
+permissions. However, no additional obligations are imposed on any
+author or copyright holder as a result of your choosing to follow a
+later version.
+
+ 15. Disclaimer of Warranty.
+
+ THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY
+APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT
+HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY
+OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO,
+THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM
+IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF
+ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
+
+ 16. Limitation of Liability.
+
+ IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS
+THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY
+GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE
+USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF
+DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD
+PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS),
+EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF
+SUCH DAMAGES.
+
+ 17. Interpretation of Sections 15 and 16.
+
+ If the disclaimer of warranty and limitation of liability provided
+above cannot be given local legal effect according to their terms,
+reviewing courts shall apply local law that most closely approximates
+an absolute waiver of all civil liability in connection with the
+Program, unless a warranty or assumption of liability accompanies a
+copy of the Program in return for a fee.
+
+ END OF TERMS AND CONDITIONS
+
+ How to Apply These Terms to Your New Programs
+
+ If you develop a new program, and you want it to be of the greatest
+possible use to the public, the best way to achieve this is to make it
+free software which everyone can redistribute and change under these terms.
+
+ To do so, attach the following notices to the program. It is safest
+to attach them to the start of each source file to most effectively
+state the exclusion of warranty; and each file should have at least
+the "copyright" line and a pointer to where the full notice is found.
+
+
+ Copyright (C)
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see .
+
+Also add information on how to contact you by electronic and paper mail.
+
+ If the program does terminal interaction, make it output a short
+notice like this when it starts in an interactive mode:
+
+ Copyright (C)
+ This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
+ This is free software, and you are welcome to redistribute it
+ under certain conditions; type `show c' for details.
+
+The hypothetical commands `show w' and `show c' should show the appropriate
+parts of the General Public License. Of course, your program's commands
+might be different; for a GUI interface, you would use an "about box".
+
+ You should also get your employer (if you work as a programmer) or school,
+if any, to sign a "copyright disclaimer" for the program, if necessary.
+For more information on this, and how to apply and follow the GNU GPL, see
+.
+
+ The GNU General Public License does not permit incorporating your program
+into proprietary programs. If your program is a subroutine library, you
+may consider it more useful to permit linking proprietary applications with
+the library. If this is what you want to do, use the GNU Lesser General
+Public License instead of this License. But first, please read
+.
diff --git a/modules/sale_history/MANIFEST.in b/modules/sale_history/MANIFEST.in
new file mode 100644
index 0000000000..e88b2348a3
--- /dev/null
+++ b/modules/sale_history/MANIFEST.in
@@ -0,0 +1,5 @@
+include CHANGELOG
+include COPYRIGHT
+include LICENSE
+include README.rst
+include doc/*
diff --git a/modules/sale_history/README.rst b/modules/sale_history/README.rst
new file mode 120000
index 0000000000..176d9c2695
--- /dev/null
+++ b/modules/sale_history/README.rst
@@ -0,0 +1 @@
+doc/index.rst
\ No newline at end of file
diff --git a/modules/sale_history/__init__.py b/modules/sale_history/__init__.py
new file mode 100644
index 0000000000..26e529ce0c
--- /dev/null
+++ b/modules/sale_history/__init__.py
@@ -0,0 +1,15 @@
+# This file is part of Tryton. The COPYRIGHT file at the top level of
+# this repository contains the full copyright notices and license terms.
+
+from trytond.pool import Pool
+from . import sale
+
+__all__ = ['register']
+
+
+def register():
+ Pool.register(
+ sale.Sale,
+ sale.Line,
+ sale.LineTax,
+ module='sale_history', type_='model')
diff --git a/modules/sale_history/doc/index.rst b/modules/sale_history/doc/index.rst
new file mode 100644
index 0000000000..2c7c71cff2
--- /dev/null
+++ b/modules/sale_history/doc/index.rst
@@ -0,0 +1,5 @@
+Sale History Module
+###################
+
+The sale history module activates the historization of the sale and adds a
+revision counter which increases each time the sale is reset to draft.
diff --git a/modules/sale_history/locale/bg.po b/modules/sale_history/locale/bg.po
new file mode 100644
index 0000000000..14bb7b84ea
--- /dev/null
+++ b/modules/sale_history/locale/bg.po
@@ -0,0 +1,11 @@
+#
+msgid ""
+msgstr "Content-Type: text/plain; charset=utf-8\n"
+
+msgctxt "field:sale.sale,revision:"
+msgid "Revision"
+msgstr ""
+
+msgctxt "view:sale.sale:"
+msgid "/"
+msgstr ""
diff --git a/modules/sale_history/locale/ca.po b/modules/sale_history/locale/ca.po
new file mode 100644
index 0000000000..bfd97830a9
--- /dev/null
+++ b/modules/sale_history/locale/ca.po
@@ -0,0 +1,11 @@
+#
+msgid ""
+msgstr "Content-Type: text/plain; charset=utf-8\n"
+
+msgctxt "field:sale.sale,revision:"
+msgid "Revision"
+msgstr "Revisió"
+
+msgctxt "view:sale.sale:"
+msgid "/"
+msgstr "/"
diff --git a/modules/sale_history/locale/cs.po b/modules/sale_history/locale/cs.po
new file mode 100644
index 0000000000..14bb7b84ea
--- /dev/null
+++ b/modules/sale_history/locale/cs.po
@@ -0,0 +1,11 @@
+#
+msgid ""
+msgstr "Content-Type: text/plain; charset=utf-8\n"
+
+msgctxt "field:sale.sale,revision:"
+msgid "Revision"
+msgstr ""
+
+msgctxt "view:sale.sale:"
+msgid "/"
+msgstr ""
diff --git a/modules/sale_history/locale/de.po b/modules/sale_history/locale/de.po
new file mode 100644
index 0000000000..b686c16e74
--- /dev/null
+++ b/modules/sale_history/locale/de.po
@@ -0,0 +1,11 @@
+#
+msgid ""
+msgstr "Content-Type: text/plain; charset=utf-8\n"
+
+msgctxt "field:sale.sale,revision:"
+msgid "Revision"
+msgstr "Version"
+
+msgctxt "view:sale.sale:"
+msgid "/"
+msgstr "/"
diff --git a/modules/sale_history/locale/es.po b/modules/sale_history/locale/es.po
new file mode 100644
index 0000000000..1b12945f44
--- /dev/null
+++ b/modules/sale_history/locale/es.po
@@ -0,0 +1,11 @@
+#
+msgid ""
+msgstr "Content-Type: text/plain; charset=utf-8\n"
+
+msgctxt "field:sale.sale,revision:"
+msgid "Revision"
+msgstr "Revisión"
+
+msgctxt "view:sale.sale:"
+msgid "/"
+msgstr "/"
diff --git a/modules/sale_history/locale/es_419.po b/modules/sale_history/locale/es_419.po
new file mode 100644
index 0000000000..14bb7b84ea
--- /dev/null
+++ b/modules/sale_history/locale/es_419.po
@@ -0,0 +1,11 @@
+#
+msgid ""
+msgstr "Content-Type: text/plain; charset=utf-8\n"
+
+msgctxt "field:sale.sale,revision:"
+msgid "Revision"
+msgstr ""
+
+msgctxt "view:sale.sale:"
+msgid "/"
+msgstr ""
diff --git a/modules/sale_history/locale/et.po b/modules/sale_history/locale/et.po
new file mode 100644
index 0000000000..14bb7b84ea
--- /dev/null
+++ b/modules/sale_history/locale/et.po
@@ -0,0 +1,11 @@
+#
+msgid ""
+msgstr "Content-Type: text/plain; charset=utf-8\n"
+
+msgctxt "field:sale.sale,revision:"
+msgid "Revision"
+msgstr ""
+
+msgctxt "view:sale.sale:"
+msgid "/"
+msgstr ""
diff --git a/modules/sale_history/locale/fa.po b/modules/sale_history/locale/fa.po
new file mode 100644
index 0000000000..14bb7b84ea
--- /dev/null
+++ b/modules/sale_history/locale/fa.po
@@ -0,0 +1,11 @@
+#
+msgid ""
+msgstr "Content-Type: text/plain; charset=utf-8\n"
+
+msgctxt "field:sale.sale,revision:"
+msgid "Revision"
+msgstr ""
+
+msgctxt "view:sale.sale:"
+msgid "/"
+msgstr ""
diff --git a/modules/sale_history/locale/fi.po b/modules/sale_history/locale/fi.po
new file mode 100644
index 0000000000..14bb7b84ea
--- /dev/null
+++ b/modules/sale_history/locale/fi.po
@@ -0,0 +1,11 @@
+#
+msgid ""
+msgstr "Content-Type: text/plain; charset=utf-8\n"
+
+msgctxt "field:sale.sale,revision:"
+msgid "Revision"
+msgstr ""
+
+msgctxt "view:sale.sale:"
+msgid "/"
+msgstr ""
diff --git a/modules/sale_history/locale/fr.po b/modules/sale_history/locale/fr.po
new file mode 100644
index 0000000000..fe818aa55e
--- /dev/null
+++ b/modules/sale_history/locale/fr.po
@@ -0,0 +1,11 @@
+#
+msgid ""
+msgstr "Content-Type: text/plain; charset=utf-8\n"
+
+msgctxt "field:sale.sale,revision:"
+msgid "Revision"
+msgstr "Révision"
+
+msgctxt "view:sale.sale:"
+msgid "/"
+msgstr "/"
diff --git a/modules/sale_history/locale/hu.po b/modules/sale_history/locale/hu.po
new file mode 100644
index 0000000000..14bb7b84ea
--- /dev/null
+++ b/modules/sale_history/locale/hu.po
@@ -0,0 +1,11 @@
+#
+msgid ""
+msgstr "Content-Type: text/plain; charset=utf-8\n"
+
+msgctxt "field:sale.sale,revision:"
+msgid "Revision"
+msgstr ""
+
+msgctxt "view:sale.sale:"
+msgid "/"
+msgstr ""
diff --git a/modules/sale_history/locale/id.po b/modules/sale_history/locale/id.po
new file mode 100644
index 0000000000..1d571b77e0
--- /dev/null
+++ b/modules/sale_history/locale/id.po
@@ -0,0 +1,11 @@
+#
+msgid ""
+msgstr "Content-Type: text/plain; charset=utf-8\n"
+
+msgctxt "field:sale.sale,revision:"
+msgid "Revision"
+msgstr "Revisi"
+
+msgctxt "view:sale.sale:"
+msgid "/"
+msgstr "/"
diff --git a/modules/sale_history/locale/it.po b/modules/sale_history/locale/it.po
new file mode 100644
index 0000000000..c2d0741f42
--- /dev/null
+++ b/modules/sale_history/locale/it.po
@@ -0,0 +1,11 @@
+#
+msgid ""
+msgstr "Content-Type: text/plain; charset=utf-8\n"
+
+msgctxt "field:sale.sale,revision:"
+msgid "Revision"
+msgstr "Revisione"
+
+msgctxt "view:sale.sale:"
+msgid "/"
+msgstr "/"
diff --git a/modules/sale_history/locale/lo.po b/modules/sale_history/locale/lo.po
new file mode 100644
index 0000000000..14bb7b84ea
--- /dev/null
+++ b/modules/sale_history/locale/lo.po
@@ -0,0 +1,11 @@
+#
+msgid ""
+msgstr "Content-Type: text/plain; charset=utf-8\n"
+
+msgctxt "field:sale.sale,revision:"
+msgid "Revision"
+msgstr ""
+
+msgctxt "view:sale.sale:"
+msgid "/"
+msgstr ""
diff --git a/modules/sale_history/locale/lt.po b/modules/sale_history/locale/lt.po
new file mode 100644
index 0000000000..14bb7b84ea
--- /dev/null
+++ b/modules/sale_history/locale/lt.po
@@ -0,0 +1,11 @@
+#
+msgid ""
+msgstr "Content-Type: text/plain; charset=utf-8\n"
+
+msgctxt "field:sale.sale,revision:"
+msgid "Revision"
+msgstr ""
+
+msgctxt "view:sale.sale:"
+msgid "/"
+msgstr ""
diff --git a/modules/sale_history/locale/nl.po b/modules/sale_history/locale/nl.po
new file mode 100644
index 0000000000..6bb8e00257
--- /dev/null
+++ b/modules/sale_history/locale/nl.po
@@ -0,0 +1,11 @@
+#
+msgid ""
+msgstr "Content-Type: text/plain; charset=utf-8\n"
+
+msgctxt "field:sale.sale,revision:"
+msgid "Revision"
+msgstr "Herziening"
+
+msgctxt "view:sale.sale:"
+msgid "/"
+msgstr "/"
diff --git a/modules/sale_history/locale/pl.po b/modules/sale_history/locale/pl.po
new file mode 100644
index 0000000000..63d326083b
--- /dev/null
+++ b/modules/sale_history/locale/pl.po
@@ -0,0 +1,11 @@
+#
+msgid ""
+msgstr "Content-Type: text/plain; charset=utf-8\n"
+
+msgctxt "field:sale.sale,revision:"
+msgid "Revision"
+msgstr "Wersja"
+
+msgctxt "view:sale.sale:"
+msgid "/"
+msgstr "/"
diff --git a/modules/sale_history/locale/pt.po b/modules/sale_history/locale/pt.po
new file mode 100644
index 0000000000..6885909a18
--- /dev/null
+++ b/modules/sale_history/locale/pt.po
@@ -0,0 +1,11 @@
+#
+msgid ""
+msgstr "Content-Type: text/plain; charset=utf-8\n"
+
+msgctxt "field:sale.sale,revision:"
+msgid "Revision"
+msgstr "Revisão"
+
+msgctxt "view:sale.sale:"
+msgid "/"
+msgstr ""
diff --git a/modules/sale_history/locale/ro.po b/modules/sale_history/locale/ro.po
new file mode 100644
index 0000000000..429b56fcdf
--- /dev/null
+++ b/modules/sale_history/locale/ro.po
@@ -0,0 +1,11 @@
+#
+msgid ""
+msgstr "Content-Type: text/plain; charset=utf-8\n"
+
+msgctxt "field:sale.sale,revision:"
+msgid "Revision"
+msgstr "Revizuire"
+
+msgctxt "view:sale.sale:"
+msgid "/"
+msgstr "/"
diff --git a/modules/sale_history/locale/ru.po b/modules/sale_history/locale/ru.po
new file mode 100644
index 0000000000..14bb7b84ea
--- /dev/null
+++ b/modules/sale_history/locale/ru.po
@@ -0,0 +1,11 @@
+#
+msgid ""
+msgstr "Content-Type: text/plain; charset=utf-8\n"
+
+msgctxt "field:sale.sale,revision:"
+msgid "Revision"
+msgstr ""
+
+msgctxt "view:sale.sale:"
+msgid "/"
+msgstr ""
diff --git a/modules/sale_history/locale/sl.po b/modules/sale_history/locale/sl.po
new file mode 100644
index 0000000000..14bb7b84ea
--- /dev/null
+++ b/modules/sale_history/locale/sl.po
@@ -0,0 +1,11 @@
+#
+msgid ""
+msgstr "Content-Type: text/plain; charset=utf-8\n"
+
+msgctxt "field:sale.sale,revision:"
+msgid "Revision"
+msgstr ""
+
+msgctxt "view:sale.sale:"
+msgid "/"
+msgstr ""
diff --git a/modules/sale_history/locale/tr.po b/modules/sale_history/locale/tr.po
new file mode 100644
index 0000000000..14bb7b84ea
--- /dev/null
+++ b/modules/sale_history/locale/tr.po
@@ -0,0 +1,11 @@
+#
+msgid ""
+msgstr "Content-Type: text/plain; charset=utf-8\n"
+
+msgctxt "field:sale.sale,revision:"
+msgid "Revision"
+msgstr ""
+
+msgctxt "view:sale.sale:"
+msgid "/"
+msgstr ""
diff --git a/modules/sale_history/locale/zh_CN.po b/modules/sale_history/locale/zh_CN.po
new file mode 100644
index 0000000000..14bb7b84ea
--- /dev/null
+++ b/modules/sale_history/locale/zh_CN.po
@@ -0,0 +1,11 @@
+#
+msgid ""
+msgstr "Content-Type: text/plain; charset=utf-8\n"
+
+msgctxt "field:sale.sale,revision:"
+msgid "Revision"
+msgstr ""
+
+msgctxt "view:sale.sale:"
+msgid "/"
+msgstr ""
diff --git a/modules/sale_history/sale.py b/modules/sale_history/sale.py
new file mode 100644
index 0000000000..f719a40cbf
--- /dev/null
+++ b/modules/sale_history/sale.py
@@ -0,0 +1,64 @@
+# This file is part of Tryton. The COPYRIGHT file at the top level of
+# this repository contains the full copyright notices and license terms.
+
+from trytond.model import ModelView, Workflow, fields
+from trytond.pool import PoolMeta
+from trytond.pyson import Eval
+from trytond.transaction import Transaction
+from trytond.tools import grouped_slice, reduce_ids
+
+
+class Sale(metaclass=PoolMeta):
+ __name__ = 'sale.sale'
+ _history = True
+ revision = fields.Integer(
+ "Revision", required=True, readonly=True,
+ states={
+ 'invisible': Eval('revision', 0) == 0,
+ })
+
+ @classmethod
+ def default_revision(cls):
+ return 0
+
+ @property
+ def full_number(self):
+ number = super().full_number
+ if number is not None and self.revision:
+ number += '/%d' % self.revision
+ return number
+
+ @classmethod
+ def copy(cls, sales, default=None):
+ if default is None:
+ default = {}
+ else:
+ default = default.copy()
+ default.setdefault('revision', cls.default_revision())
+ return super().copy(sales, default=default)
+
+ @classmethod
+ @ModelView.button
+ @Workflow.transition('draft')
+ def draft(cls, sales):
+ cursor = Transaction().connection.cursor()
+ table = cls.__table__()
+
+ # Use SQL and before super to avoid two history entries
+ for sub_sales in grouped_slice(sales):
+ cursor.execute(*table.update(
+ [table.revision],
+ [table.revision + 1],
+ where=reduce_ids(table.id, sub_sales)))
+
+ super().draft(sales)
+
+
+class Line(metaclass=PoolMeta):
+ __name__ = 'sale.line'
+ _history = True
+
+
+class LineTax(metaclass=PoolMeta):
+ __name__ = 'sale.line-account.tax'
+ _history = True
diff --git a/modules/sale_history/sale.xml b/modules/sale_history/sale.xml
new file mode 100644
index 0000000000..b23afd7b71
--- /dev/null
+++ b/modules/sale_history/sale.xml
@@ -0,0 +1,17 @@
+
+
+
+
+
+ sale.sale
+
+ sale_form
+
+
+ sale.sale
+
+ sale_tree
+
+
+
diff --git a/modules/sale_history/setup.py b/modules/sale_history/setup.py
new file mode 100755
index 0000000000..18baf25e0c
--- /dev/null
+++ b/modules/sale_history/setup.py
@@ -0,0 +1,147 @@
+#!/usr/bin/env python3
+# This file is part of Tryton. The COPYRIGHT file at the top level of
+# this repository contains the full copyright notices and license terms.
+
+import io
+import os
+import re
+from configparser import ConfigParser
+from setuptools import setup, find_packages
+
+
+def read(fname):
+ return io.open(
+ os.path.join(os.path.dirname(__file__), fname),
+ 'r', encoding='utf-8').read()
+
+
+def get_require_version(name):
+ if minor_version % 2:
+ require = '%s >= %s.%s.dev0, < %s.%s'
+ else:
+ require = '%s >= %s.%s, < %s.%s'
+ require %= (name, major_version, minor_version,
+ major_version, minor_version + 1)
+ return require
+
+
+config = ConfigParser()
+config.read_file(open(os.path.join(os.path.dirname(__file__), 'tryton.cfg')))
+info = dict(config.items('tryton'))
+for key in ('depends', 'extras_depend', 'xml'):
+ if key in info:
+ info[key] = info[key].strip().splitlines()
+version = info.get('version', '0.0.1')
+major_version, minor_version, _ = version.split('.', 2)
+major_version = int(major_version)
+minor_version = int(minor_version)
+name = 'trytond_sale_history'
+
+download_url = 'http://downloads.tryton.org/%s.%s/' % (
+ major_version, minor_version)
+if minor_version % 2:
+ version = '%s.%s.dev0' % (major_version, minor_version)
+ download_url = (
+ 'hg+http://hg.tryton.org/modules/%s#egg=%s-%s' % (
+ name[8:], name, version))
+local_version = []
+if os.environ.get('CI_JOB_ID'):
+ local_version.append(os.environ['CI_JOB_ID'])
+else:
+ for build in ['CI_BUILD_NUMBER', 'CI_JOB_NUMBER']:
+ if os.environ.get(build):
+ local_version.append(os.environ[build])
+ else:
+ local_version = []
+ break
+if local_version:
+ version += '+' + '.'.join(local_version)
+
+requires = []
+for dep in info.get('depends', []):
+ if not re.match(r'(ir|res)(\W|$)', dep):
+ requires.append(get_require_version('trytond_%s' % dep))
+requires.append(get_require_version('trytond'))
+
+tests_require = [get_require_version('proteus')]
+dependency_links = []
+if minor_version % 2:
+ dependency_links.append(
+ 'https://trydevpi.tryton.org/?local_version='
+ + '.'.join(local_version))
+
+setup(name=name,
+ version=version,
+ description='Tryton module to historize sales',
+ long_description=read('README.rst'),
+ author='Tryton',
+ author_email='bugs@tryton.org',
+ url='http://www.tryton.org/',
+ download_url=download_url,
+ project_urls={
+ "Bug Tracker": 'https://bugs.tryton.org/',
+ "Documentation": 'https://docs.tryton.org/',
+ "Forum": 'https://www.tryton.org/forum',
+ "Source Code": 'https://hg.tryton.org/modules/sale_history',
+ },
+ keywords='tryton sale history revision',
+ package_dir={'trytond.modules.sale_history': '.'},
+ packages=(
+ ['trytond.modules.sale_history']
+ + ['trytond.modules.sale_history.%s' % p for p in find_packages()]
+ ),
+ package_data={
+ 'trytond.modules.sale_history': (info.get('xml', [])
+ + ['tryton.cfg', 'view/*.xml', 'locale/*.po', '*.fodt',
+ 'icons/*.svg', 'tests/*.rst']),
+ },
+ classifiers=[
+ 'Development Status :: 5 - Production/Stable',
+ 'Environment :: Plugins',
+ 'Framework :: Tryton',
+ 'Intended Audience :: Developers',
+ 'Intended Audience :: Financial and Insurance Industry',
+ 'Intended Audience :: Legal Industry',
+ 'License :: OSI Approved :: '
+ 'GNU General Public License v3 or later (GPLv3+)',
+ 'Natural Language :: Bulgarian',
+ 'Natural Language :: Catalan',
+ 'Natural Language :: Chinese (Simplified)',
+ 'Natural Language :: Czech',
+ 'Natural Language :: Dutch',
+ 'Natural Language :: English',
+ 'Natural Language :: French',
+ 'Natural Language :: German',
+ 'Natural Language :: Hungarian',
+ 'Natural Language :: Indonesian',
+ 'Natural Language :: Italian',
+ 'Natural Language :: Persian',
+ 'Natural Language :: Polish',
+ 'Natural Language :: Portuguese (Brazilian)',
+ 'Natural Language :: Romanian',
+ 'Natural Language :: Russian',
+ 'Natural Language :: Slovenian',
+ 'Natural Language :: Spanish',
+ 'Operating System :: OS Independent',
+ 'Programming Language :: Python :: 3',
+ 'Programming Language :: Python :: 3.6',
+ 'Programming Language :: Python :: 3.7',
+ 'Programming Language :: Python :: 3.8',
+ 'Programming Language :: Python :: 3.9',
+ 'Programming Language :: Python :: Implementation :: CPython',
+ 'Programming Language :: Python :: Implementation :: PyPy',
+ 'Topic :: Office/Business',
+ ],
+ license='GPL-3',
+ python_requires='>=3.6',
+ install_requires=requires,
+ dependency_links=dependency_links,
+ zip_safe=False,
+ entry_points="""
+ [trytond.modules]
+ sale_history = trytond.modules.sale_history
+ """,
+ test_suite='tests',
+ test_loader='trytond.test_loader:Loader',
+ tests_require=tests_require,
+ )
diff --git a/modules/sale_history/tests/__init__.py b/modules/sale_history/tests/__init__.py
new file mode 100644
index 0000000000..32b6ff03f1
--- /dev/null
+++ b/modules/sale_history/tests/__init__.py
@@ -0,0 +1,9 @@
+# This file is part of Tryton. The COPYRIGHT file at the top level of
+# this repository contains the full copyright notices and license terms.
+
+try:
+ from trytond.modules.sale_history.tests.test_sale_history import suite
+except ImportError:
+ from .test_sale_history import suite
+
+__all__ = ['suite']
diff --git a/modules/sale_history/tests/scenario_sale_history.rst b/modules/sale_history/tests/scenario_sale_history.rst
new file mode 100644
index 0000000000..4f7893e887
--- /dev/null
+++ b/modules/sale_history/tests/scenario_sale_history.rst
@@ -0,0 +1,48 @@
+=====================
+Sale History Scenario
+=====================
+
+Imports::
+
+ >>> from proteus import Model, Wizard
+ >>> from trytond.tests.tools import activate_modules
+ >>> from trytond.modules.company.tests.tools import create_company, \
+ ... get_company
+
+Activate modules::
+
+ >>> config = activate_modules('sale_history')
+
+Create company::
+
+ >>> _ = create_company()
+ >>> company = get_company()
+
+Create customer::
+
+ >>> Party = Model.get('party.party')
+ >>> customer = Party(name='Customer')
+ >>> customer.save()
+
+Create a sale::
+
+ >>> Sale = Model.get('sale.sale')
+ >>> sale = Sale()
+ >>> sale.party = customer
+ >>> sale.click('quote')
+
+ >>> sale.number
+ '1'
+ >>> sale.revision
+ 0
+ >>> sale.rec_name
+ '1'
+
+Reset to draft increases revision::
+
+ >>> sale.click('draft')
+
+ >>> sale.revision
+ 1
+ >>> sale.rec_name
+ '1/1'
diff --git a/modules/sale_history/tests/test_sale_history.py b/modules/sale_history/tests/test_sale_history.py
new file mode 100644
index 0000000000..c0d7d83a6a
--- /dev/null
+++ b/modules/sale_history/tests/test_sale_history.py
@@ -0,0 +1,28 @@
+# This file is part of Tryton. The COPYRIGHT file at the top level of
+# this repository contains the full copyright notices and license terms.
+
+import unittest
+
+import doctest
+
+from trytond.tests.test_tryton import ModuleTestCase
+from trytond.tests.test_tryton import suite as test_suite
+from trytond.tests.test_tryton import doctest_teardown
+from trytond.tests.test_tryton import doctest_checker
+
+
+class SaleHistoryTestCase(ModuleTestCase):
+ 'Test Sale History module'
+ module = 'sale_history'
+
+
+def suite():
+ suite = test_suite()
+ suite.addTests(unittest.TestLoader().loadTestsFromTestCase(
+ SaleHistoryTestCase))
+ suite.addTests(doctest.DocFileSuite(
+ 'scenario_sale_history.rst',
+ tearDown=doctest_teardown, encoding='utf-8',
+ checker=doctest_checker,
+ optionflags=doctest.REPORT_ONLY_FIRST_FAILURE))
+ return suite
diff --git a/modules/sale_history/tox.ini b/modules/sale_history/tox.ini
new file mode 100644
index 0000000000..197496c0cb
--- /dev/null
+++ b/modules/sale_history/tox.ini
@@ -0,0 +1,15 @@
+[tox]
+envlist = {py36,py37,py38,py39}-{sqlite,postgresql},pypy3-{sqlite,postgresql}
+
+[testenv]
+commands = {envpython} setup.py test
+deps =
+ {py36,py37,py38,py39}-postgresql: psycopg2 >= 2.5
+ pypy3-postgresql: psycopg2cffi >= 2.5
+ py36-sqlite: sqlitebck
+setenv =
+ sqlite: TRYTOND_DATABASE_URI={env:SQLITE_URI:sqlite://}
+ postgresql: TRYTOND_DATABASE_URI={env:POSTGRESQL_URI:postgresql://}
+ sqlite: DB_NAME={env:SQLITE_NAME::memory:}
+ postgresql: DB_NAME={env:POSTGRESQL_NAME:test}
+install_command = pip install --pre --find-links https://trydevpi.tryton.org/?local_version={env:CI_JOB_ID:{env:CI_BUILD_NUMBER}.{env:CI_JOB_NUMBER}} {opts} {packages}
diff --git a/modules/sale_history/tryton.cfg b/modules/sale_history/tryton.cfg
new file mode 100644
index 0000000000..b5344e2a10
--- /dev/null
+++ b/modules/sale_history/tryton.cfg
@@ -0,0 +1,7 @@
+[tryton]
+version=6.0.1
+depends:
+ ir
+ sale
+xml:
+ sale.xml
diff --git a/modules/sale_history/view/sale_form.xml b/modules/sale_history/view/sale_form.xml
new file mode 100644
index 0000000000..47fcd8ed94
--- /dev/null
+++ b/modules/sale_history/view/sale_form.xml
@@ -0,0 +1,12 @@
+
+
+
+
+
+
+
+
+
+
+
diff --git a/modules/sale_history/view/sale_tree.xml b/modules/sale_history/view/sale_tree.xml
new file mode 100644
index 0000000000..62eff27c16
--- /dev/null
+++ b/modules/sale_history/view/sale_tree.xml
@@ -0,0 +1,8 @@
+
+
+
+
+
+
+
diff --git a/modules/sale_invoice_grouping/.drone.yml b/modules/sale_invoice_grouping/.drone.yml
new file mode 100644
index 0000000000..2049d30a49
--- /dev/null
+++ b/modules/sale_invoice_grouping/.drone.yml
@@ -0,0 +1,68 @@
+clone:
+ hg:
+ image: plugins/hg
+ environment:
+ - HG_SHARE_POOL=/root/.cache/hg
+ volumes:
+ - cache:/root/.cache
+
+pipeline:
+ tox:
+ image: ${IMAGE}
+ environment:
+ - CFLAGS=-O0
+ - DB_CACHE=/cache
+ - TOX_TESTENV_PASSENV=CFLAGS DB_CACHE CI_BUILD_NUMBER CI_JOB_NUMBER CI_JOB_ID
+ - POSTGRESQL_URI=postgresql://postgres@postgresql:5432/
+ commands:
+ - echo "[extensions]" >> /root/.hgrc
+ - echo "hgext.share =" >> /root/.hgrc
+ - echo "[share]" >> /root/.hgrc
+ - echo "pool = /root/.cache/hg" >> /root/.hgrc
+ - pip install tox
+ - tox -e "${TOXENV}-${DATABASE}"
+ volumes:
+ - cache:/root/.cache
+ check_dist:
+ image: ${IMAGE}
+ commands:
+ - pip install twine
+ - python setup.py sdist
+ - twine check dist/*
+
+services:
+ postgresql:
+ image: postgres
+ environment:
+ - POSTGRES_HOST_AUTH_METHOD=trust
+ command: "-c fsync=off -c synchronous_commit=off -c full_page_writes=off"
+ when:
+ matrix:
+ DATABASE: postgresql
+
+matrix:
+ include:
+ - IMAGE: python:3.6
+ TOXENV: py36
+ DATABASE: sqlite
+ - IMAGE: python:3.6
+ TOXENV: py36
+ DATABASE: postgresql
+ - IMAGE: python:3.7
+ TOXENV: py37
+ DATABASE: sqlite
+ - IMAGE: python:3.7
+ TOXENV: py37
+ DATABASE: postgresql
+ - IMAGE: python:3.8
+ TOXENV: py38
+ DATABASE: sqlite
+ - IMAGE: python:3.8
+ TOXENV: py38
+ DATABASE: postgresql
+ - IMAGE: python:3.9
+ TOXENV: py39
+ DATABASE: sqlite
+ - IMAGE: python:3.9
+ TOXENV: py39
+ DATABASE: postgresql
diff --git a/modules/sale_invoice_grouping/.flake8 b/modules/sale_invoice_grouping/.flake8
new file mode 100644
index 0000000000..fa6b4f66d1
--- /dev/null
+++ b/modules/sale_invoice_grouping/.flake8
@@ -0,0 +1,2 @@
+[flake8]
+ignore=E123,E124,E126,E128,E741,W503
diff --git a/modules/sale_invoice_grouping/CHANGELOG b/modules/sale_invoice_grouping/CHANGELOG
new file mode 100644
index 0000000000..a8322f5c67
--- /dev/null
+++ b/modules/sale_invoice_grouping/CHANGELOG
@@ -0,0 +1,51 @@
+Version 6.0.0 - 2021-05-03
+* Bug fixes (see mercurial logs for details)
+
+Version 5.8.0 - 2020-11-02
+* Bug fixes (see mercurial logs for details)
+* Remove support for Python 3.5
+
+Version 5.6.0 - 2020-05-04
+* Bug fixes (see mercurial logs for details)
+
+Version 5.4.0 - 2019-11-04
+* Bug fixes (see mercurial logs for details)
+
+Version 5.2.0 - 2019-05-06
+* Bug fixes (see mercurial logs for details)
+
+Version 5.0.0 - 2018-10-01
+* Bug fixes (see mercurial logs for details)
+* Remove support for Python 2.7
+
+Version 4.8.0 - 2018-04-23
+* Bug fixes (see mercurial logs for details)
+
+Version 4.6.0 - 2017-10-30
+* Bug fixes (see mercurial logs for details)
+* Add default invoice grouping method
+
+Version 4.4.0 - 2017-05-01
+* Bug fixes (see mercurial logs for details)
+
+Version 4.2.0 - 2016-11-28
+* Bug fixes (see mercurial logs for details)
+
+Version 4.0.0 - 2016-05-02
+* Bug fixes (see mercurial logs for details)
+* Add Python3 support
+
+Version 3.8.0 - 2015-11-02
+* Bug fixes (see mercurial logs for details)
+
+Version 3.6.0 - 2015-04-20
+* Bug fixes (see mercurial logs for details)
+* Add support for PyPy
+Version 3.4.0 - 2014-10-20
+* Bug fixes (see mercurial logs for details)
+
+Version 3.2.0 - 2014-04-21
+* Bug fixes (see mercurial logs for details)
+
+Version 3.0.0 - 2013-10-21
+* Initial release
diff --git a/modules/sale_invoice_grouping/COPYRIGHT b/modules/sale_invoice_grouping/COPYRIGHT
new file mode 100644
index 0000000000..254bee49c9
--- /dev/null
+++ b/modules/sale_invoice_grouping/COPYRIGHT
@@ -0,0 +1,15 @@
+Copyright (C) 2013-2017 Nicolas Évrard.
+Copyright (C) 2013-2021 B2CK SPRL.
+
+This program is free software: you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation, either version 3 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program. If not, see .
diff --git a/modules/sale_invoice_grouping/LICENSE b/modules/sale_invoice_grouping/LICENSE
new file mode 100644
index 0000000000..94a9ed024d
--- /dev/null
+++ b/modules/sale_invoice_grouping/LICENSE
@@ -0,0 +1,674 @@
+ GNU GENERAL PUBLIC LICENSE
+ Version 3, 29 June 2007
+
+ Copyright (C) 2007 Free Software Foundation, Inc.
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+ Preamble
+
+ The GNU General Public License is a free, copyleft license for
+software and other kinds of works.
+
+ The licenses for most software and other practical works are designed
+to take away your freedom to share and change the works. By contrast,
+the GNU General Public License is intended to guarantee your freedom to
+share and change all versions of a program--to make sure it remains free
+software for all its users. We, the Free Software Foundation, use the
+GNU General Public License for most of our software; it applies also to
+any other work released this way by its authors. You can apply it to
+your programs, too.
+
+ When we speak of free software, we are referring to freedom, not
+price. Our General Public Licenses are designed to make sure that you
+have the freedom to distribute copies of free software (and charge for
+them if you wish), that you receive source code or can get it if you
+want it, that you can change the software or use pieces of it in new
+free programs, and that you know you can do these things.
+
+ To protect your rights, we need to prevent others from denying you
+these rights or asking you to surrender the rights. Therefore, you have
+certain responsibilities if you distribute copies of the software, or if
+you modify it: responsibilities to respect the freedom of others.
+
+ For example, if you distribute copies of such a program, whether
+gratis or for a fee, you must pass on to the recipients the same
+freedoms that you received. You must make sure that they, too, receive
+or can get the source code. And you must show them these terms so they
+know their rights.
+
+ Developers that use the GNU GPL protect your rights with two steps:
+(1) assert copyright on the software, and (2) offer you this License
+giving you legal permission to copy, distribute and/or modify it.
+
+ For the developers' and authors' protection, the GPL clearly explains
+that there is no warranty for this free software. For both users' and
+authors' sake, the GPL requires that modified versions be marked as
+changed, so that their problems will not be attributed erroneously to
+authors of previous versions.
+
+ Some devices are designed to deny users access to install or run
+modified versions of the software inside them, although the manufacturer
+can do so. This is fundamentally incompatible with the aim of
+protecting users' freedom to change the software. The systematic
+pattern of such abuse occurs in the area of products for individuals to
+use, which is precisely where it is most unacceptable. Therefore, we
+have designed this version of the GPL to prohibit the practice for those
+products. If such problems arise substantially in other domains, we
+stand ready to extend this provision to those domains in future versions
+of the GPL, as needed to protect the freedom of users.
+
+ Finally, every program is threatened constantly by software patents.
+States should not allow patents to restrict development and use of
+software on general-purpose computers, but in those that do, we wish to
+avoid the special danger that patents applied to a free program could
+make it effectively proprietary. To prevent this, the GPL assures that
+patents cannot be used to render the program non-free.
+
+ The precise terms and conditions for copying, distribution and
+modification follow.
+
+ TERMS AND CONDITIONS
+
+ 0. Definitions.
+
+ "This License" refers to version 3 of the GNU General Public License.
+
+ "Copyright" also means copyright-like laws that apply to other kinds of
+works, such as semiconductor masks.
+
+ "The Program" refers to any copyrightable work licensed under this
+License. Each licensee is addressed as "you". "Licensees" and
+"recipients" may be individuals or organizations.
+
+ To "modify" a work means to copy from or adapt all or part of the work
+in a fashion requiring copyright permission, other than the making of an
+exact copy. The resulting work is called a "modified version" of the
+earlier work or a work "based on" the earlier work.
+
+ A "covered work" means either the unmodified Program or a work based
+on the Program.
+
+ To "propagate" a work means to do anything with it that, without
+permission, would make you directly or secondarily liable for
+infringement under applicable copyright law, except executing it on a
+computer or modifying a private copy. Propagation includes copying,
+distribution (with or without modification), making available to the
+public, and in some countries other activities as well.
+
+ To "convey" a work means any kind of propagation that enables other
+parties to make or receive copies. Mere interaction with a user through
+a computer network, with no transfer of a copy, is not conveying.
+
+ An interactive user interface displays "Appropriate Legal Notices"
+to the extent that it includes a convenient and prominently visible
+feature that (1) displays an appropriate copyright notice, and (2)
+tells the user that there is no warranty for the work (except to the
+extent that warranties are provided), that licensees may convey the
+work under this License, and how to view a copy of this License. If
+the interface presents a list of user commands or options, such as a
+menu, a prominent item in the list meets this criterion.
+
+ 1. Source Code.
+
+ The "source code" for a work means the preferred form of the work
+for making modifications to it. "Object code" means any non-source
+form of a work.
+
+ A "Standard Interface" means an interface that either is an official
+standard defined by a recognized standards body, or, in the case of
+interfaces specified for a particular programming language, one that
+is widely used among developers working in that language.
+
+ The "System Libraries" of an executable work include anything, other
+than the work as a whole, that (a) is included in the normal form of
+packaging a Major Component, but which is not part of that Major
+Component, and (b) serves only to enable use of the work with that
+Major Component, or to implement a Standard Interface for which an
+implementation is available to the public in source code form. A
+"Major Component", in this context, means a major essential component
+(kernel, window system, and so on) of the specific operating system
+(if any) on which the executable work runs, or a compiler used to
+produce the work, or an object code interpreter used to run it.
+
+ The "Corresponding Source" for a work in object code form means all
+the source code needed to generate, install, and (for an executable
+work) run the object code and to modify the work, including scripts to
+control those activities. However, it does not include the work's
+System Libraries, or general-purpose tools or generally available free
+programs which are used unmodified in performing those activities but
+which are not part of the work. For example, Corresponding Source
+includes interface definition files associated with source files for
+the work, and the source code for shared libraries and dynamically
+linked subprograms that the work is specifically designed to require,
+such as by intimate data communication or control flow between those
+subprograms and other parts of the work.
+
+ The Corresponding Source need not include anything that users
+can regenerate automatically from other parts of the Corresponding
+Source.
+
+ The Corresponding Source for a work in source code form is that
+same work.
+
+ 2. Basic Permissions.
+
+ All rights granted under this License are granted for the term of
+copyright on the Program, and are irrevocable provided the stated
+conditions are met. This License explicitly affirms your unlimited
+permission to run the unmodified Program. The output from running a
+covered work is covered by this License only if the output, given its
+content, constitutes a covered work. This License acknowledges your
+rights of fair use or other equivalent, as provided by copyright law.
+
+ You may make, run and propagate covered works that you do not
+convey, without conditions so long as your license otherwise remains
+in force. You may convey covered works to others for the sole purpose
+of having them make modifications exclusively for you, or provide you
+with facilities for running those works, provided that you comply with
+the terms of this License in conveying all material for which you do
+not control copyright. Those thus making or running the covered works
+for you must do so exclusively on your behalf, under your direction
+and control, on terms that prohibit them from making any copies of
+your copyrighted material outside their relationship with you.
+
+ Conveying under any other circumstances is permitted solely under
+the conditions stated below. Sublicensing is not allowed; section 10
+makes it unnecessary.
+
+ 3. Protecting Users' Legal Rights From Anti-Circumvention Law.
+
+ No covered work shall be deemed part of an effective technological
+measure under any applicable law fulfilling obligations under article
+11 of the WIPO copyright treaty adopted on 20 December 1996, or
+similar laws prohibiting or restricting circumvention of such
+measures.
+
+ When you convey a covered work, you waive any legal power to forbid
+circumvention of technological measures to the extent such circumvention
+is effected by exercising rights under this License with respect to
+the covered work, and you disclaim any intention to limit operation or
+modification of the work as a means of enforcing, against the work's
+users, your or third parties' legal rights to forbid circumvention of
+technological measures.
+
+ 4. Conveying Verbatim Copies.
+
+ You may convey verbatim copies of the Program's source code as you
+receive it, in any medium, provided that you conspicuously and
+appropriately publish on each copy an appropriate copyright notice;
+keep intact all notices stating that this License and any
+non-permissive terms added in accord with section 7 apply to the code;
+keep intact all notices of the absence of any warranty; and give all
+recipients a copy of this License along with the Program.
+
+ You may charge any price or no price for each copy that you convey,
+and you may offer support or warranty protection for a fee.
+
+ 5. Conveying Modified Source Versions.
+
+ You may convey a work based on the Program, or the modifications to
+produce it from the Program, in the form of source code under the
+terms of section 4, provided that you also meet all of these conditions:
+
+ a) The work must carry prominent notices stating that you modified
+ it, and giving a relevant date.
+
+ b) The work must carry prominent notices stating that it is
+ released under this License and any conditions added under section
+ 7. This requirement modifies the requirement in section 4 to
+ "keep intact all notices".
+
+ c) You must license the entire work, as a whole, under this
+ License to anyone who comes into possession of a copy. This
+ License will therefore apply, along with any applicable section 7
+ additional terms, to the whole of the work, and all its parts,
+ regardless of how they are packaged. This License gives no
+ permission to license the work in any other way, but it does not
+ invalidate such permission if you have separately received it.
+
+ d) If the work has interactive user interfaces, each must display
+ Appropriate Legal Notices; however, if the Program has interactive
+ interfaces that do not display Appropriate Legal Notices, your
+ work need not make them do so.
+
+ A compilation of a covered work with other separate and independent
+works, which are not by their nature extensions of the covered work,
+and which are not combined with it such as to form a larger program,
+in or on a volume of a storage or distribution medium, is called an
+"aggregate" if the compilation and its resulting copyright are not
+used to limit the access or legal rights of the compilation's users
+beyond what the individual works permit. Inclusion of a covered work
+in an aggregate does not cause this License to apply to the other
+parts of the aggregate.
+
+ 6. Conveying Non-Source Forms.
+
+ You may convey a covered work in object code form under the terms
+of sections 4 and 5, provided that you also convey the
+machine-readable Corresponding Source under the terms of this License,
+in one of these ways:
+
+ a) Convey the object code in, or embodied in, a physical product
+ (including a physical distribution medium), accompanied by the
+ Corresponding Source fixed on a durable physical medium
+ customarily used for software interchange.
+
+ b) Convey the object code in, or embodied in, a physical product
+ (including a physical distribution medium), accompanied by a
+ written offer, valid for at least three years and valid for as
+ long as you offer spare parts or customer support for that product
+ model, to give anyone who possesses the object code either (1) a
+ copy of the Corresponding Source for all the software in the
+ product that is covered by this License, on a durable physical
+ medium customarily used for software interchange, for a price no
+ more than your reasonable cost of physically performing this
+ conveying of source, or (2) access to copy the
+ Corresponding Source from a network server at no charge.
+
+ c) Convey individual copies of the object code with a copy of the
+ written offer to provide the Corresponding Source. This
+ alternative is allowed only occasionally and noncommercially, and
+ only if you received the object code with such an offer, in accord
+ with subsection 6b.
+
+ d) Convey the object code by offering access from a designated
+ place (gratis or for a charge), and offer equivalent access to the
+ Corresponding Source in the same way through the same place at no
+ further charge. You need not require recipients to copy the
+ Corresponding Source along with the object code. If the place to
+ copy the object code is a network server, the Corresponding Source
+ may be on a different server (operated by you or a third party)
+ that supports equivalent copying facilities, provided you maintain
+ clear directions next to the object code saying where to find the
+ Corresponding Source. Regardless of what server hosts the
+ Corresponding Source, you remain obligated to ensure that it is
+ available for as long as needed to satisfy these requirements.
+
+ e) Convey the object code using peer-to-peer transmission, provided
+ you inform other peers where the object code and Corresponding
+ Source of the work are being offered to the general public at no
+ charge under subsection 6d.
+
+ A separable portion of the object code, whose source code is excluded
+from the Corresponding Source as a System Library, need not be
+included in conveying the object code work.
+
+ A "User Product" is either (1) a "consumer product", which means any
+tangible personal property which is normally used for personal, family,
+or household purposes, or (2) anything designed or sold for incorporation
+into a dwelling. In determining whether a product is a consumer product,
+doubtful cases shall be resolved in favor of coverage. For a particular
+product received by a particular user, "normally used" refers to a
+typical or common use of that class of product, regardless of the status
+of the particular user or of the way in which the particular user
+actually uses, or expects or is expected to use, the product. A product
+is a consumer product regardless of whether the product has substantial
+commercial, industrial or non-consumer uses, unless such uses represent
+the only significant mode of use of the product.
+
+ "Installation Information" for a User Product means any methods,
+procedures, authorization keys, or other information required to install
+and execute modified versions of a covered work in that User Product from
+a modified version of its Corresponding Source. The information must
+suffice to ensure that the continued functioning of the modified object
+code is in no case prevented or interfered with solely because
+modification has been made.
+
+ If you convey an object code work under this section in, or with, or
+specifically for use in, a User Product, and the conveying occurs as
+part of a transaction in which the right of possession and use of the
+User Product is transferred to the recipient in perpetuity or for a
+fixed term (regardless of how the transaction is characterized), the
+Corresponding Source conveyed under this section must be accompanied
+by the Installation Information. But this requirement does not apply
+if neither you nor any third party retains the ability to install
+modified object code on the User Product (for example, the work has
+been installed in ROM).
+
+ The requirement to provide Installation Information does not include a
+requirement to continue to provide support service, warranty, or updates
+for a work that has been modified or installed by the recipient, or for
+the User Product in which it has been modified or installed. Access to a
+network may be denied when the modification itself materially and
+adversely affects the operation of the network or violates the rules and
+protocols for communication across the network.
+
+ Corresponding Source conveyed, and Installation Information provided,
+in accord with this section must be in a format that is publicly
+documented (and with an implementation available to the public in
+source code form), and must require no special password or key for
+unpacking, reading or copying.
+
+ 7. Additional Terms.
+
+ "Additional permissions" are terms that supplement the terms of this
+License by making exceptions from one or more of its conditions.
+Additional permissions that are applicable to the entire Program shall
+be treated as though they were included in this License, to the extent
+that they are valid under applicable law. If additional permissions
+apply only to part of the Program, that part may be used separately
+under those permissions, but the entire Program remains governed by
+this License without regard to the additional permissions.
+
+ When you convey a copy of a covered work, you may at your option
+remove any additional permissions from that copy, or from any part of
+it. (Additional permissions may be written to require their own
+removal in certain cases when you modify the work.) You may place
+additional permissions on material, added by you to a covered work,
+for which you have or can give appropriate copyright permission.
+
+ Notwithstanding any other provision of this License, for material you
+add to a covered work, you may (if authorized by the copyright holders of
+that material) supplement the terms of this License with terms:
+
+ a) Disclaiming warranty or limiting liability differently from the
+ terms of sections 15 and 16 of this License; or
+
+ b) Requiring preservation of specified reasonable legal notices or
+ author attributions in that material or in the Appropriate Legal
+ Notices displayed by works containing it; or
+
+ c) Prohibiting misrepresentation of the origin of that material, or
+ requiring that modified versions of such material be marked in
+ reasonable ways as different from the original version; or
+
+ d) Limiting the use for publicity purposes of names of licensors or
+ authors of the material; or
+
+ e) Declining to grant rights under trademark law for use of some
+ trade names, trademarks, or service marks; or
+
+ f) Requiring indemnification of licensors and authors of that
+ material by anyone who conveys the material (or modified versions of
+ it) with contractual assumptions of liability to the recipient, for
+ any liability that these contractual assumptions directly impose on
+ those licensors and authors.
+
+ All other non-permissive additional terms are considered "further
+restrictions" within the meaning of section 10. If the Program as you
+received it, or any part of it, contains a notice stating that it is
+governed by this License along with a term that is a further
+restriction, you may remove that term. If a license document contains
+a further restriction but permits relicensing or conveying under this
+License, you may add to a covered work material governed by the terms
+of that license document, provided that the further restriction does
+not survive such relicensing or conveying.
+
+ If you add terms to a covered work in accord with this section, you
+must place, in the relevant source files, a statement of the
+additional terms that apply to those files, or a notice indicating
+where to find the applicable terms.
+
+ Additional terms, permissive or non-permissive, may be stated in the
+form of a separately written license, or stated as exceptions;
+the above requirements apply either way.
+
+ 8. Termination.
+
+ You may not propagate or modify a covered work except as expressly
+provided under this License. Any attempt otherwise to propagate or
+modify it is void, and will automatically terminate your rights under
+this License (including any patent licenses granted under the third
+paragraph of section 11).
+
+ However, if you cease all violation of this License, then your
+license from a particular copyright holder is reinstated (a)
+provisionally, unless and until the copyright holder explicitly and
+finally terminates your license, and (b) permanently, if the copyright
+holder fails to notify you of the violation by some reasonable means
+prior to 60 days after the cessation.
+
+ Moreover, your license from a particular copyright holder is
+reinstated permanently if the copyright holder notifies you of the
+violation by some reasonable means, this is the first time you have
+received notice of violation of this License (for any work) from that
+copyright holder, and you cure the violation prior to 30 days after
+your receipt of the notice.
+
+ Termination of your rights under this section does not terminate the
+licenses of parties who have received copies or rights from you under
+this License. If your rights have been terminated and not permanently
+reinstated, you do not qualify to receive new licenses for the same
+material under section 10.
+
+ 9. Acceptance Not Required for Having Copies.
+
+ You are not required to accept this License in order to receive or
+run a copy of the Program. Ancillary propagation of a covered work
+occurring solely as a consequence of using peer-to-peer transmission
+to receive a copy likewise does not require acceptance. However,
+nothing other than this License grants you permission to propagate or
+modify any covered work. These actions infringe copyright if you do
+not accept this License. Therefore, by modifying or propagating a
+covered work, you indicate your acceptance of this License to do so.
+
+ 10. Automatic Licensing of Downstream Recipients.
+
+ Each time you convey a covered work, the recipient automatically
+receives a license from the original licensors, to run, modify and
+propagate that work, subject to this License. You are not responsible
+for enforcing compliance by third parties with this License.
+
+ An "entity transaction" is a transaction transferring control of an
+organization, or substantially all assets of one, or subdividing an
+organization, or merging organizations. If propagation of a covered
+work results from an entity transaction, each party to that
+transaction who receives a copy of the work also receives whatever
+licenses to the work the party's predecessor in interest had or could
+give under the previous paragraph, plus a right to possession of the
+Corresponding Source of the work from the predecessor in interest, if
+the predecessor has it or can get it with reasonable efforts.
+
+ You may not impose any further restrictions on the exercise of the
+rights granted or affirmed under this License. For example, you may
+not impose a license fee, royalty, or other charge for exercise of
+rights granted under this License, and you may not initiate litigation
+(including a cross-claim or counterclaim in a lawsuit) alleging that
+any patent claim is infringed by making, using, selling, offering for
+sale, or importing the Program or any portion of it.
+
+ 11. Patents.
+
+ A "contributor" is a copyright holder who authorizes use under this
+License of the Program or a work on which the Program is based. The
+work thus licensed is called the contributor's "contributor version".
+
+ A contributor's "essential patent claims" are all patent claims
+owned or controlled by the contributor, whether already acquired or
+hereafter acquired, that would be infringed by some manner, permitted
+by this License, of making, using, or selling its contributor version,
+but do not include claims that would be infringed only as a
+consequence of further modification of the contributor version. For
+purposes of this definition, "control" includes the right to grant
+patent sublicenses in a manner consistent with the requirements of
+this License.
+
+ Each contributor grants you a non-exclusive, worldwide, royalty-free
+patent license under the contributor's essential patent claims, to
+make, use, sell, offer for sale, import and otherwise run, modify and
+propagate the contents of its contributor version.
+
+ In the following three paragraphs, a "patent license" is any express
+agreement or commitment, however denominated, not to enforce a patent
+(such as an express permission to practice a patent or covenant not to
+sue for patent infringement). To "grant" such a patent license to a
+party means to make such an agreement or commitment not to enforce a
+patent against the party.
+
+ If you convey a covered work, knowingly relying on a patent license,
+and the Corresponding Source of the work is not available for anyone
+to copy, free of charge and under the terms of this License, through a
+publicly available network server or other readily accessible means,
+then you must either (1) cause the Corresponding Source to be so
+available, or (2) arrange to deprive yourself of the benefit of the
+patent license for this particular work, or (3) arrange, in a manner
+consistent with the requirements of this License, to extend the patent
+license to downstream recipients. "Knowingly relying" means you have
+actual knowledge that, but for the patent license, your conveying the
+covered work in a country, or your recipient's use of the covered work
+in a country, would infringe one or more identifiable patents in that
+country that you have reason to believe are valid.
+
+ If, pursuant to or in connection with a single transaction or
+arrangement, you convey, or propagate by procuring conveyance of, a
+covered work, and grant a patent license to some of the parties
+receiving the covered work authorizing them to use, propagate, modify
+or convey a specific copy of the covered work, then the patent license
+you grant is automatically extended to all recipients of the covered
+work and works based on it.
+
+ A patent license is "discriminatory" if it does not include within
+the scope of its coverage, prohibits the exercise of, or is
+conditioned on the non-exercise of one or more of the rights that are
+specifically granted under this License. You may not convey a covered
+work if you are a party to an arrangement with a third party that is
+in the business of distributing software, under which you make payment
+to the third party based on the extent of your activity of conveying
+the work, and under which the third party grants, to any of the
+parties who would receive the covered work from you, a discriminatory
+patent license (a) in connection with copies of the covered work
+conveyed by you (or copies made from those copies), or (b) primarily
+for and in connection with specific products or compilations that
+contain the covered work, unless you entered into that arrangement,
+or that patent license was granted, prior to 28 March 2007.
+
+ Nothing in this License shall be construed as excluding or limiting
+any implied license or other defenses to infringement that may
+otherwise be available to you under applicable patent law.
+
+ 12. No Surrender of Others' Freedom.
+
+ If conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License. If you cannot convey a
+covered work so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you may
+not convey it at all. For example, if you agree to terms that obligate you
+to collect a royalty for further conveying from those to whom you convey
+the Program, the only way you could satisfy both those terms and this
+License would be to refrain entirely from conveying the Program.
+
+ 13. Use with the GNU Affero General Public License.
+
+ Notwithstanding any other provision of this License, you have
+permission to link or combine any covered work with a work licensed
+under version 3 of the GNU Affero General Public License into a single
+combined work, and to convey the resulting work. The terms of this
+License will continue to apply to the part which is the covered work,
+but the special requirements of the GNU Affero General Public License,
+section 13, concerning interaction through a network will apply to the
+combination as such.
+
+ 14. Revised Versions of this License.
+
+ The Free Software Foundation may publish revised and/or new versions of
+the GNU General Public License from time to time. Such new versions will
+be similar in spirit to the present version, but may differ in detail to
+address new problems or concerns.
+
+ Each version is given a distinguishing version number. If the
+Program specifies that a certain numbered version of the GNU General
+Public License "or any later version" applies to it, you have the
+option of following the terms and conditions either of that numbered
+version or of any later version published by the Free Software
+Foundation. If the Program does not specify a version number of the
+GNU General Public License, you may choose any version ever published
+by the Free Software Foundation.
+
+ If the Program specifies that a proxy can decide which future
+versions of the GNU General Public License can be used, that proxy's
+public statement of acceptance of a version permanently authorizes you
+to choose that version for the Program.
+
+ Later license versions may give you additional or different
+permissions. However, no additional obligations are imposed on any
+author or copyright holder as a result of your choosing to follow a
+later version.
+
+ 15. Disclaimer of Warranty.
+
+ THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY
+APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT
+HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY
+OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO,
+THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM
+IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF
+ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
+
+ 16. Limitation of Liability.
+
+ IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS
+THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY
+GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE
+USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF
+DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD
+PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS),
+EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF
+SUCH DAMAGES.
+
+ 17. Interpretation of Sections 15 and 16.
+
+ If the disclaimer of warranty and limitation of liability provided
+above cannot be given local legal effect according to their terms,
+reviewing courts shall apply local law that most closely approximates
+an absolute waiver of all civil liability in connection with the
+Program, unless a warranty or assumption of liability accompanies a
+copy of the Program in return for a fee.
+
+ END OF TERMS AND CONDITIONS
+
+ How to Apply These Terms to Your New Programs
+
+ If you develop a new program, and you want it to be of the greatest
+possible use to the public, the best way to achieve this is to make it
+free software which everyone can redistribute and change under these terms.
+
+ To do so, attach the following notices to the program. It is safest
+to attach them to the start of each source file to most effectively
+state the exclusion of warranty; and each file should have at least
+the "copyright" line and a pointer to where the full notice is found.
+
+
+ Copyright (C)
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see .
+
+Also add information on how to contact you by electronic and paper mail.
+
+ If the program does terminal interaction, make it output a short
+notice like this when it starts in an interactive mode:
+
+ Copyright (C)
+ This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
+ This is free software, and you are welcome to redistribute it
+ under certain conditions; type `show c' for details.
+
+The hypothetical commands `show w' and `show c' should show the appropriate
+parts of the General Public License. Of course, your program's commands
+might be different; for a GUI interface, you would use an "about box".
+
+ You should also get your employer (if you work as a programmer) or school,
+if any, to sign a "copyright disclaimer" for the program, if necessary.
+For more information on this, and how to apply and follow the GNU GPL, see
+.
+
+ The GNU General Public License does not permit incorporating your program
+into proprietary programs. If your program is a subroutine library, you
+may consider it more useful to permit linking proprietary applications with
+the library. If this is what you want to do, use the GNU Lesser General
+Public License instead of this License. But first, please read
+.
diff --git a/modules/sale_invoice_grouping/MANIFEST.in b/modules/sale_invoice_grouping/MANIFEST.in
new file mode 100644
index 0000000000..e88b2348a3
--- /dev/null
+++ b/modules/sale_invoice_grouping/MANIFEST.in
@@ -0,0 +1,5 @@
+include CHANGELOG
+include COPYRIGHT
+include LICENSE
+include README.rst
+include doc/*
diff --git a/modules/sale_invoice_grouping/README.rst b/modules/sale_invoice_grouping/README.rst
new file mode 120000
index 0000000000..176d9c2695
--- /dev/null
+++ b/modules/sale_invoice_grouping/README.rst
@@ -0,0 +1 @@
+doc/index.rst
\ No newline at end of file
diff --git a/modules/sale_invoice_grouping/__init__.py b/modules/sale_invoice_grouping/__init__.py
new file mode 100644
index 0000000000..065d1d2fcf
--- /dev/null
+++ b/modules/sale_invoice_grouping/__init__.py
@@ -0,0 +1,17 @@
+# This file is part of Tryton. The COPYRIGHT file at the top level of
+# this repository contains the full copyright notices and license terms.
+
+from trytond.pool import Pool
+from . import party
+from . import sale
+from . import configuration
+
+
+def register():
+ Pool.register(
+ sale.Sale,
+ party.Party,
+ party.PartySaleInvoiceGroupingMethod,
+ configuration.Configuration,
+ configuration.ConfigurationSaleMethod,
+ module='sale_invoice_grouping', type_='model')
diff --git a/modules/sale_invoice_grouping/configuration.py b/modules/sale_invoice_grouping/configuration.py
new file mode 100644
index 0000000000..d9dde69f7f
--- /dev/null
+++ b/modules/sale_invoice_grouping/configuration.py
@@ -0,0 +1,38 @@
+# This file is part of Tryton. The COPYRIGHT file at the top level of
+# this repository contains the full copyright notices and license terms.
+from trytond.model import fields
+from trytond.pool import Pool, PoolMeta
+
+sale_invoice_grouping_method = fields.Selection(
+ 'get_sale_invoice_grouping_methods', "Sale Invoice Grouping Method",
+ help="The default invoice grouping method for new customers.")
+
+
+@classmethod
+def get_sale_invoice_grouping_methods(cls):
+ pool = Pool()
+ Party = pool.get('party.party')
+ field_name = 'sale_invoice_grouping_method'
+ return Party.fields_get([field_name])[field_name]['selection']
+
+
+class Configuration(metaclass=PoolMeta):
+ __name__ = 'sale.configuration'
+
+ sale_invoice_grouping_method = fields.MultiValue(
+ sale_invoice_grouping_method)
+ get_sale_invoice_grouping_methods = get_sale_invoice_grouping_methods
+
+ @classmethod
+ def multivalue_model(cls, field):
+ pool = Pool()
+ if field == 'sale_invoice_grouping_method':
+ return pool.get('sale.configuration.sale_method')
+ return super(Configuration, cls).multivalue_model(field)
+
+
+class ConfigurationSaleMethod(metaclass=PoolMeta):
+ __name__ = 'sale.configuration.sale_method'
+
+ sale_invoice_grouping_method = sale_invoice_grouping_method
+ get_sale_invoice_grouping_methods = get_sale_invoice_grouping_methods
diff --git a/modules/sale_invoice_grouping/configuration.xml b/modules/sale_invoice_grouping/configuration.xml
new file mode 100644
index 0000000000..1be072a305
--- /dev/null
+++ b/modules/sale_invoice_grouping/configuration.xml
@@ -0,0 +1,12 @@
+
+
+
+
+
+ sale.configuration
+
+ configuration_form
+
+
+
diff --git a/modules/sale_invoice_grouping/doc/index.rst b/modules/sale_invoice_grouping/doc/index.rst
new file mode 100644
index 0000000000..aa1fa87108
--- /dev/null
+++ b/modules/sale_invoice_grouping/doc/index.rst
@@ -0,0 +1,14 @@
+Sale Invoice Grouping Module
+############################
+
+The ``sale_invoice_grouping`` module adds an option to define how invoice lines
+generated from sales will be grouped.
+
+A field is added to the *Party*:
+
+- *Sale Invoice Grouping Method*: The method used when grouping invoice lines.
+
+If the Standard method is used, invoice lines generated will be added to the
+first matching invoice found. If no invoice matches sale attributes then a new
+one will be created. Invoices not created by the sale process are not taken
+into account when looking for a candidate invoice to add invoice lines to.
diff --git a/modules/sale_invoice_grouping/locale/bg.po b/modules/sale_invoice_grouping/locale/bg.po
new file mode 100644
index 0000000000..0d4e745282
--- /dev/null
+++ b/modules/sale_invoice_grouping/locale/bg.po
@@ -0,0 +1,54 @@
+#
+msgid ""
+msgstr "Content-Type: text/plain; charset=utf-8\n"
+
+msgctxt "field:party.party,sale_invoice_grouping_method:"
+msgid "Sale Invoice Grouping Method"
+msgstr ""
+
+msgctxt "field:party.party,sale_invoice_grouping_methods:"
+msgid "Sale Invoice Grouping Methods"
+msgstr ""
+
+msgctxt "field:party.party.sale_invoice_grouping_method,party:"
+msgid "Party"
+msgstr ""
+
+msgctxt ""
+"field:party.party.sale_invoice_grouping_method,sale_invoice_grouping_method:"
+msgid "Sale Invoice Grouping Method"
+msgstr ""
+
+msgctxt "field:sale.configuration,sale_invoice_grouping_method:"
+msgid "Sale Invoice Grouping Method"
+msgstr ""
+
+msgctxt "field:sale.configuration.sale_method,sale_invoice_grouping_method:"
+msgid "Sale Invoice Grouping Method"
+msgstr ""
+
+msgctxt "help:sale.configuration,sale_invoice_grouping_method:"
+msgid "The default invoice grouping method for new customers."
+msgstr ""
+
+msgctxt "help:sale.configuration.sale_method,sale_invoice_grouping_method:"
+msgid "The default invoice grouping method for new customers."
+msgstr ""
+
+msgctxt "model:party.party.sale_invoice_grouping_method,name:"
+msgid "Party Sale Invoice Grouping Method"
+msgstr ""
+
+#, fuzzy
+msgctxt "selection:party.party,sale_invoice_grouping_method:"
+msgid "None"
+msgstr "Няма"
+
+#, fuzzy
+msgctxt "selection:party.party,sale_invoice_grouping_method:"
+msgid "Standard"
+msgstr "Стандартен"
+
+msgctxt "view:party.party:"
+msgid "Invoicing"
+msgstr ""
diff --git a/modules/sale_invoice_grouping/locale/ca.po b/modules/sale_invoice_grouping/locale/ca.po
new file mode 100644
index 0000000000..f7a6748a68
--- /dev/null
+++ b/modules/sale_invoice_grouping/locale/ca.po
@@ -0,0 +1,52 @@
+#
+msgid ""
+msgstr "Content-Type: text/plain; charset=utf-8\n"
+
+msgctxt "field:party.party,sale_invoice_grouping_method:"
+msgid "Sale Invoice Grouping Method"
+msgstr "Mètode d'agrupació factures de venda"
+
+msgctxt "field:party.party,sale_invoice_grouping_methods:"
+msgid "Sale Invoice Grouping Methods"
+msgstr "Mètodes d'agrupació factures de venda"
+
+msgctxt "field:party.party.sale_invoice_grouping_method,party:"
+msgid "Party"
+msgstr "Tercer"
+
+msgctxt ""
+"field:party.party.sale_invoice_grouping_method,sale_invoice_grouping_method:"
+msgid "Sale Invoice Grouping Method"
+msgstr "Mètode d'agrupació factures de venda"
+
+msgctxt "field:sale.configuration,sale_invoice_grouping_method:"
+msgid "Sale Invoice Grouping Method"
+msgstr "Mètode d'agrupació factures de venda"
+
+msgctxt "field:sale.configuration.sale_method,sale_invoice_grouping_method:"
+msgid "Sale Invoice Grouping Method"
+msgstr "Mètode d'agrupació factures de venda"
+
+msgctxt "help:sale.configuration,sale_invoice_grouping_method:"
+msgid "The default invoice grouping method for new customers."
+msgstr "El mètode d'agrupació de factures per als nous clients."
+
+msgctxt "help:sale.configuration.sale_method,sale_invoice_grouping_method:"
+msgid "The default invoice grouping method for new customers."
+msgstr "El mètode d'agrupació de factures per als nous clients."
+
+msgctxt "model:party.party.sale_invoice_grouping_method,name:"
+msgid "Party Sale Invoice Grouping Method"
+msgstr "Mètode d'agrupació factures de venda"
+
+msgctxt "selection:party.party,sale_invoice_grouping_method:"
+msgid "None"
+msgstr "Cap"
+
+msgctxt "selection:party.party,sale_invoice_grouping_method:"
+msgid "Standard"
+msgstr "Estàndard"
+
+msgctxt "view:party.party:"
+msgid "Invoicing"
+msgstr "Facturació"
diff --git a/modules/sale_invoice_grouping/locale/cs.po b/modules/sale_invoice_grouping/locale/cs.po
new file mode 100644
index 0000000000..54a581e066
--- /dev/null
+++ b/modules/sale_invoice_grouping/locale/cs.po
@@ -0,0 +1,52 @@
+#
+msgid ""
+msgstr "Content-Type: text/plain; charset=utf-8\n"
+
+msgctxt "field:party.party,sale_invoice_grouping_method:"
+msgid "Sale Invoice Grouping Method"
+msgstr ""
+
+msgctxt "field:party.party,sale_invoice_grouping_methods:"
+msgid "Sale Invoice Grouping Methods"
+msgstr ""
+
+msgctxt "field:party.party.sale_invoice_grouping_method,party:"
+msgid "Party"
+msgstr ""
+
+msgctxt ""
+"field:party.party.sale_invoice_grouping_method,sale_invoice_grouping_method:"
+msgid "Sale Invoice Grouping Method"
+msgstr ""
+
+msgctxt "field:sale.configuration,sale_invoice_grouping_method:"
+msgid "Sale Invoice Grouping Method"
+msgstr ""
+
+msgctxt "field:sale.configuration.sale_method,sale_invoice_grouping_method:"
+msgid "Sale Invoice Grouping Method"
+msgstr ""
+
+msgctxt "help:sale.configuration,sale_invoice_grouping_method:"
+msgid "The default invoice grouping method for new customers."
+msgstr ""
+
+msgctxt "help:sale.configuration.sale_method,sale_invoice_grouping_method:"
+msgid "The default invoice grouping method for new customers."
+msgstr ""
+
+msgctxt "model:party.party.sale_invoice_grouping_method,name:"
+msgid "Party Sale Invoice Grouping Method"
+msgstr ""
+
+msgctxt "selection:party.party,sale_invoice_grouping_method:"
+msgid "None"
+msgstr ""
+
+msgctxt "selection:party.party,sale_invoice_grouping_method:"
+msgid "Standard"
+msgstr ""
+
+msgctxt "view:party.party:"
+msgid "Invoicing"
+msgstr ""
diff --git a/modules/sale_invoice_grouping/locale/de.po b/modules/sale_invoice_grouping/locale/de.po
new file mode 100644
index 0000000000..7e528a99c3
--- /dev/null
+++ b/modules/sale_invoice_grouping/locale/de.po
@@ -0,0 +1,52 @@
+#
+msgid ""
+msgstr "Content-Type: text/plain; charset=utf-8\n"
+
+msgctxt "field:party.party,sale_invoice_grouping_method:"
+msgid "Sale Invoice Grouping Method"
+msgstr "Gruppierungsmethode Rechnungsstellung (Verkauf)"
+
+msgctxt "field:party.party,sale_invoice_grouping_methods:"
+msgid "Sale Invoice Grouping Methods"
+msgstr "Gruppierungsmethode Rechnungsstellung (Verkauf)"
+
+msgctxt "field:party.party.sale_invoice_grouping_method,party:"
+msgid "Party"
+msgstr "Partei"
+
+msgctxt ""
+"field:party.party.sale_invoice_grouping_method,sale_invoice_grouping_method:"
+msgid "Sale Invoice Grouping Method"
+msgstr "Gruppierungsmethode Rechnungsstellung (Verkauf)"
+
+msgctxt "field:sale.configuration,sale_invoice_grouping_method:"
+msgid "Sale Invoice Grouping Method"
+msgstr "Gruppierungsmethode Rechnungsstellung (Verkauf)"
+
+msgctxt "field:sale.configuration.sale_method,sale_invoice_grouping_method:"
+msgid "Sale Invoice Grouping Method"
+msgstr "Gruppierungsmethode Rechnungsstellung (Verkauf)"
+
+msgctxt "help:sale.configuration,sale_invoice_grouping_method:"
+msgid "The default invoice grouping method for new customers."
+msgstr "Die Standard-Methode für gruppierte Rechnungen an neue Kunden."
+
+msgctxt "help:sale.configuration.sale_method,sale_invoice_grouping_method:"
+msgid "The default invoice grouping method for new customers."
+msgstr "Die Standard-Methode für gruppierte Rechnungen an neue Kunden."
+
+msgctxt "model:party.party.sale_invoice_grouping_method,name:"
+msgid "Party Sale Invoice Grouping Method"
+msgstr "Gruppierungsmethode Rechnungsstellung Partei (Verkauf)"
+
+msgctxt "selection:party.party,sale_invoice_grouping_method:"
+msgid "None"
+msgstr "Keine"
+
+msgctxt "selection:party.party,sale_invoice_grouping_method:"
+msgid "Standard"
+msgstr "Standard"
+
+msgctxt "view:party.party:"
+msgid "Invoicing"
+msgstr "Rechnungsstellung"
diff --git a/modules/sale_invoice_grouping/locale/es.po b/modules/sale_invoice_grouping/locale/es.po
new file mode 100644
index 0000000000..af5321098a
--- /dev/null
+++ b/modules/sale_invoice_grouping/locale/es.po
@@ -0,0 +1,54 @@
+#
+msgid ""
+msgstr "Content-Type: text/plain; charset=utf-8\n"
+
+msgctxt "field:party.party,sale_invoice_grouping_method:"
+msgid "Sale Invoice Grouping Method"
+msgstr "Método agrupación facturas de venta"
+
+msgctxt "field:party.party,sale_invoice_grouping_methods:"
+msgid "Sale Invoice Grouping Methods"
+msgstr "Método agrupación facturas de venta"
+
+msgctxt "field:party.party.sale_invoice_grouping_method,party:"
+msgid "Party"
+msgstr "Tercero"
+
+msgctxt ""
+"field:party.party.sale_invoice_grouping_method,sale_invoice_grouping_method:"
+msgid "Sale Invoice Grouping Method"
+msgstr "Método agrupación facturas de venta"
+
+msgctxt "field:sale.configuration,sale_invoice_grouping_method:"
+msgid "Sale Invoice Grouping Method"
+msgstr "Método agrupación facturas de venta"
+
+msgctxt "field:sale.configuration.sale_method,sale_invoice_grouping_method:"
+msgid "Sale Invoice Grouping Method"
+msgstr "Método agrupación facturas de venta"
+
+msgctxt "help:sale.configuration,sale_invoice_grouping_method:"
+msgid "The default invoice grouping method for new customers."
+msgstr ""
+"El método de agrupación de facturas por defecto para los nuevos clientes."
+
+msgctxt "help:sale.configuration.sale_method,sale_invoice_grouping_method:"
+msgid "The default invoice grouping method for new customers."
+msgstr ""
+"El método de agrupación de facturas por defecto para los nuevos clientes."
+
+msgctxt "model:party.party.sale_invoice_grouping_method,name:"
+msgid "Party Sale Invoice Grouping Method"
+msgstr "Método agrupación facturas de venta"
+
+msgctxt "selection:party.party,sale_invoice_grouping_method:"
+msgid "None"
+msgstr "Ninguno"
+
+msgctxt "selection:party.party,sale_invoice_grouping_method:"
+msgid "Standard"
+msgstr "Estándar"
+
+msgctxt "view:party.party:"
+msgid "Invoicing"
+msgstr "Facturación"
diff --git a/modules/sale_invoice_grouping/locale/es_419.po b/modules/sale_invoice_grouping/locale/es_419.po
new file mode 100644
index 0000000000..9cb894e1fe
--- /dev/null
+++ b/modules/sale_invoice_grouping/locale/es_419.po
@@ -0,0 +1,52 @@
+#
+msgid ""
+msgstr "Content-Type: text/plain; charset=utf-8\n"
+
+msgctxt "field:party.party,sale_invoice_grouping_method:"
+msgid "Sale Invoice Grouping Method"
+msgstr "Método de agrupación de facturas de venta"
+
+msgctxt "field:party.party,sale_invoice_grouping_methods:"
+msgid "Sale Invoice Grouping Methods"
+msgstr "Método de agrupación de facturas de venta"
+
+msgctxt "field:party.party.sale_invoice_grouping_method,party:"
+msgid "Party"
+msgstr ""
+
+msgctxt ""
+"field:party.party.sale_invoice_grouping_method,sale_invoice_grouping_method:"
+msgid "Sale Invoice Grouping Method"
+msgstr "Método de agrupación de facturas de venta"
+
+msgctxt "field:sale.configuration,sale_invoice_grouping_method:"
+msgid "Sale Invoice Grouping Method"
+msgstr "Método de agrupación de facturas de venta"
+
+msgctxt "field:sale.configuration.sale_method,sale_invoice_grouping_method:"
+msgid "Sale Invoice Grouping Method"
+msgstr "Método de agrupación de facturas de venta"
+
+msgctxt "help:sale.configuration,sale_invoice_grouping_method:"
+msgid "The default invoice grouping method for new customers."
+msgstr ""
+
+msgctxt "help:sale.configuration.sale_method,sale_invoice_grouping_method:"
+msgid "The default invoice grouping method for new customers."
+msgstr ""
+
+msgctxt "model:party.party.sale_invoice_grouping_method,name:"
+msgid "Party Sale Invoice Grouping Method"
+msgstr "Método de agrupación de facturas de venta"
+
+msgctxt "selection:party.party,sale_invoice_grouping_method:"
+msgid "None"
+msgstr ""
+
+msgctxt "selection:party.party,sale_invoice_grouping_method:"
+msgid "Standard"
+msgstr ""
+
+msgctxt "view:party.party:"
+msgid "Invoicing"
+msgstr ""
diff --git a/modules/sale_invoice_grouping/locale/et.po b/modules/sale_invoice_grouping/locale/et.po
new file mode 100644
index 0000000000..13e74e2baa
--- /dev/null
+++ b/modules/sale_invoice_grouping/locale/et.po
@@ -0,0 +1,52 @@
+#
+msgid ""
+msgstr "Content-Type: text/plain; charset=utf-8\n"
+
+msgctxt "field:party.party,sale_invoice_grouping_method:"
+msgid "Sale Invoice Grouping Method"
+msgstr "Müügiarvete grupeerimise meetod"
+
+msgctxt "field:party.party,sale_invoice_grouping_methods:"
+msgid "Sale Invoice Grouping Methods"
+msgstr "Müügiarvete grupeerimise meetodid"
+
+msgctxt "field:party.party.sale_invoice_grouping_method,party:"
+msgid "Party"
+msgstr "Osapool"
+
+msgctxt ""
+"field:party.party.sale_invoice_grouping_method,sale_invoice_grouping_method:"
+msgid "Sale Invoice Grouping Method"
+msgstr "Müügiarvete grupeerimise meetod"
+
+msgctxt "field:sale.configuration,sale_invoice_grouping_method:"
+msgid "Sale Invoice Grouping Method"
+msgstr "Müügiarvete grupeerimise meetod"
+
+msgctxt "field:sale.configuration.sale_method,sale_invoice_grouping_method:"
+msgid "Sale Invoice Grouping Method"
+msgstr "Müügiarvete grupeerimise meetod"
+
+msgctxt "help:sale.configuration,sale_invoice_grouping_method:"
+msgid "The default invoice grouping method for new customers."
+msgstr "Vaikimisi uute klientide arvete grupeerimise meetod."
+
+msgctxt "help:sale.configuration.sale_method,sale_invoice_grouping_method:"
+msgid "The default invoice grouping method for new customers."
+msgstr "Vaikimisi uute klientide arvete grupeerimise meetod."
+
+msgctxt "model:party.party.sale_invoice_grouping_method,name:"
+msgid "Party Sale Invoice Grouping Method"
+msgstr "Osapoole müügiarvete grupeerimise meetod"
+
+msgctxt "selection:party.party,sale_invoice_grouping_method:"
+msgid "None"
+msgstr "Mitte"
+
+msgctxt "selection:party.party,sale_invoice_grouping_method:"
+msgid "Standard"
+msgstr "Standard"
+
+msgctxt "view:party.party:"
+msgid "Invoicing"
+msgstr "Arveldamine"
diff --git a/modules/sale_invoice_grouping/locale/fa.po b/modules/sale_invoice_grouping/locale/fa.po
new file mode 100644
index 0000000000..87f55d7d10
--- /dev/null
+++ b/modules/sale_invoice_grouping/locale/fa.po
@@ -0,0 +1,52 @@
+#
+msgid ""
+msgstr "Content-Type: text/plain; charset=utf-8\n"
+
+msgctxt "field:party.party,sale_invoice_grouping_method:"
+msgid "Sale Invoice Grouping Method"
+msgstr "متد گروهبندی صورتحساب فروش"
+
+msgctxt "field:party.party,sale_invoice_grouping_methods:"
+msgid "Sale Invoice Grouping Methods"
+msgstr "متدهای گروهبندی صورتحساب فروش"
+
+msgctxt "field:party.party.sale_invoice_grouping_method,party:"
+msgid "Party"
+msgstr "نهاد/سازمان"
+
+msgctxt ""
+"field:party.party.sale_invoice_grouping_method,sale_invoice_grouping_method:"
+msgid "Sale Invoice Grouping Method"
+msgstr "متد گروهبندی صورتحساب فروش"
+
+msgctxt "field:sale.configuration,sale_invoice_grouping_method:"
+msgid "Sale Invoice Grouping Method"
+msgstr "متد گروهبندی صورتحساب فروش"
+
+msgctxt "field:sale.configuration.sale_method,sale_invoice_grouping_method:"
+msgid "Sale Invoice Grouping Method"
+msgstr "متد گروهبندی صورتحساب فروش"
+
+msgctxt "help:sale.configuration,sale_invoice_grouping_method:"
+msgid "The default invoice grouping method for new customers."
+msgstr "متد گروهبندی صورتحساب پیش فرض برای مشتریان جدید."
+
+msgctxt "help:sale.configuration.sale_method,sale_invoice_grouping_method:"
+msgid "The default invoice grouping method for new customers."
+msgstr "متد گروهبندی صورتحساب پیش فرض برای مشتریان جدید."
+
+msgctxt "model:party.party.sale_invoice_grouping_method,name:"
+msgid "Party Sale Invoice Grouping Method"
+msgstr "متد گروهبندی صورتحساب فروش نهاد/سازمان"
+
+msgctxt "selection:party.party,sale_invoice_grouping_method:"
+msgid "None"
+msgstr "هیجکدام"
+
+msgctxt "selection:party.party,sale_invoice_grouping_method:"
+msgid "Standard"
+msgstr "استاندارد"
+
+msgctxt "view:party.party:"
+msgid "Invoicing"
+msgstr "فاکتورسازی"
diff --git a/modules/sale_invoice_grouping/locale/fi.po b/modules/sale_invoice_grouping/locale/fi.po
new file mode 100644
index 0000000000..54a581e066
--- /dev/null
+++ b/modules/sale_invoice_grouping/locale/fi.po
@@ -0,0 +1,52 @@
+#
+msgid ""
+msgstr "Content-Type: text/plain; charset=utf-8\n"
+
+msgctxt "field:party.party,sale_invoice_grouping_method:"
+msgid "Sale Invoice Grouping Method"
+msgstr ""
+
+msgctxt "field:party.party,sale_invoice_grouping_methods:"
+msgid "Sale Invoice Grouping Methods"
+msgstr ""
+
+msgctxt "field:party.party.sale_invoice_grouping_method,party:"
+msgid "Party"
+msgstr ""
+
+msgctxt ""
+"field:party.party.sale_invoice_grouping_method,sale_invoice_grouping_method:"
+msgid "Sale Invoice Grouping Method"
+msgstr ""
+
+msgctxt "field:sale.configuration,sale_invoice_grouping_method:"
+msgid "Sale Invoice Grouping Method"
+msgstr ""
+
+msgctxt "field:sale.configuration.sale_method,sale_invoice_grouping_method:"
+msgid "Sale Invoice Grouping Method"
+msgstr ""
+
+msgctxt "help:sale.configuration,sale_invoice_grouping_method:"
+msgid "The default invoice grouping method for new customers."
+msgstr ""
+
+msgctxt "help:sale.configuration.sale_method,sale_invoice_grouping_method:"
+msgid "The default invoice grouping method for new customers."
+msgstr ""
+
+msgctxt "model:party.party.sale_invoice_grouping_method,name:"
+msgid "Party Sale Invoice Grouping Method"
+msgstr ""
+
+msgctxt "selection:party.party,sale_invoice_grouping_method:"
+msgid "None"
+msgstr ""
+
+msgctxt "selection:party.party,sale_invoice_grouping_method:"
+msgid "Standard"
+msgstr ""
+
+msgctxt "view:party.party:"
+msgid "Invoicing"
+msgstr ""
diff --git a/modules/sale_invoice_grouping/locale/fr.po b/modules/sale_invoice_grouping/locale/fr.po
new file mode 100644
index 0000000000..0eb769f574
--- /dev/null
+++ b/modules/sale_invoice_grouping/locale/fr.po
@@ -0,0 +1,56 @@
+#
+msgid ""
+msgstr "Content-Type: text/plain; charset=utf-8\n"
+
+msgctxt "field:party.party,sale_invoice_grouping_method:"
+msgid "Sale Invoice Grouping Method"
+msgstr "Méthode de regroupement des factures de vente"
+
+msgctxt "field:party.party,sale_invoice_grouping_methods:"
+msgid "Sale Invoice Grouping Methods"
+msgstr "Méthodes de regroupement des factures de vente"
+
+msgctxt "field:party.party.sale_invoice_grouping_method,party:"
+msgid "Party"
+msgstr "Tiers"
+
+msgctxt ""
+"field:party.party.sale_invoice_grouping_method,sale_invoice_grouping_method:"
+msgid "Sale Invoice Grouping Method"
+msgstr "Méthode de regroupement des factures de vente"
+
+msgctxt "field:sale.configuration,sale_invoice_grouping_method:"
+msgid "Sale Invoice Grouping Method"
+msgstr "Méthode de regroupement des factures de vente"
+
+msgctxt "field:sale.configuration.sale_method,sale_invoice_grouping_method:"
+msgid "Sale Invoice Grouping Method"
+msgstr "Méthode de regroupement des factures de vente"
+
+msgctxt "help:sale.configuration,sale_invoice_grouping_method:"
+msgid "The default invoice grouping method for new customers."
+msgstr ""
+"La méthode par défaut de regroupement des factures pour les nouveaux "
+"clients."
+
+msgctxt "help:sale.configuration.sale_method,sale_invoice_grouping_method:"
+msgid "The default invoice grouping method for new customers."
+msgstr ""
+"La méthode par défaut de regroupement des factures pour les nouveaux "
+"clients."
+
+msgctxt "model:party.party.sale_invoice_grouping_method,name:"
+msgid "Party Sale Invoice Grouping Method"
+msgstr "Tiers Méthode de regroupement des factures de vente"
+
+msgctxt "selection:party.party,sale_invoice_grouping_method:"
+msgid "None"
+msgstr "Aucune"
+
+msgctxt "selection:party.party,sale_invoice_grouping_method:"
+msgid "Standard"
+msgstr "Standard"
+
+msgctxt "view:party.party:"
+msgid "Invoicing"
+msgstr "Facturation"
diff --git a/modules/sale_invoice_grouping/locale/hu.po b/modules/sale_invoice_grouping/locale/hu.po
new file mode 100644
index 0000000000..236623631d
--- /dev/null
+++ b/modules/sale_invoice_grouping/locale/hu.po
@@ -0,0 +1,53 @@
+#
+msgid ""
+msgstr "Content-Type: text/plain; charset=utf-8\n"
+
+msgctxt "field:party.party,sale_invoice_grouping_method:"
+msgid "Sale Invoice Grouping Method"
+msgstr ""
+
+msgctxt "field:party.party,sale_invoice_grouping_methods:"
+msgid "Sale Invoice Grouping Methods"
+msgstr ""
+
+msgctxt "field:party.party.sale_invoice_grouping_method,party:"
+msgid "Party"
+msgstr ""
+
+msgctxt ""
+"field:party.party.sale_invoice_grouping_method,sale_invoice_grouping_method:"
+msgid "Sale Invoice Grouping Method"
+msgstr ""
+
+msgctxt "field:sale.configuration,sale_invoice_grouping_method:"
+msgid "Sale Invoice Grouping Method"
+msgstr ""
+
+msgctxt "field:sale.configuration.sale_method,sale_invoice_grouping_method:"
+msgid "Sale Invoice Grouping Method"
+msgstr ""
+
+msgctxt "help:sale.configuration,sale_invoice_grouping_method:"
+msgid "The default invoice grouping method for new customers."
+msgstr ""
+
+msgctxt "help:sale.configuration.sale_method,sale_invoice_grouping_method:"
+msgid "The default invoice grouping method for new customers."
+msgstr ""
+
+msgctxt "model:party.party.sale_invoice_grouping_method,name:"
+msgid "Party Sale Invoice Grouping Method"
+msgstr ""
+
+#, fuzzy
+msgctxt "selection:party.party,sale_invoice_grouping_method:"
+msgid "None"
+msgstr "Nincs"
+
+msgctxt "selection:party.party,sale_invoice_grouping_method:"
+msgid "Standard"
+msgstr ""
+
+msgctxt "view:party.party:"
+msgid "Invoicing"
+msgstr ""
diff --git a/modules/sale_invoice_grouping/locale/id.po b/modules/sale_invoice_grouping/locale/id.po
new file mode 100644
index 0000000000..7a5d424bb2
--- /dev/null
+++ b/modules/sale_invoice_grouping/locale/id.po
@@ -0,0 +1,52 @@
+#
+msgid ""
+msgstr "Content-Type: text/plain; charset=utf-8\n"
+
+msgctxt "field:party.party,sale_invoice_grouping_method:"
+msgid "Sale Invoice Grouping Method"
+msgstr ""
+
+msgctxt "field:party.party,sale_invoice_grouping_methods:"
+msgid "Sale Invoice Grouping Methods"
+msgstr ""
+
+msgctxt "field:party.party.sale_invoice_grouping_method,party:"
+msgid "Party"
+msgstr "Pihak"
+
+msgctxt ""
+"field:party.party.sale_invoice_grouping_method,sale_invoice_grouping_method:"
+msgid "Sale Invoice Grouping Method"
+msgstr ""
+
+msgctxt "field:sale.configuration,sale_invoice_grouping_method:"
+msgid "Sale Invoice Grouping Method"
+msgstr ""
+
+msgctxt "field:sale.configuration.sale_method,sale_invoice_grouping_method:"
+msgid "Sale Invoice Grouping Method"
+msgstr ""
+
+msgctxt "help:sale.configuration,sale_invoice_grouping_method:"
+msgid "The default invoice grouping method for new customers."
+msgstr ""
+
+msgctxt "help:sale.configuration.sale_method,sale_invoice_grouping_method:"
+msgid "The default invoice grouping method for new customers."
+msgstr ""
+
+msgctxt "model:party.party.sale_invoice_grouping_method,name:"
+msgid "Party Sale Invoice Grouping Method"
+msgstr ""
+
+msgctxt "selection:party.party,sale_invoice_grouping_method:"
+msgid "None"
+msgstr "Tidak ada"
+
+msgctxt "selection:party.party,sale_invoice_grouping_method:"
+msgid "Standard"
+msgstr "Standar"
+
+msgctxt "view:party.party:"
+msgid "Invoicing"
+msgstr ""
diff --git a/modules/sale_invoice_grouping/locale/it.po b/modules/sale_invoice_grouping/locale/it.po
new file mode 100644
index 0000000000..396f1a01c8
--- /dev/null
+++ b/modules/sale_invoice_grouping/locale/it.po
@@ -0,0 +1,57 @@
+#
+msgid ""
+msgstr "Content-Type: text/plain; charset=utf-8\n"
+
+msgctxt "field:party.party,sale_invoice_grouping_method:"
+msgid "Sale Invoice Grouping Method"
+msgstr "Metodo di raggruppamento in fattura vendita"
+
+#, fuzzy
+msgctxt "field:party.party,sale_invoice_grouping_methods:"
+msgid "Sale Invoice Grouping Methods"
+msgstr "Metodo di raggruppamento in fattura vendita"
+
+msgctxt "field:party.party.sale_invoice_grouping_method,party:"
+msgid "Party"
+msgstr ""
+
+#, fuzzy
+msgctxt ""
+"field:party.party.sale_invoice_grouping_method,sale_invoice_grouping_method:"
+msgid "Sale Invoice Grouping Method"
+msgstr "Metodo di raggruppamento in fattura vendita"
+
+#, fuzzy
+msgctxt "field:sale.configuration,sale_invoice_grouping_method:"
+msgid "Sale Invoice Grouping Method"
+msgstr "Metodo di raggruppamento in fattura vendita"
+
+#, fuzzy
+msgctxt "field:sale.configuration.sale_method,sale_invoice_grouping_method:"
+msgid "Sale Invoice Grouping Method"
+msgstr "Metodo di raggruppamento in fattura vendita"
+
+msgctxt "help:sale.configuration,sale_invoice_grouping_method:"
+msgid "The default invoice grouping method for new customers."
+msgstr ""
+
+msgctxt "help:sale.configuration.sale_method,sale_invoice_grouping_method:"
+msgid "The default invoice grouping method for new customers."
+msgstr ""
+
+#, fuzzy
+msgctxt "model:party.party.sale_invoice_grouping_method,name:"
+msgid "Party Sale Invoice Grouping Method"
+msgstr "Metodo di raggruppamento in fattura vendita"
+
+msgctxt "selection:party.party,sale_invoice_grouping_method:"
+msgid "None"
+msgstr "Nessuno"
+
+msgctxt "selection:party.party,sale_invoice_grouping_method:"
+msgid "Standard"
+msgstr "Standard"
+
+msgctxt "view:party.party:"
+msgid "Invoicing"
+msgstr "fatturazione"
diff --git a/modules/sale_invoice_grouping/locale/lo.po b/modules/sale_invoice_grouping/locale/lo.po
new file mode 100644
index 0000000000..a9a7762ee9
--- /dev/null
+++ b/modules/sale_invoice_grouping/locale/lo.po
@@ -0,0 +1,57 @@
+#
+msgid ""
+msgstr "Content-Type: text/plain; charset=utf-8\n"
+
+msgctxt "field:party.party,sale_invoice_grouping_method:"
+msgid "Sale Invoice Grouping Method"
+msgstr "ວິທີຮວມກຸ່ມໃບເກັບເງິນ"
+
+#, fuzzy
+msgctxt "field:party.party,sale_invoice_grouping_methods:"
+msgid "Sale Invoice Grouping Methods"
+msgstr "ວິທີຮວມກຸ່ມໃບເກັບເງິນ"
+
+msgctxt "field:party.party.sale_invoice_grouping_method,party:"
+msgid "Party"
+msgstr ""
+
+#, fuzzy
+msgctxt ""
+"field:party.party.sale_invoice_grouping_method,sale_invoice_grouping_method:"
+msgid "Sale Invoice Grouping Method"
+msgstr "ວິທີຮວມກຸ່ມໃບເກັບເງິນ"
+
+#, fuzzy
+msgctxt "field:sale.configuration,sale_invoice_grouping_method:"
+msgid "Sale Invoice Grouping Method"
+msgstr "ວິທີຮວມກຸ່ມໃບເກັບເງິນ"
+
+#, fuzzy
+msgctxt "field:sale.configuration.sale_method,sale_invoice_grouping_method:"
+msgid "Sale Invoice Grouping Method"
+msgstr "ວິທີຮວມກຸ່ມໃບເກັບເງິນ"
+
+msgctxt "help:sale.configuration,sale_invoice_grouping_method:"
+msgid "The default invoice grouping method for new customers."
+msgstr ""
+
+msgctxt "help:sale.configuration.sale_method,sale_invoice_grouping_method:"
+msgid "The default invoice grouping method for new customers."
+msgstr ""
+
+#, fuzzy
+msgctxt "model:party.party.sale_invoice_grouping_method,name:"
+msgid "Party Sale Invoice Grouping Method"
+msgstr "ວິທີຮວມກຸ່ມໃບເກັບເງິນ"
+
+msgctxt "selection:party.party,sale_invoice_grouping_method:"
+msgid "None"
+msgstr "ບໍ່ມີ"
+
+msgctxt "selection:party.party,sale_invoice_grouping_method:"
+msgid "Standard"
+msgstr "ມາດຕະຖານ"
+
+msgctxt "view:party.party:"
+msgid "Invoicing"
+msgstr "ການສ້າງໃບເກັບເງິນ"
diff --git a/modules/sale_invoice_grouping/locale/lt.po b/modules/sale_invoice_grouping/locale/lt.po
new file mode 100644
index 0000000000..fefb050bf9
--- /dev/null
+++ b/modules/sale_invoice_grouping/locale/lt.po
@@ -0,0 +1,54 @@
+#
+msgid ""
+msgstr "Content-Type: text/plain; charset=utf-8\n"
+
+msgctxt "field:party.party,sale_invoice_grouping_method:"
+msgid "Sale Invoice Grouping Method"
+msgstr "Pardavimo sąskaitų faktūrų grupavimo būdas"
+
+msgctxt "field:party.party,sale_invoice_grouping_methods:"
+msgid "Sale Invoice Grouping Methods"
+msgstr "Pardavimo sąskaitų faktūrų grupavimo būdai"
+
+msgctxt "field:party.party.sale_invoice_grouping_method,party:"
+msgid "Party"
+msgstr ""
+
+msgctxt ""
+"field:party.party.sale_invoice_grouping_method,sale_invoice_grouping_method:"
+msgid "Sale Invoice Grouping Method"
+msgstr "Pardavimo sąskaitų faktūrų grupavimo būdas"
+
+msgctxt "field:sale.configuration,sale_invoice_grouping_method:"
+msgid "Sale Invoice Grouping Method"
+msgstr "Pardavimo sąskaitų faktūrų grupavimo būdas"
+
+msgctxt "field:sale.configuration.sale_method,sale_invoice_grouping_method:"
+msgid "Sale Invoice Grouping Method"
+msgstr "Pardavimo sąskaitų faktūrų grupavimo būdas"
+
+msgctxt "help:sale.configuration,sale_invoice_grouping_method:"
+msgid "The default invoice grouping method for new customers."
+msgstr ""
+"Numatytasis pardavimo sąskaitų faktūrų grupavimo būdas naujiems pirkėjams."
+
+msgctxt "help:sale.configuration.sale_method,sale_invoice_grouping_method:"
+msgid "The default invoice grouping method for new customers."
+msgstr ""
+"Numatytasis pardavimo sąskaitų faktūrų grupavimo būdas naujiems pirkėjams."
+
+msgctxt "model:party.party.sale_invoice_grouping_method,name:"
+msgid "Party Sale Invoice Grouping Method"
+msgstr "Pardavimo sąskaitų faktūrų grupavimo būdas kontrahentui"
+
+msgctxt "selection:party.party,sale_invoice_grouping_method:"
+msgid "None"
+msgstr ""
+
+msgctxt "selection:party.party,sale_invoice_grouping_method:"
+msgid "Standard"
+msgstr ""
+
+msgctxt "view:party.party:"
+msgid "Invoicing"
+msgstr ""
diff --git a/modules/sale_invoice_grouping/locale/nl.po b/modules/sale_invoice_grouping/locale/nl.po
new file mode 100644
index 0000000000..dc2af0dcdf
--- /dev/null
+++ b/modules/sale_invoice_grouping/locale/nl.po
@@ -0,0 +1,52 @@
+#
+msgid ""
+msgstr "Content-Type: text/plain; charset=utf-8\n"
+
+msgctxt "field:party.party,sale_invoice_grouping_method:"
+msgid "Sale Invoice Grouping Method"
+msgstr "Verzamelmethode verkoopfactuur"
+
+msgctxt "field:party.party,sale_invoice_grouping_methods:"
+msgid "Sale Invoice Grouping Methods"
+msgstr "Verzamelmethode verkoopfactuur"
+
+msgctxt "field:party.party.sale_invoice_grouping_method,party:"
+msgid "Party"
+msgstr "Relatie"
+
+msgctxt ""
+"field:party.party.sale_invoice_grouping_method,sale_invoice_grouping_method:"
+msgid "Sale Invoice Grouping Method"
+msgstr "Verzamelmethode verkoopfactuur"
+
+msgctxt "field:sale.configuration,sale_invoice_grouping_method:"
+msgid "Sale Invoice Grouping Method"
+msgstr "Verzamelmethode verkoopfactuur"
+
+msgctxt "field:sale.configuration.sale_method,sale_invoice_grouping_method:"
+msgid "Sale Invoice Grouping Method"
+msgstr "Verzamelmethode verkoopfactuur"
+
+msgctxt "help:sale.configuration,sale_invoice_grouping_method:"
+msgid "The default invoice grouping method for new customers."
+msgstr "De standaard factuurgroeperingsmethode voor nieuwe klanten."
+
+msgctxt "help:sale.configuration.sale_method,sale_invoice_grouping_method:"
+msgid "The default invoice grouping method for new customers."
+msgstr "De standaard factuurgroeperingsmethode voor nieuwe klanten."
+
+msgctxt "model:party.party.sale_invoice_grouping_method,name:"
+msgid "Party Sale Invoice Grouping Method"
+msgstr "relatie verkoop factuur groepering methode"
+
+msgctxt "selection:party.party,sale_invoice_grouping_method:"
+msgid "None"
+msgstr "Geen"
+
+msgctxt "selection:party.party,sale_invoice_grouping_method:"
+msgid "Standard"
+msgstr "Standaard"
+
+msgctxt "view:party.party:"
+msgid "Invoicing"
+msgstr "Facturering"
diff --git a/modules/sale_invoice_grouping/locale/pl.po b/modules/sale_invoice_grouping/locale/pl.po
new file mode 100644
index 0000000000..e7f15df0bb
--- /dev/null
+++ b/modules/sale_invoice_grouping/locale/pl.po
@@ -0,0 +1,52 @@
+#
+msgid ""
+msgstr "Content-Type: text/plain; charset=utf-8\n"
+
+msgctxt "field:party.party,sale_invoice_grouping_method:"
+msgid "Sale Invoice Grouping Method"
+msgstr ""
+
+msgctxt "field:party.party,sale_invoice_grouping_methods:"
+msgid "Sale Invoice Grouping Methods"
+msgstr ""
+
+msgctxt "field:party.party.sale_invoice_grouping_method,party:"
+msgid "Party"
+msgstr "Strona"
+
+msgctxt ""
+"field:party.party.sale_invoice_grouping_method,sale_invoice_grouping_method:"
+msgid "Sale Invoice Grouping Method"
+msgstr ""
+
+msgctxt "field:sale.configuration,sale_invoice_grouping_method:"
+msgid "Sale Invoice Grouping Method"
+msgstr ""
+
+msgctxt "field:sale.configuration.sale_method,sale_invoice_grouping_method:"
+msgid "Sale Invoice Grouping Method"
+msgstr ""
+
+msgctxt "help:sale.configuration,sale_invoice_grouping_method:"
+msgid "The default invoice grouping method for new customers."
+msgstr ""
+
+msgctxt "help:sale.configuration.sale_method,sale_invoice_grouping_method:"
+msgid "The default invoice grouping method for new customers."
+msgstr ""
+
+msgctxt "model:party.party.sale_invoice_grouping_method,name:"
+msgid "Party Sale Invoice Grouping Method"
+msgstr ""
+
+msgctxt "selection:party.party,sale_invoice_grouping_method:"
+msgid "None"
+msgstr "Brak"
+
+msgctxt "selection:party.party,sale_invoice_grouping_method:"
+msgid "Standard"
+msgstr "Standardowy"
+
+msgctxt "view:party.party:"
+msgid "Invoicing"
+msgstr ""
diff --git a/modules/sale_invoice_grouping/locale/pt.po b/modules/sale_invoice_grouping/locale/pt.po
new file mode 100644
index 0000000000..383ef776f7
--- /dev/null
+++ b/modules/sale_invoice_grouping/locale/pt.po
@@ -0,0 +1,52 @@
+#
+msgid ""
+msgstr "Content-Type: text/plain; charset=utf-8\n"
+
+msgctxt "field:party.party,sale_invoice_grouping_method:"
+msgid "Sale Invoice Grouping Method"
+msgstr "Método de Agrupamento de Fatura de Venda"
+
+msgctxt "field:party.party,sale_invoice_grouping_methods:"
+msgid "Sale Invoice Grouping Methods"
+msgstr "Fatura de Venda Métodos de Agrupamentos"
+
+msgctxt "field:party.party.sale_invoice_grouping_method,party:"
+msgid "Party"
+msgstr "Pessoa"
+
+msgctxt ""
+"field:party.party.sale_invoice_grouping_method,sale_invoice_grouping_method:"
+msgid "Sale Invoice Grouping Method"
+msgstr "Fatura de Venda Método de Agrupamento"
+
+msgctxt "field:sale.configuration,sale_invoice_grouping_method:"
+msgid "Sale Invoice Grouping Method"
+msgstr "Método de Agrupamento de Fatura de Venda"
+
+msgctxt "field:sale.configuration.sale_method,sale_invoice_grouping_method:"
+msgid "Sale Invoice Grouping Method"
+msgstr "Método de Agrupamento de Fatura de Venda"
+
+msgctxt "help:sale.configuration,sale_invoice_grouping_method:"
+msgid "The default invoice grouping method for new customers."
+msgstr "O método padrão para o agrupamento de faturas de novos clientes."
+
+msgctxt "help:sale.configuration.sale_method,sale_invoice_grouping_method:"
+msgid "The default invoice grouping method for new customers."
+msgstr "O método padrão para o agrupamento de faturas de novos clientes."
+
+msgctxt "model:party.party.sale_invoice_grouping_method,name:"
+msgid "Party Sale Invoice Grouping Method"
+msgstr "Fatura de Venda Métodos de Agrupamentos da Pessoa"
+
+msgctxt "selection:party.party,sale_invoice_grouping_method:"
+msgid "None"
+msgstr "Nenhum"
+
+msgctxt "selection:party.party,sale_invoice_grouping_method:"
+msgid "Standard"
+msgstr "Padrão"
+
+msgctxt "view:party.party:"
+msgid "Invoicing"
+msgstr "Faturamento"
diff --git a/modules/sale_invoice_grouping/locale/ro.po b/modules/sale_invoice_grouping/locale/ro.po
new file mode 100644
index 0000000000..607d923a28
--- /dev/null
+++ b/modules/sale_invoice_grouping/locale/ro.po
@@ -0,0 +1,52 @@
+#
+msgid ""
+msgstr "Content-Type: text/plain; charset=utf-8\n"
+
+msgctxt "field:party.party,sale_invoice_grouping_method:"
+msgid "Sale Invoice Grouping Method"
+msgstr ""
+
+msgctxt "field:party.party,sale_invoice_grouping_methods:"
+msgid "Sale Invoice Grouping Methods"
+msgstr ""
+
+msgctxt "field:party.party.sale_invoice_grouping_method,party:"
+msgid "Party"
+msgstr "Parte"
+
+msgctxt ""
+"field:party.party.sale_invoice_grouping_method,sale_invoice_grouping_method:"
+msgid "Sale Invoice Grouping Method"
+msgstr ""
+
+msgctxt "field:sale.configuration,sale_invoice_grouping_method:"
+msgid "Sale Invoice Grouping Method"
+msgstr ""
+
+msgctxt "field:sale.configuration.sale_method,sale_invoice_grouping_method:"
+msgid "Sale Invoice Grouping Method"
+msgstr ""
+
+msgctxt "help:sale.configuration,sale_invoice_grouping_method:"
+msgid "The default invoice grouping method for new customers."
+msgstr ""
+
+msgctxt "help:sale.configuration.sale_method,sale_invoice_grouping_method:"
+msgid "The default invoice grouping method for new customers."
+msgstr ""
+
+msgctxt "model:party.party.sale_invoice_grouping_method,name:"
+msgid "Party Sale Invoice Grouping Method"
+msgstr ""
+
+msgctxt "selection:party.party,sale_invoice_grouping_method:"
+msgid "None"
+msgstr ""
+
+msgctxt "selection:party.party,sale_invoice_grouping_method:"
+msgid "Standard"
+msgstr ""
+
+msgctxt "view:party.party:"
+msgid "Invoicing"
+msgstr ""
diff --git a/modules/sale_invoice_grouping/locale/ru.po b/modules/sale_invoice_grouping/locale/ru.po
new file mode 100644
index 0000000000..0e3f57faf3
--- /dev/null
+++ b/modules/sale_invoice_grouping/locale/ru.po
@@ -0,0 +1,54 @@
+#
+msgid ""
+msgstr "Content-Type: text/plain; charset=utf-8\n"
+
+msgctxt "field:party.party,sale_invoice_grouping_method:"
+msgid "Sale Invoice Grouping Method"
+msgstr ""
+
+msgctxt "field:party.party,sale_invoice_grouping_methods:"
+msgid "Sale Invoice Grouping Methods"
+msgstr ""
+
+msgctxt "field:party.party.sale_invoice_grouping_method,party:"
+msgid "Party"
+msgstr ""
+
+msgctxt ""
+"field:party.party.sale_invoice_grouping_method,sale_invoice_grouping_method:"
+msgid "Sale Invoice Grouping Method"
+msgstr ""
+
+msgctxt "field:sale.configuration,sale_invoice_grouping_method:"
+msgid "Sale Invoice Grouping Method"
+msgstr ""
+
+msgctxt "field:sale.configuration.sale_method,sale_invoice_grouping_method:"
+msgid "Sale Invoice Grouping Method"
+msgstr ""
+
+msgctxt "help:sale.configuration,sale_invoice_grouping_method:"
+msgid "The default invoice grouping method for new customers."
+msgstr ""
+
+msgctxt "help:sale.configuration.sale_method,sale_invoice_grouping_method:"
+msgid "The default invoice grouping method for new customers."
+msgstr ""
+
+msgctxt "model:party.party.sale_invoice_grouping_method,name:"
+msgid "Party Sale Invoice Grouping Method"
+msgstr ""
+
+#, fuzzy
+msgctxt "selection:party.party,sale_invoice_grouping_method:"
+msgid "None"
+msgstr "Отсутствует"
+
+#, fuzzy
+msgctxt "selection:party.party,sale_invoice_grouping_method:"
+msgid "Standard"
+msgstr "Стандартный"
+
+msgctxt "view:party.party:"
+msgid "Invoicing"
+msgstr ""
diff --git a/modules/sale_invoice_grouping/locale/sl.po b/modules/sale_invoice_grouping/locale/sl.po
new file mode 100644
index 0000000000..1b16739770
--- /dev/null
+++ b/modules/sale_invoice_grouping/locale/sl.po
@@ -0,0 +1,54 @@
+#
+msgid ""
+msgstr "Content-Type: text/plain; charset=utf-8\n"
+
+msgctxt "field:party.party,sale_invoice_grouping_method:"
+msgid "Sale Invoice Grouping Method"
+msgstr "Način združevanja izdanih računov"
+
+msgctxt "field:party.party,sale_invoice_grouping_methods:"
+msgid "Sale Invoice Grouping Methods"
+msgstr "Načini združevanja izdanih računov"
+
+msgctxt "field:party.party.sale_invoice_grouping_method,party:"
+msgid "Party"
+msgstr "Partner"
+
+msgctxt ""
+"field:party.party.sale_invoice_grouping_method,sale_invoice_grouping_method:"
+msgid "Sale Invoice Grouping Method"
+msgstr "Način združevanje izdanih računov"
+
+#, fuzzy
+msgctxt "field:sale.configuration,sale_invoice_grouping_method:"
+msgid "Sale Invoice Grouping Method"
+msgstr "Način združevanja izdanih računov"
+
+#, fuzzy
+msgctxt "field:sale.configuration.sale_method,sale_invoice_grouping_method:"
+msgid "Sale Invoice Grouping Method"
+msgstr "Način združevanja izdanih računov"
+
+msgctxt "help:sale.configuration,sale_invoice_grouping_method:"
+msgid "The default invoice grouping method for new customers."
+msgstr ""
+
+msgctxt "help:sale.configuration.sale_method,sale_invoice_grouping_method:"
+msgid "The default invoice grouping method for new customers."
+msgstr ""
+
+msgctxt "model:party.party.sale_invoice_grouping_method,name:"
+msgid "Party Sale Invoice Grouping Method"
+msgstr "Način združevanja izdanih računov partnerja"
+
+msgctxt "selection:party.party,sale_invoice_grouping_method:"
+msgid "None"
+msgstr "Brez"
+
+msgctxt "selection:party.party,sale_invoice_grouping_method:"
+msgid "Standard"
+msgstr "Standardno"
+
+msgctxt "view:party.party:"
+msgid "Invoicing"
+msgstr "Izdajanje računov"
diff --git a/modules/sale_invoice_grouping/locale/tr.po b/modules/sale_invoice_grouping/locale/tr.po
new file mode 100644
index 0000000000..54a581e066
--- /dev/null
+++ b/modules/sale_invoice_grouping/locale/tr.po
@@ -0,0 +1,52 @@
+#
+msgid ""
+msgstr "Content-Type: text/plain; charset=utf-8\n"
+
+msgctxt "field:party.party,sale_invoice_grouping_method:"
+msgid "Sale Invoice Grouping Method"
+msgstr ""
+
+msgctxt "field:party.party,sale_invoice_grouping_methods:"
+msgid "Sale Invoice Grouping Methods"
+msgstr ""
+
+msgctxt "field:party.party.sale_invoice_grouping_method,party:"
+msgid "Party"
+msgstr ""
+
+msgctxt ""
+"field:party.party.sale_invoice_grouping_method,sale_invoice_grouping_method:"
+msgid "Sale Invoice Grouping Method"
+msgstr ""
+
+msgctxt "field:sale.configuration,sale_invoice_grouping_method:"
+msgid "Sale Invoice Grouping Method"
+msgstr ""
+
+msgctxt "field:sale.configuration.sale_method,sale_invoice_grouping_method:"
+msgid "Sale Invoice Grouping Method"
+msgstr ""
+
+msgctxt "help:sale.configuration,sale_invoice_grouping_method:"
+msgid "The default invoice grouping method for new customers."
+msgstr ""
+
+msgctxt "help:sale.configuration.sale_method,sale_invoice_grouping_method:"
+msgid "The default invoice grouping method for new customers."
+msgstr ""
+
+msgctxt "model:party.party.sale_invoice_grouping_method,name:"
+msgid "Party Sale Invoice Grouping Method"
+msgstr ""
+
+msgctxt "selection:party.party,sale_invoice_grouping_method:"
+msgid "None"
+msgstr ""
+
+msgctxt "selection:party.party,sale_invoice_grouping_method:"
+msgid "Standard"
+msgstr ""
+
+msgctxt "view:party.party:"
+msgid "Invoicing"
+msgstr ""
diff --git a/modules/sale_invoice_grouping/locale/zh_CN.po b/modules/sale_invoice_grouping/locale/zh_CN.po
new file mode 100644
index 0000000000..54a581e066
--- /dev/null
+++ b/modules/sale_invoice_grouping/locale/zh_CN.po
@@ -0,0 +1,52 @@
+#
+msgid ""
+msgstr "Content-Type: text/plain; charset=utf-8\n"
+
+msgctxt "field:party.party,sale_invoice_grouping_method:"
+msgid "Sale Invoice Grouping Method"
+msgstr ""
+
+msgctxt "field:party.party,sale_invoice_grouping_methods:"
+msgid "Sale Invoice Grouping Methods"
+msgstr ""
+
+msgctxt "field:party.party.sale_invoice_grouping_method,party:"
+msgid "Party"
+msgstr ""
+
+msgctxt ""
+"field:party.party.sale_invoice_grouping_method,sale_invoice_grouping_method:"
+msgid "Sale Invoice Grouping Method"
+msgstr ""
+
+msgctxt "field:sale.configuration,sale_invoice_grouping_method:"
+msgid "Sale Invoice Grouping Method"
+msgstr ""
+
+msgctxt "field:sale.configuration.sale_method,sale_invoice_grouping_method:"
+msgid "Sale Invoice Grouping Method"
+msgstr ""
+
+msgctxt "help:sale.configuration,sale_invoice_grouping_method:"
+msgid "The default invoice grouping method for new customers."
+msgstr ""
+
+msgctxt "help:sale.configuration.sale_method,sale_invoice_grouping_method:"
+msgid "The default invoice grouping method for new customers."
+msgstr ""
+
+msgctxt "model:party.party.sale_invoice_grouping_method,name:"
+msgid "Party Sale Invoice Grouping Method"
+msgstr ""
+
+msgctxt "selection:party.party,sale_invoice_grouping_method:"
+msgid "None"
+msgstr ""
+
+msgctxt "selection:party.party,sale_invoice_grouping_method:"
+msgid "Standard"
+msgstr ""
+
+msgctxt "view:party.party:"
+msgid "Invoicing"
+msgstr ""
diff --git a/modules/sale_invoice_grouping/party.py b/modules/sale_invoice_grouping/party.py
new file mode 100644
index 0000000000..a09bc74cdf
--- /dev/null
+++ b/modules/sale_invoice_grouping/party.py
@@ -0,0 +1,59 @@
+# This file is part of Tryton. The COPYRIGHT file at the top level of this
+# repository contains the full copyright notices and license terms.
+from trytond import backend
+from trytond.model import ModelSQL, ValueMixin, fields
+from trytond.pool import PoolMeta, Pool
+from trytond.tools.multivalue import migrate_property
+
+
+class Party(metaclass=PoolMeta):
+ __name__ = 'party.party'
+
+ sale_invoice_grouping_method = fields.MultiValue(fields.Selection([
+ (None, 'None'),
+ ('standard', 'Standard'),
+ ],
+ 'Sale Invoice Grouping Method'))
+ sale_invoice_grouping_methods = fields.One2Many(
+ 'party.party.sale_invoice_grouping_method', 'party',
+ "Sale Invoice Grouping Methods")
+
+ @classmethod
+ def default_sale_invoice_grouping_method(cls, **pattern):
+ pool = Pool()
+ Configuration = pool.get('sale.configuration')
+ return Configuration(1).get_multivalue(
+ 'sale_invoice_grouping_method', **pattern)
+
+
+class PartySaleInvoiceGroupingMethod(ModelSQL, ValueMixin):
+ "Party Sale Invoice Grouping Method"
+ __name__ = 'party.party.sale_invoice_grouping_method'
+ party = fields.Many2One(
+ 'party.party', "Party", ondelete='CASCADE', select=True)
+ sale_invoice_grouping_method = fields.Selection(
+ 'get_sale_invoice_grouping_methods', "Sale Invoice Grouping Method")
+
+ @classmethod
+ def __register__(cls, module_name):
+ exist = backend.TableHandler.table_exist(cls._table)
+
+ super(PartySaleInvoiceGroupingMethod, cls).__register__(module_name)
+
+ if not exist:
+ cls._migrate_property([], [], [])
+
+ @classmethod
+ def _migrate_property(cls, field_names, value_names, fields):
+ field_names.append('sale_invoice_grouping_method')
+ value_names.append('sale_invoice_grouping_method')
+ migrate_property(
+ 'party.party', field_names, cls, value_names,
+ parent='party', fields=fields)
+
+ @classmethod
+ def get_sale_invoice_grouping_methods(cls):
+ pool = Pool()
+ Party = pool.get('party.party')
+ field_name = 'sale_invoice_grouping_method'
+ return Party.fields_get([field_name])[field_name]['selection']
diff --git a/modules/sale_invoice_grouping/party.xml b/modules/sale_invoice_grouping/party.xml
new file mode 100644
index 0000000000..e5c6732c93
--- /dev/null
+++ b/modules/sale_invoice_grouping/party.xml
@@ -0,0 +1,12 @@
+
+
+
+
+
+ party.party
+
+ party_form
+
+
+
diff --git a/modules/sale_invoice_grouping/sale.py b/modules/sale_invoice_grouping/sale.py
new file mode 100644
index 0000000000..a199d0e0f4
--- /dev/null
+++ b/modules/sale_invoice_grouping/sale.py
@@ -0,0 +1,53 @@
+# This file is part of Tryton. The COPYRIGHT file at the top level of
+# this repository contains the full copyright notices and license terms.
+
+from trytond.pool import PoolMeta
+from trytond.transaction import Transaction
+
+
+class Sale(metaclass=PoolMeta):
+ __name__ = 'sale.sale'
+
+ @property
+ def invoice_grouping_method(self):
+ party = self.invoice_party or self.party
+ return party.sale_invoice_grouping_method
+
+ @property
+ def _invoice_grouping_fields(self):
+ return ('state', 'company', 'type', 'journal', 'party',
+ 'invoice_address', 'currency', 'account', 'payment_term')
+
+ def _get_grouped_invoice_order(self):
+ "Returns the order clause used to find invoice that should be grouped"
+ return None
+
+ def _get_grouped_invoice_domain(self, invoice):
+ "Returns a domain that will find invoices that should be grouped"
+ Invoice = invoice.__class__
+ invoice_domain = [
+ ('lines.origin', 'like', 'sale.line,%'),
+ ]
+ defaults = Invoice.default_get(self._invoice_grouping_fields,
+ with_rec_name=False)
+ for field in self._invoice_grouping_fields:
+ invoice_domain.append(
+ (field, '=', getattr(invoice, field, defaults.get(field)))
+ )
+ return invoice_domain
+
+ def _get_invoice_sale(self):
+ transaction = Transaction()
+ context = transaction.context
+ invoice = super(Sale, self)._get_invoice_sale()
+ if (not context.get('skip_grouping', False)
+ and self.invoice_grouping_method):
+ with transaction.set_context(skip_grouping=True):
+ invoice = self._get_invoice_sale()
+ Invoice = invoice.__class__
+ domain = self._get_grouped_invoice_domain(invoice)
+ order = self._get_grouped_invoice_order()
+ grouped_invoices = Invoice.search(domain, order=order, limit=1)
+ if grouped_invoices:
+ invoice, = grouped_invoices
+ return invoice
diff --git a/modules/sale_invoice_grouping/setup.py b/modules/sale_invoice_grouping/setup.py
new file mode 100755
index 0000000000..9eac5b3a02
--- /dev/null
+++ b/modules/sale_invoice_grouping/setup.py
@@ -0,0 +1,150 @@
+#!/usr/bin/env python3
+# This file is part of Tryton. The COPYRIGHT file at the top level of
+# this repository contains the full copyright notices and license terms.
+
+import io
+import os
+import re
+from configparser import ConfigParser
+from setuptools import setup, find_packages
+
+
+def read(fname):
+ return io.open(
+ os.path.join(os.path.dirname(__file__), fname),
+ 'r', encoding='utf-8').read()
+
+
+def get_require_version(name):
+ if minor_version % 2:
+ require = '%s >= %s.%s.dev0, < %s.%s'
+ else:
+ require = '%s >= %s.%s, < %s.%s'
+ require %= (name, major_version, minor_version,
+ major_version, minor_version + 1)
+ return require
+
+
+config = ConfigParser()
+config.read_file(open(os.path.join(os.path.dirname(__file__), 'tryton.cfg')))
+info = dict(config.items('tryton'))
+for key in ('depends', 'extras_depend', 'xml'):
+ if key in info:
+ info[key] = info[key].strip().splitlines()
+version = info.get('version', '0.0.1')
+major_version, minor_version, _ = version.split('.', 2)
+major_version = int(major_version)
+minor_version = int(minor_version)
+name = 'trytond_sale_invoice_grouping'
+
+download_url = 'http://downloads.tryton.org/%s.%s/' % (
+ major_version, minor_version)
+if minor_version % 2:
+ version = '%s.%s.dev0' % (major_version, minor_version)
+ download_url = (
+ 'hg+http://hg.tryton.org/modules/%s#egg=%s-%s' % (
+ name[8:], name, version))
+local_version = []
+if os.environ.get('CI_JOB_ID'):
+ local_version.append(os.environ['CI_JOB_ID'])
+else:
+ for build in ['CI_BUILD_NUMBER', 'CI_JOB_NUMBER']:
+ if os.environ.get(build):
+ local_version.append(os.environ[build])
+ else:
+ local_version = []
+ break
+if local_version:
+ version += '+' + '.'.join(local_version)
+
+requires = []
+for dep in info.get('depends', []):
+ if not re.match(r'(ir|res)(\W|$)', dep):
+ requires.append(get_require_version('trytond_%s' % dep))
+requires.append(get_require_version('trytond'))
+
+tests_require = [get_require_version('proteus')]
+dependency_links = []
+if minor_version % 2:
+ dependency_links.append(
+ 'https://trydevpi.tryton.org/?local_version='
+ + '.'.join(local_version))
+
+setup(name=name,
+ version=version,
+ description='Tryton module to group sale invoices',
+ long_description=read('README.rst'),
+ author='Tryton',
+ author_email='bugs@tryton.org',
+ url='http://www.tryton.org/',
+ download_url=download_url,
+ project_urls={
+ "Bug Tracker": 'https://bugs.tryton.org/',
+ "Documentation": 'https://docs.tryton.org/',
+ "Forum": 'https://www.tryton.org/forum',
+ "Source Code": 'https://hg.tryton.org/modules/sale_invoice_grouping',
+ },
+ keywords='tryton sale group invoice',
+ package_dir={'trytond.modules.sale_invoice_grouping': '.'},
+ packages=(
+ ['trytond.modules.sale_invoice_grouping']
+ + ['trytond.modules.sale_invoice_grouping.%s' % p
+ for p in find_packages()]
+ ),
+ package_data={
+ 'trytond.modules.sale_invoice_grouping': (info.get('xml', [])
+ + ['tryton.cfg', 'view/*.xml', 'locale/*.po', 'tests/*.rst']),
+ },
+ classifiers=[
+ 'Development Status :: 5 - Production/Stable',
+ 'Environment :: Plugins',
+ 'Framework :: Tryton',
+ 'Intended Audience :: Developers',
+ 'Intended Audience :: Financial and Insurance Industry',
+ 'Intended Audience :: Legal Industry',
+ 'License :: OSI Approved :: '
+ 'GNU General Public License v3 or later (GPLv3+)',
+ 'Natural Language :: Bulgarian',
+ 'Natural Language :: Catalan',
+ 'Natural Language :: Chinese (Simplified)',
+ 'Natural Language :: Czech',
+ 'Natural Language :: Dutch',
+ 'Natural Language :: English',
+ 'Natural Language :: Finnish',
+ 'Natural Language :: French',
+ 'Natural Language :: German',
+ 'Natural Language :: Hungarian',
+ 'Natural Language :: Indonesian',
+ 'Natural Language :: Italian',
+ 'Natural Language :: Persian',
+ 'Natural Language :: Polish',
+ 'Natural Language :: Portuguese (Brazilian)',
+ 'Natural Language :: Romanian',
+ 'Natural Language :: Russian',
+ 'Natural Language :: Slovenian',
+ 'Natural Language :: Spanish',
+ 'Natural Language :: Turkish',
+ 'Operating System :: OS Independent',
+ 'Programming Language :: Python :: 3',
+ 'Programming Language :: Python :: 3.6',
+ 'Programming Language :: Python :: 3.7',
+ 'Programming Language :: Python :: 3.8',
+ 'Programming Language :: Python :: 3.9',
+ 'Programming Language :: Python :: Implementation :: CPython',
+ 'Programming Language :: Python :: Implementation :: PyPy',
+ 'Topic :: Office/Business',
+ 'Topic :: Office/Business :: Financial :: Accounting',
+ ],
+ license='GPL-3',
+ python_requires='>=3.6',
+ install_requires=requires,
+ dependency_links=dependency_links,
+ zip_safe=False,
+ entry_points="""
+ [trytond.modules]
+ sale_invoice_grouping = trytond.modules.sale_invoice_grouping
+ """,
+ test_suite='tests',
+ test_loader='trytond.test_loader:Loader',
+ tests_require=tests_require,
+ )
diff --git a/modules/sale_invoice_grouping/tests/__init__.py b/modules/sale_invoice_grouping/tests/__init__.py
new file mode 100644
index 0000000000..8bd6efb85c
--- /dev/null
+++ b/modules/sale_invoice_grouping/tests/__init__.py
@@ -0,0 +1,9 @@
+# This file is part of Tryton. The COPYRIGHT file at the top level of
+# this repository contains the full copyright notices and license terms.
+
+try:
+ from trytond.modules.sale_invoice_grouping.tests.test_sale_invoice_grouping import suite # noqa: E501
+except ImportError:
+ from .test_sale_invoice_grouping import suite
+
+__all__ = ['suite']
diff --git a/modules/sale_invoice_grouping/tests/scenario_sale_invoice_grouping.rst b/modules/sale_invoice_grouping/tests/scenario_sale_invoice_grouping.rst
new file mode 100644
index 0000000000..546c8219f4
--- /dev/null
+++ b/modules/sale_invoice_grouping/tests/scenario_sale_invoice_grouping.rst
@@ -0,0 +1,219 @@
+==============================
+Sale Invoice Grouping Scenario
+==============================
+
+Imports::
+
+ >>> import datetime
+ >>> from dateutil.relativedelta import relativedelta
+ >>> from decimal import Decimal
+ >>> from operator import attrgetter
+ >>> from proteus import Model, Wizard
+ >>> from trytond.tests.tools import activate_modules, set_user
+ >>> from trytond.modules.company.tests.tools import create_company, \
+ ... get_company
+ >>> from trytond.modules.account.tests.tools import create_fiscalyear, \
+ ... create_chart, get_accounts
+ >>> from trytond.modules.account_invoice.tests.tools import \
+ ... set_fiscalyear_invoice_sequences, create_payment_term
+ >>> today = datetime.date.today()
+
+Activate modules::
+
+ >>> config = activate_modules('sale_invoice_grouping')
+
+Create company::
+
+ >>> _ = create_company()
+ >>> company = get_company()
+
+Create sale user::
+
+ >>> User = Model.get('res.user')
+ >>> Group = Model.get('res.group')
+ >>> sale_user = User()
+ >>> sale_user.name = 'Sale'
+ >>> sale_user.login = 'sale'
+ >>> sale_group, = Group.find([('name', '=', 'Sales')])
+ >>> sale_user.groups.append(sale_group)
+ >>> sale_user.save()
+
+Create account user::
+
+ >>> account_user = User()
+ >>> account_user.name = 'Account'
+ >>> account_user.login = 'account'
+ >>> account_group, = Group.find([('name', '=', 'Account')])
+ >>> account_user.groups.append(account_group)
+ >>> account_user.save()
+
+Create fiscal year::
+
+ >>> fiscalyear = set_fiscalyear_invoice_sequences(
+ ... create_fiscalyear(company))
+ >>> fiscalyear.click('create_period')
+
+Create chart of accounts::
+
+ >>> _ = create_chart(company)
+ >>> accounts = get_accounts(company)
+ >>> revenue = accounts['revenue']
+ >>> expense = accounts['expense']
+
+Create parties::
+
+ >>> Party = Model.get('party.party')
+ >>> customer = Party(name='Customer')
+ >>> customer.save()
+ >>> customer_grouped = Party(name='Customer Grouped',
+ ... sale_invoice_grouping_method='standard')
+ >>> customer_grouped.save()
+
+Create account category::
+
+ >>> ProductCategory = Model.get('product.category')
+ >>> account_category = ProductCategory(name="Account Category")
+ >>> account_category.accounting = True
+ >>> account_category.account_expense = expense
+ >>> account_category.account_revenue = revenue
+ >>> account_category.save()
+
+Create product::
+
+ >>> ProductUom = Model.get('product.uom')
+ >>> unit, = ProductUom.find([('name', '=', 'Unit')])
+ >>> ProductTemplate = Model.get('product.template')
+
+ >>> template = ProductTemplate()
+ >>> template.name = 'product'
+ >>> template.default_uom = unit
+ >>> template.type = 'goods'
+ >>> template.salable = True
+ >>> template.list_price = Decimal('10')
+ >>> template.account_category = account_category
+ >>> template.save()
+ >>> product, = template.products
+
+Create payment term::
+
+ >>> payment_term = create_payment_term()
+ >>> payment_term.save()
+
+Sale some products::
+
+ >>> set_user(sale_user)
+ >>> Sale = Model.get('sale.sale')
+ >>> sale = Sale()
+ >>> sale.party = customer
+ >>> sale.payment_term = payment_term
+ >>> sale.invoice_method = 'order'
+ >>> sale_line = sale.lines.new()
+ >>> sale_line.product = product
+ >>> sale_line.quantity = 2.0
+ >>> sale.click('quote')
+ >>> sale.click('confirm')
+ >>> sale.state
+ 'processing'
+
+Make another sale::
+
+ >>> sale, = Sale.duplicate([sale])
+ >>> sale.click('quote')
+ >>> sale.click('confirm')
+ >>> sale.state
+ 'processing'
+
+Check the invoices::
+
+ >>> set_user(account_user)
+ >>> Invoice = Model.get('account.invoice')
+ >>> invoices = Invoice.find([('party', '=', customer.id)])
+ >>> len(invoices)
+ 2
+ >>> invoice = invoices[0]
+ >>> invoice.type
+ 'out'
+ >>> invoice.click('post')
+ >>> invoice.state
+ 'posted'
+
+Now we'll use the same scenario with the grouped customer::
+
+ >>> set_user(sale_user)
+ >>> sale = Sale()
+ >>> sale.party = customer_grouped
+ >>> sale.payment_term = payment_term
+ >>> sale.invoice_method = 'order'
+ >>> sale_line = sale.lines.new()
+ >>> sale_line.product = product
+ >>> sale_line.quantity = 1.0
+ >>> sale.click('quote')
+ >>> sale.click('confirm')
+ >>> sale.state
+ 'processing'
+
+Make another sale::
+
+ >>> sale = Sale()
+ >>> sale.party = customer_grouped
+ >>> sale.payment_term = payment_term
+ >>> sale.invoice_method = 'order'
+ >>> sale_line = sale.lines.new()
+ >>> sale_line.product = product
+ >>> sale_line.quantity = 2.0
+ >>> sale.click('quote')
+ >>> sale.click('confirm')
+ >>> sale.state
+ 'processing'
+
+Check the invoices::
+
+ >>> set_user(account_user)
+ >>> invoices = Invoice.find([
+ ... ('party', '=', customer_grouped.id),
+ ... ('state', '=', 'draft'),
+ ... ])
+ >>> len(invoices)
+ 1
+ >>> invoice, = invoices
+ >>> len(invoice.lines)
+ 2
+ >>> invoice.lines[0].quantity
+ 1.0
+ >>> invoice.lines[1].quantity
+ 2.0
+ >>> invoice.click('post')
+ >>> invoice.state
+ 'posted'
+
+Create a manual invoice::
+
+ >>> manual_invoice = Invoice()
+ >>> manual_invoice.party = customer_grouped
+ >>> manual_invoice.payment_term = payment_term
+ >>> manual_invoice.save()
+
+Check that a new sale won't be grouped with the manual invoice::
+
+ >>> set_user(sale_user)
+ >>> sale = Sale()
+ >>> sale.party = customer_grouped
+ >>> sale.payment_term = payment_term
+ >>> sale.invoice_method = 'order'
+ >>> sale_line = sale.lines.new()
+ >>> sale_line.product = product
+ >>> sale_line.quantity = 3.0
+ >>> sale.click('quote')
+ >>> sale.click('confirm')
+ >>> sale.state
+ 'processing'
+
+Check the invoices::
+
+ >>> set_user(account_user)
+ >>> invoices = Invoice.find([
+ ... ('party', '=', customer_grouped.id),
+ ... ('state', '=', 'draft'),
+ ... ])
+ >>> len(invoices)
+ 2
diff --git a/modules/sale_invoice_grouping/tests/test_sale_invoice_grouping.py b/modules/sale_invoice_grouping/tests/test_sale_invoice_grouping.py
new file mode 100644
index 0000000000..4de41b64a0
--- /dev/null
+++ b/modules/sale_invoice_grouping/tests/test_sale_invoice_grouping.py
@@ -0,0 +1,24 @@
+# This file is part of Tryton. The COPYRIGHT file at the top level of
+# this repository contains the full copyright notices and license terms.
+import unittest
+import doctest
+import trytond.tests.test_tryton
+from trytond.tests.test_tryton import ModuleTestCase
+from trytond.tests.test_tryton import doctest_teardown
+from trytond.tests.test_tryton import doctest_checker
+
+
+class SaleInvoiceGroupingTestCase(ModuleTestCase):
+ 'Test Sale Invoice Grouping module'
+ module = 'sale_invoice_grouping'
+
+
+def suite():
+ suite = trytond.tests.test_tryton.suite()
+ suite.addTests(unittest.TestLoader().loadTestsFromTestCase(
+ SaleInvoiceGroupingTestCase))
+ suite.addTests(doctest.DocFileSuite('scenario_sale_invoice_grouping.rst',
+ tearDown=doctest_teardown, encoding='utf-8',
+ checker=doctest_checker,
+ optionflags=doctest.REPORT_ONLY_FIRST_FAILURE))
+ return suite
diff --git a/modules/sale_invoice_grouping/tox.ini b/modules/sale_invoice_grouping/tox.ini
new file mode 100644
index 0000000000..197496c0cb
--- /dev/null
+++ b/modules/sale_invoice_grouping/tox.ini
@@ -0,0 +1,15 @@
+[tox]
+envlist = {py36,py37,py38,py39}-{sqlite,postgresql},pypy3-{sqlite,postgresql}
+
+[testenv]
+commands = {envpython} setup.py test
+deps =
+ {py36,py37,py38,py39}-postgresql: psycopg2 >= 2.5
+ pypy3-postgresql: psycopg2cffi >= 2.5
+ py36-sqlite: sqlitebck
+setenv =
+ sqlite: TRYTOND_DATABASE_URI={env:SQLITE_URI:sqlite://}
+ postgresql: TRYTOND_DATABASE_URI={env:POSTGRESQL_URI:postgresql://}
+ sqlite: DB_NAME={env:SQLITE_NAME::memory:}
+ postgresql: DB_NAME={env:POSTGRESQL_NAME:test}
+install_command = pip install --pre --find-links https://trydevpi.tryton.org/?local_version={env:CI_JOB_ID:{env:CI_BUILD_NUMBER}.{env:CI_JOB_NUMBER}} {opts} {packages}
diff --git a/modules/sale_invoice_grouping/tryton.cfg b/modules/sale_invoice_grouping/tryton.cfg
new file mode 100644
index 0000000000..c5c694c866
--- /dev/null
+++ b/modules/sale_invoice_grouping/tryton.cfg
@@ -0,0 +1,11 @@
+[tryton]
+version=6.0.1
+depends:
+ ir
+ res
+ party
+ account_invoice
+ sale
+xml:
+ party.xml
+ configuration.xml
diff --git a/modules/sale_invoice_grouping/view/configuration_form.xml b/modules/sale_invoice_grouping/view/configuration_form.xml
new file mode 100644
index 0000000000..f15f4ddc66
--- /dev/null
+++ b/modules/sale_invoice_grouping/view/configuration_form.xml
@@ -0,0 +1,9 @@
+
+
+
+
+
+
+
+
diff --git a/modules/sale_invoice_grouping/view/party_form.xml b/modules/sale_invoice_grouping/view/party_form.xml
new file mode 100644
index 0000000000..df9962f0bf
--- /dev/null
+++ b/modules/sale_invoice_grouping/view/party_form.xml
@@ -0,0 +1,10 @@
+
+
+
+
+
+
+
+
+
diff --git a/modules/sale_opportunity/.drone.yml b/modules/sale_opportunity/.drone.yml
new file mode 100644
index 0000000000..2049d30a49
--- /dev/null
+++ b/modules/sale_opportunity/.drone.yml
@@ -0,0 +1,68 @@
+clone:
+ hg:
+ image: plugins/hg
+ environment:
+ - HG_SHARE_POOL=/root/.cache/hg
+ volumes:
+ - cache:/root/.cache
+
+pipeline:
+ tox:
+ image: ${IMAGE}
+ environment:
+ - CFLAGS=-O0
+ - DB_CACHE=/cache
+ - TOX_TESTENV_PASSENV=CFLAGS DB_CACHE CI_BUILD_NUMBER CI_JOB_NUMBER CI_JOB_ID
+ - POSTGRESQL_URI=postgresql://postgres@postgresql:5432/
+ commands:
+ - echo "[extensions]" >> /root/.hgrc
+ - echo "hgext.share =" >> /root/.hgrc
+ - echo "[share]" >> /root/.hgrc
+ - echo "pool = /root/.cache/hg" >> /root/.hgrc
+ - pip install tox
+ - tox -e "${TOXENV}-${DATABASE}"
+ volumes:
+ - cache:/root/.cache
+ check_dist:
+ image: ${IMAGE}
+ commands:
+ - pip install twine
+ - python setup.py sdist
+ - twine check dist/*
+
+services:
+ postgresql:
+ image: postgres
+ environment:
+ - POSTGRES_HOST_AUTH_METHOD=trust
+ command: "-c fsync=off -c synchronous_commit=off -c full_page_writes=off"
+ when:
+ matrix:
+ DATABASE: postgresql
+
+matrix:
+ include:
+ - IMAGE: python:3.6
+ TOXENV: py36
+ DATABASE: sqlite
+ - IMAGE: python:3.6
+ TOXENV: py36
+ DATABASE: postgresql
+ - IMAGE: python:3.7
+ TOXENV: py37
+ DATABASE: sqlite
+ - IMAGE: python:3.7
+ TOXENV: py37
+ DATABASE: postgresql
+ - IMAGE: python:3.8
+ TOXENV: py38
+ DATABASE: sqlite
+ - IMAGE: python:3.8
+ TOXENV: py38
+ DATABASE: postgresql
+ - IMAGE: python:3.9
+ TOXENV: py39
+ DATABASE: sqlite
+ - IMAGE: python:3.9
+ TOXENV: py39
+ DATABASE: postgresql
diff --git a/modules/sale_opportunity/.flake8 b/modules/sale_opportunity/.flake8
new file mode 100644
index 0000000000..fa6b4f66d1
--- /dev/null
+++ b/modules/sale_opportunity/.flake8
@@ -0,0 +1,2 @@
+[flake8]
+ignore=E123,E124,E126,E128,E741,W503
diff --git a/modules/sale_opportunity/CHANGELOG b/modules/sale_opportunity/CHANGELOG
new file mode 100644
index 0000000000..a4dda0edcd
--- /dev/null
+++ b/modules/sale_opportunity/CHANGELOG
@@ -0,0 +1,92 @@
+Version 6.0.1 - 2021-07-01
+* Bug fixes (see mercurial logs for details)
+
+Version 6.0.0 - 2021-05-03
+* Bug fixes (see mercurial logs for details)
+
+Version 5.8.0 - 2020-11-02
+* Bug fixes (see mercurial logs for details)
+* Remove support for Python 3.5
+
+Version 5.6.0 - 2020-05-04
+* Bug fixes (see mercurial logs for details)
+* Add employee on opportunities for some states
+* Add contact on opportunity
+
+Version 5.4.0 - 2019-11-04
+* Bug fixes (see mercurial logs for details)
+* Use ir.calendar.month in report
+
+Version 5.2.0 - 2019-05-06
+* Bug fixes (see mercurial logs for details)
+* Make description on sale opportunity optional
+
+Version 5.0.0 - 2018-10-01
+* Bug fixes (see mercurial logs for details)
+* Remove support for Python 2.7
+
+Version 4.8.0 - 2018-04-23
+* Bug fixes (see mercurial logs for details)
+
+Version 4.6.0 - 2017-10-30
+* Bug fixes (see mercurial logs for details)
+
+Version 4.4.0 - 2017-05-01
+* Bug fixes (see mercurial logs for details)
+* Compute rates as ratio
+* Make Opportunity employee not required on leads
+
+Version 4.2.0 - 2016-11-28
+* Bug fixes (see mercurial logs for details)
+* Change probability into conversion probability
+* Manage readonly state on Opportunity Line
+
+Version 4.0.0 - 2016-05-02
+* Bug fixes (see mercurial logs for details)
+* Rename Opportunity reference into number and add reference
+* Add Python3 support
+* Replace history by revision on client
+
+Version 3.8.0 - 2015-11-02
+* Bug fixes (see mercurial logs for details)
+* Fix origin migration from 3.4
+
+Version 3.6.0 - 2015-04-20
+* Bug fixes (see mercurial logs for details)
+* Add support for PyPy
+* Allow to set manually end date
+* Update of opportunity amount based on linked sales
+* Add a state 'won'
+* Allow to edit the probability after conversion
+
+Version 3.4.0 - 2014-10-20
+* Bug fixes (see mercurial logs for details)
+
+Version 3.2.0 - 2014-04-21
+* Bug fixes (see mercurial logs for details)
+
+Version 3.0.0 - 2013-10-21
+* Bug fixes (see mercurial logs for details)
+* Make party optional in leads
+
+Version 2.8.0 - 2013-04-22
+* Bug fixes (see mercurial logs for details)
+
+Version 2.6.0 - 2012-10-22
+* Bug fixes (see mercurial logs for details)
+
+Version 2.4.0 - 2012-04-24
+* Bug fixes (see mercurial logs for details)
+* Remove warehouse
+
+Version 2.2.0 - 2011-10-25
+* Bug fixes (see mercurial logs for details)
+
+Version 2.0.0 - 2011-04-27
+* Bug fixes (see mercurial logs for details)
+
+Version 1.8.0 - 2010-11-01
+* Bug fixes (see mercurial logs for details)
+
+Version 1.6.0 - 2010-09-07
+* Initial release
diff --git a/modules/sale_opportunity/COPYRIGHT b/modules/sale_opportunity/COPYRIGHT
new file mode 100644
index 0000000000..9154de4048
--- /dev/null
+++ b/modules/sale_opportunity/COPYRIGHT
@@ -0,0 +1,16 @@
+Copyright (C) 2010-2011 Open Labs Business Solutions.
+Copyright (C) 2010-2021 Cédric Krier.
+Copyright (C) 2010-2021 B2CK SPRL.
+
+This program is free software: you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation, either version 3 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program. If not, see .
diff --git a/modules/sale_opportunity/LICENSE b/modules/sale_opportunity/LICENSE
new file mode 100644
index 0000000000..94a9ed024d
--- /dev/null
+++ b/modules/sale_opportunity/LICENSE
@@ -0,0 +1,674 @@
+ GNU GENERAL PUBLIC LICENSE
+ Version 3, 29 June 2007
+
+ Copyright (C) 2007 Free Software Foundation, Inc.
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+ Preamble
+
+ The GNU General Public License is a free, copyleft license for
+software and other kinds of works.
+
+ The licenses for most software and other practical works are designed
+to take away your freedom to share and change the works. By contrast,
+the GNU General Public License is intended to guarantee your freedom to
+share and change all versions of a program--to make sure it remains free
+software for all its users. We, the Free Software Foundation, use the
+GNU General Public License for most of our software; it applies also to
+any other work released this way by its authors. You can apply it to
+your programs, too.
+
+ When we speak of free software, we are referring to freedom, not
+price. Our General Public Licenses are designed to make sure that you
+have the freedom to distribute copies of free software (and charge for
+them if you wish), that you receive source code or can get it if you
+want it, that you can change the software or use pieces of it in new
+free programs, and that you know you can do these things.
+
+ To protect your rights, we need to prevent others from denying you
+these rights or asking you to surrender the rights. Therefore, you have
+certain responsibilities if you distribute copies of the software, or if
+you modify it: responsibilities to respect the freedom of others.
+
+ For example, if you distribute copies of such a program, whether
+gratis or for a fee, you must pass on to the recipients the same
+freedoms that you received. You must make sure that they, too, receive
+or can get the source code. And you must show them these terms so they
+know their rights.
+
+ Developers that use the GNU GPL protect your rights with two steps:
+(1) assert copyright on the software, and (2) offer you this License
+giving you legal permission to copy, distribute and/or modify it.
+
+ For the developers' and authors' protection, the GPL clearly explains
+that there is no warranty for this free software. For both users' and
+authors' sake, the GPL requires that modified versions be marked as
+changed, so that their problems will not be attributed erroneously to
+authors of previous versions.
+
+ Some devices are designed to deny users access to install or run
+modified versions of the software inside them, although the manufacturer
+can do so. This is fundamentally incompatible with the aim of
+protecting users' freedom to change the software. The systematic
+pattern of such abuse occurs in the area of products for individuals to
+use, which is precisely where it is most unacceptable. Therefore, we
+have designed this version of the GPL to prohibit the practice for those
+products. If such problems arise substantially in other domains, we
+stand ready to extend this provision to those domains in future versions
+of the GPL, as needed to protect the freedom of users.
+
+ Finally, every program is threatened constantly by software patents.
+States should not allow patents to restrict development and use of
+software on general-purpose computers, but in those that do, we wish to
+avoid the special danger that patents applied to a free program could
+make it effectively proprietary. To prevent this, the GPL assures that
+patents cannot be used to render the program non-free.
+
+ The precise terms and conditions for copying, distribution and
+modification follow.
+
+ TERMS AND CONDITIONS
+
+ 0. Definitions.
+
+ "This License" refers to version 3 of the GNU General Public License.
+
+ "Copyright" also means copyright-like laws that apply to other kinds of
+works, such as semiconductor masks.
+
+ "The Program" refers to any copyrightable work licensed under this
+License. Each licensee is addressed as "you". "Licensees" and
+"recipients" may be individuals or organizations.
+
+ To "modify" a work means to copy from or adapt all or part of the work
+in a fashion requiring copyright permission, other than the making of an
+exact copy. The resulting work is called a "modified version" of the
+earlier work or a work "based on" the earlier work.
+
+ A "covered work" means either the unmodified Program or a work based
+on the Program.
+
+ To "propagate" a work means to do anything with it that, without
+permission, would make you directly or secondarily liable for
+infringement under applicable copyright law, except executing it on a
+computer or modifying a private copy. Propagation includes copying,
+distribution (with or without modification), making available to the
+public, and in some countries other activities as well.
+
+ To "convey" a work means any kind of propagation that enables other
+parties to make or receive copies. Mere interaction with a user through
+a computer network, with no transfer of a copy, is not conveying.
+
+ An interactive user interface displays "Appropriate Legal Notices"
+to the extent that it includes a convenient and prominently visible
+feature that (1) displays an appropriate copyright notice, and (2)
+tells the user that there is no warranty for the work (except to the
+extent that warranties are provided), that licensees may convey the
+work under this License, and how to view a copy of this License. If
+the interface presents a list of user commands or options, such as a
+menu, a prominent item in the list meets this criterion.
+
+ 1. Source Code.
+
+ The "source code" for a work means the preferred form of the work
+for making modifications to it. "Object code" means any non-source
+form of a work.
+
+ A "Standard Interface" means an interface that either is an official
+standard defined by a recognized standards body, or, in the case of
+interfaces specified for a particular programming language, one that
+is widely used among developers working in that language.
+
+ The "System Libraries" of an executable work include anything, other
+than the work as a whole, that (a) is included in the normal form of
+packaging a Major Component, but which is not part of that Major
+Component, and (b) serves only to enable use of the work with that
+Major Component, or to implement a Standard Interface for which an
+implementation is available to the public in source code form. A
+"Major Component", in this context, means a major essential component
+(kernel, window system, and so on) of the specific operating system
+(if any) on which the executable work runs, or a compiler used to
+produce the work, or an object code interpreter used to run it.
+
+ The "Corresponding Source" for a work in object code form means all
+the source code needed to generate, install, and (for an executable
+work) run the object code and to modify the work, including scripts to
+control those activities. However, it does not include the work's
+System Libraries, or general-purpose tools or generally available free
+programs which are used unmodified in performing those activities but
+which are not part of the work. For example, Corresponding Source
+includes interface definition files associated with source files for
+the work, and the source code for shared libraries and dynamically
+linked subprograms that the work is specifically designed to require,
+such as by intimate data communication or control flow between those
+subprograms and other parts of the work.
+
+ The Corresponding Source need not include anything that users
+can regenerate automatically from other parts of the Corresponding
+Source.
+
+ The Corresponding Source for a work in source code form is that
+same work.
+
+ 2. Basic Permissions.
+
+ All rights granted under this License are granted for the term of
+copyright on the Program, and are irrevocable provided the stated
+conditions are met. This License explicitly affirms your unlimited
+permission to run the unmodified Program. The output from running a
+covered work is covered by this License only if the output, given its
+content, constitutes a covered work. This License acknowledges your
+rights of fair use or other equivalent, as provided by copyright law.
+
+ You may make, run and propagate covered works that you do not
+convey, without conditions so long as your license otherwise remains
+in force. You may convey covered works to others for the sole purpose
+of having them make modifications exclusively for you, or provide you
+with facilities for running those works, provided that you comply with
+the terms of this License in conveying all material for which you do
+not control copyright. Those thus making or running the covered works
+for you must do so exclusively on your behalf, under your direction
+and control, on terms that prohibit them from making any copies of
+your copyrighted material outside their relationship with you.
+
+ Conveying under any other circumstances is permitted solely under
+the conditions stated below. Sublicensing is not allowed; section 10
+makes it unnecessary.
+
+ 3. Protecting Users' Legal Rights From Anti-Circumvention Law.
+
+ No covered work shall be deemed part of an effective technological
+measure under any applicable law fulfilling obligations under article
+11 of the WIPO copyright treaty adopted on 20 December 1996, or
+similar laws prohibiting or restricting circumvention of such
+measures.
+
+ When you convey a covered work, you waive any legal power to forbid
+circumvention of technological measures to the extent such circumvention
+is effected by exercising rights under this License with respect to
+the covered work, and you disclaim any intention to limit operation or
+modification of the work as a means of enforcing, against the work's
+users, your or third parties' legal rights to forbid circumvention of
+technological measures.
+
+ 4. Conveying Verbatim Copies.
+
+ You may convey verbatim copies of the Program's source code as you
+receive it, in any medium, provided that you conspicuously and
+appropriately publish on each copy an appropriate copyright notice;
+keep intact all notices stating that this License and any
+non-permissive terms added in accord with section 7 apply to the code;
+keep intact all notices of the absence of any warranty; and give all
+recipients a copy of this License along with the Program.
+
+ You may charge any price or no price for each copy that you convey,
+and you may offer support or warranty protection for a fee.
+
+ 5. Conveying Modified Source Versions.
+
+ You may convey a work based on the Program, or the modifications to
+produce it from the Program, in the form of source code under the
+terms of section 4, provided that you also meet all of these conditions:
+
+ a) The work must carry prominent notices stating that you modified
+ it, and giving a relevant date.
+
+ b) The work must carry prominent notices stating that it is
+ released under this License and any conditions added under section
+ 7. This requirement modifies the requirement in section 4 to
+ "keep intact all notices".
+
+ c) You must license the entire work, as a whole, under this
+ License to anyone who comes into possession of a copy. This
+ License will therefore apply, along with any applicable section 7
+ additional terms, to the whole of the work, and all its parts,
+ regardless of how they are packaged. This License gives no
+ permission to license the work in any other way, but it does not
+ invalidate such permission if you have separately received it.
+
+ d) If the work has interactive user interfaces, each must display
+ Appropriate Legal Notices; however, if the Program has interactive
+ interfaces that do not display Appropriate Legal Notices, your
+ work need not make them do so.
+
+ A compilation of a covered work with other separate and independent
+works, which are not by their nature extensions of the covered work,
+and which are not combined with it such as to form a larger program,
+in or on a volume of a storage or distribution medium, is called an
+"aggregate" if the compilation and its resulting copyright are not
+used to limit the access or legal rights of the compilation's users
+beyond what the individual works permit. Inclusion of a covered work
+in an aggregate does not cause this License to apply to the other
+parts of the aggregate.
+
+ 6. Conveying Non-Source Forms.
+
+ You may convey a covered work in object code form under the terms
+of sections 4 and 5, provided that you also convey the
+machine-readable Corresponding Source under the terms of this License,
+in one of these ways:
+
+ a) Convey the object code in, or embodied in, a physical product
+ (including a physical distribution medium), accompanied by the
+ Corresponding Source fixed on a durable physical medium
+ customarily used for software interchange.
+
+ b) Convey the object code in, or embodied in, a physical product
+ (including a physical distribution medium), accompanied by a
+ written offer, valid for at least three years and valid for as
+ long as you offer spare parts or customer support for that product
+ model, to give anyone who possesses the object code either (1) a
+ copy of the Corresponding Source for all the software in the
+ product that is covered by this License, on a durable physical
+ medium customarily used for software interchange, for a price no
+ more than your reasonable cost of physically performing this
+ conveying of source, or (2) access to copy the
+ Corresponding Source from a network server at no charge.
+
+ c) Convey individual copies of the object code with a copy of the
+ written offer to provide the Corresponding Source. This
+ alternative is allowed only occasionally and noncommercially, and
+ only if you received the object code with such an offer, in accord
+ with subsection 6b.
+
+ d) Convey the object code by offering access from a designated
+ place (gratis or for a charge), and offer equivalent access to the
+ Corresponding Source in the same way through the same place at no
+ further charge. You need not require recipients to copy the
+ Corresponding Source along with the object code. If the place to
+ copy the object code is a network server, the Corresponding Source
+ may be on a different server (operated by you or a third party)
+ that supports equivalent copying facilities, provided you maintain
+ clear directions next to the object code saying where to find the
+ Corresponding Source. Regardless of what server hosts the
+ Corresponding Source, you remain obligated to ensure that it is
+ available for as long as needed to satisfy these requirements.
+
+ e) Convey the object code using peer-to-peer transmission, provided
+ you inform other peers where the object code and Corresponding
+ Source of the work are being offered to the general public at no
+ charge under subsection 6d.
+
+ A separable portion of the object code, whose source code is excluded
+from the Corresponding Source as a System Library, need not be
+included in conveying the object code work.
+
+ A "User Product" is either (1) a "consumer product", which means any
+tangible personal property which is normally used for personal, family,
+or household purposes, or (2) anything designed or sold for incorporation
+into a dwelling. In determining whether a product is a consumer product,
+doubtful cases shall be resolved in favor of coverage. For a particular
+product received by a particular user, "normally used" refers to a
+typical or common use of that class of product, regardless of the status
+of the particular user or of the way in which the particular user
+actually uses, or expects or is expected to use, the product. A product
+is a consumer product regardless of whether the product has substantial
+commercial, industrial or non-consumer uses, unless such uses represent
+the only significant mode of use of the product.
+
+ "Installation Information" for a User Product means any methods,
+procedures, authorization keys, or other information required to install
+and execute modified versions of a covered work in that User Product from
+a modified version of its Corresponding Source. The information must
+suffice to ensure that the continued functioning of the modified object
+code is in no case prevented or interfered with solely because
+modification has been made.
+
+ If you convey an object code work under this section in, or with, or
+specifically for use in, a User Product, and the conveying occurs as
+part of a transaction in which the right of possession and use of the
+User Product is transferred to the recipient in perpetuity or for a
+fixed term (regardless of how the transaction is characterized), the
+Corresponding Source conveyed under this section must be accompanied
+by the Installation Information. But this requirement does not apply
+if neither you nor any third party retains the ability to install
+modified object code on the User Product (for example, the work has
+been installed in ROM).
+
+ The requirement to provide Installation Information does not include a
+requirement to continue to provide support service, warranty, or updates
+for a work that has been modified or installed by the recipient, or for
+the User Product in which it has been modified or installed. Access to a
+network may be denied when the modification itself materially and
+adversely affects the operation of the network or violates the rules and
+protocols for communication across the network.
+
+ Corresponding Source conveyed, and Installation Information provided,
+in accord with this section must be in a format that is publicly
+documented (and with an implementation available to the public in
+source code form), and must require no special password or key for
+unpacking, reading or copying.
+
+ 7. Additional Terms.
+
+ "Additional permissions" are terms that supplement the terms of this
+License by making exceptions from one or more of its conditions.
+Additional permissions that are applicable to the entire Program shall
+be treated as though they were included in this License, to the extent
+that they are valid under applicable law. If additional permissions
+apply only to part of the Program, that part may be used separately
+under those permissions, but the entire Program remains governed by
+this License without regard to the additional permissions.
+
+ When you convey a copy of a covered work, you may at your option
+remove any additional permissions from that copy, or from any part of
+it. (Additional permissions may be written to require their own
+removal in certain cases when you modify the work.) You may place
+additional permissions on material, added by you to a covered work,
+for which you have or can give appropriate copyright permission.
+
+ Notwithstanding any other provision of this License, for material you
+add to a covered work, you may (if authorized by the copyright holders of
+that material) supplement the terms of this License with terms:
+
+ a) Disclaiming warranty or limiting liability differently from the
+ terms of sections 15 and 16 of this License; or
+
+ b) Requiring preservation of specified reasonable legal notices or
+ author attributions in that material or in the Appropriate Legal
+ Notices displayed by works containing it; or
+
+ c) Prohibiting misrepresentation of the origin of that material, or
+ requiring that modified versions of such material be marked in
+ reasonable ways as different from the original version; or
+
+ d) Limiting the use for publicity purposes of names of licensors or
+ authors of the material; or
+
+ e) Declining to grant rights under trademark law for use of some
+ trade names, trademarks, or service marks; or
+
+ f) Requiring indemnification of licensors and authors of that
+ material by anyone who conveys the material (or modified versions of
+ it) with contractual assumptions of liability to the recipient, for
+ any liability that these contractual assumptions directly impose on
+ those licensors and authors.
+
+ All other non-permissive additional terms are considered "further
+restrictions" within the meaning of section 10. If the Program as you
+received it, or any part of it, contains a notice stating that it is
+governed by this License along with a term that is a further
+restriction, you may remove that term. If a license document contains
+a further restriction but permits relicensing or conveying under this
+License, you may add to a covered work material governed by the terms
+of that license document, provided that the further restriction does
+not survive such relicensing or conveying.
+
+ If you add terms to a covered work in accord with this section, you
+must place, in the relevant source files, a statement of the
+additional terms that apply to those files, or a notice indicating
+where to find the applicable terms.
+
+ Additional terms, permissive or non-permissive, may be stated in the
+form of a separately written license, or stated as exceptions;
+the above requirements apply either way.
+
+ 8. Termination.
+
+ You may not propagate or modify a covered work except as expressly
+provided under this License. Any attempt otherwise to propagate or
+modify it is void, and will automatically terminate your rights under
+this License (including any patent licenses granted under the third
+paragraph of section 11).
+
+ However, if you cease all violation of this License, then your
+license from a particular copyright holder is reinstated (a)
+provisionally, unless and until the copyright holder explicitly and
+finally terminates your license, and (b) permanently, if the copyright
+holder fails to notify you of the violation by some reasonable means
+prior to 60 days after the cessation.
+
+ Moreover, your license from a particular copyright holder is
+reinstated permanently if the copyright holder notifies you of the
+violation by some reasonable means, this is the first time you have
+received notice of violation of this License (for any work) from that
+copyright holder, and you cure the violation prior to 30 days after
+your receipt of the notice.
+
+ Termination of your rights under this section does not terminate the
+licenses of parties who have received copies or rights from you under
+this License. If your rights have been terminated and not permanently
+reinstated, you do not qualify to receive new licenses for the same
+material under section 10.
+
+ 9. Acceptance Not Required for Having Copies.
+
+ You are not required to accept this License in order to receive or
+run a copy of the Program. Ancillary propagation of a covered work
+occurring solely as a consequence of using peer-to-peer transmission
+to receive a copy likewise does not require acceptance. However,
+nothing other than this License grants you permission to propagate or
+modify any covered work. These actions infringe copyright if you do
+not accept this License. Therefore, by modifying or propagating a
+covered work, you indicate your acceptance of this License to do so.
+
+ 10. Automatic Licensing of Downstream Recipients.
+
+ Each time you convey a covered work, the recipient automatically
+receives a license from the original licensors, to run, modify and
+propagate that work, subject to this License. You are not responsible
+for enforcing compliance by third parties with this License.
+
+ An "entity transaction" is a transaction transferring control of an
+organization, or substantially all assets of one, or subdividing an
+organization, or merging organizations. If propagation of a covered
+work results from an entity transaction, each party to that
+transaction who receives a copy of the work also receives whatever
+licenses to the work the party's predecessor in interest had or could
+give under the previous paragraph, plus a right to possession of the
+Corresponding Source of the work from the predecessor in interest, if
+the predecessor has it or can get it with reasonable efforts.
+
+ You may not impose any further restrictions on the exercise of the
+rights granted or affirmed under this License. For example, you may
+not impose a license fee, royalty, or other charge for exercise of
+rights granted under this License, and you may not initiate litigation
+(including a cross-claim or counterclaim in a lawsuit) alleging that
+any patent claim is infringed by making, using, selling, offering for
+sale, or importing the Program or any portion of it.
+
+ 11. Patents.
+
+ A "contributor" is a copyright holder who authorizes use under this
+License of the Program or a work on which the Program is based. The
+work thus licensed is called the contributor's "contributor version".
+
+ A contributor's "essential patent claims" are all patent claims
+owned or controlled by the contributor, whether already acquired or
+hereafter acquired, that would be infringed by some manner, permitted
+by this License, of making, using, or selling its contributor version,
+but do not include claims that would be infringed only as a
+consequence of further modification of the contributor version. For
+purposes of this definition, "control" includes the right to grant
+patent sublicenses in a manner consistent with the requirements of
+this License.
+
+ Each contributor grants you a non-exclusive, worldwide, royalty-free
+patent license under the contributor's essential patent claims, to
+make, use, sell, offer for sale, import and otherwise run, modify and
+propagate the contents of its contributor version.
+
+ In the following three paragraphs, a "patent license" is any express
+agreement or commitment, however denominated, not to enforce a patent
+(such as an express permission to practice a patent or covenant not to
+sue for patent infringement). To "grant" such a patent license to a
+party means to make such an agreement or commitment not to enforce a
+patent against the party.
+
+ If you convey a covered work, knowingly relying on a patent license,
+and the Corresponding Source of the work is not available for anyone
+to copy, free of charge and under the terms of this License, through a
+publicly available network server or other readily accessible means,
+then you must either (1) cause the Corresponding Source to be so
+available, or (2) arrange to deprive yourself of the benefit of the
+patent license for this particular work, or (3) arrange, in a manner
+consistent with the requirements of this License, to extend the patent
+license to downstream recipients. "Knowingly relying" means you have
+actual knowledge that, but for the patent license, your conveying the
+covered work in a country, or your recipient's use of the covered work
+in a country, would infringe one or more identifiable patents in that
+country that you have reason to believe are valid.
+
+ If, pursuant to or in connection with a single transaction or
+arrangement, you convey, or propagate by procuring conveyance of, a
+covered work, and grant a patent license to some of the parties
+receiving the covered work authorizing them to use, propagate, modify
+or convey a specific copy of the covered work, then the patent license
+you grant is automatically extended to all recipients of the covered
+work and works based on it.
+
+ A patent license is "discriminatory" if it does not include within
+the scope of its coverage, prohibits the exercise of, or is
+conditioned on the non-exercise of one or more of the rights that are
+specifically granted under this License. You may not convey a covered
+work if you are a party to an arrangement with a third party that is
+in the business of distributing software, under which you make payment
+to the third party based on the extent of your activity of conveying
+the work, and under which the third party grants, to any of the
+parties who would receive the covered work from you, a discriminatory
+patent license (a) in connection with copies of the covered work
+conveyed by you (or copies made from those copies), or (b) primarily
+for and in connection with specific products or compilations that
+contain the covered work, unless you entered into that arrangement,
+or that patent license was granted, prior to 28 March 2007.
+
+ Nothing in this License shall be construed as excluding or limiting
+any implied license or other defenses to infringement that may
+otherwise be available to you under applicable patent law.
+
+ 12. No Surrender of Others' Freedom.
+
+ If conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License. If you cannot convey a
+covered work so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you may
+not convey it at all. For example, if you agree to terms that obligate you
+to collect a royalty for further conveying from those to whom you convey
+the Program, the only way you could satisfy both those terms and this
+License would be to refrain entirely from conveying the Program.
+
+ 13. Use with the GNU Affero General Public License.
+
+ Notwithstanding any other provision of this License, you have
+permission to link or combine any covered work with a work licensed
+under version 3 of the GNU Affero General Public License into a single
+combined work, and to convey the resulting work. The terms of this
+License will continue to apply to the part which is the covered work,
+but the special requirements of the GNU Affero General Public License,
+section 13, concerning interaction through a network will apply to the
+combination as such.
+
+ 14. Revised Versions of this License.
+
+ The Free Software Foundation may publish revised and/or new versions of
+the GNU General Public License from time to time. Such new versions will
+be similar in spirit to the present version, but may differ in detail to
+address new problems or concerns.
+
+ Each version is given a distinguishing version number. If the
+Program specifies that a certain numbered version of the GNU General
+Public License "or any later version" applies to it, you have the
+option of following the terms and conditions either of that numbered
+version or of any later version published by the Free Software
+Foundation. If the Program does not specify a version number of the
+GNU General Public License, you may choose any version ever published
+by the Free Software Foundation.
+
+ If the Program specifies that a proxy can decide which future
+versions of the GNU General Public License can be used, that proxy's
+public statement of acceptance of a version permanently authorizes you
+to choose that version for the Program.
+
+ Later license versions may give you additional or different
+permissions. However, no additional obligations are imposed on any
+author or copyright holder as a result of your choosing to follow a
+later version.
+
+ 15. Disclaimer of Warranty.
+
+ THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY
+APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT
+HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY
+OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO,
+THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM
+IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF
+ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
+
+ 16. Limitation of Liability.
+
+ IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS
+THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY
+GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE
+USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF
+DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD
+PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS),
+EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF
+SUCH DAMAGES.
+
+ 17. Interpretation of Sections 15 and 16.
+
+ If the disclaimer of warranty and limitation of liability provided
+above cannot be given local legal effect according to their terms,
+reviewing courts shall apply local law that most closely approximates
+an absolute waiver of all civil liability in connection with the
+Program, unless a warranty or assumption of liability accompanies a
+copy of the Program in return for a fee.
+
+ END OF TERMS AND CONDITIONS
+
+ How to Apply These Terms to Your New Programs
+
+ If you develop a new program, and you want it to be of the greatest
+possible use to the public, the best way to achieve this is to make it
+free software which everyone can redistribute and change under these terms.
+
+ To do so, attach the following notices to the program. It is safest
+to attach them to the start of each source file to most effectively
+state the exclusion of warranty; and each file should have at least
+the "copyright" line and a pointer to where the full notice is found.
+
+
+ Copyright (C)
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see .
+
+Also add information on how to contact you by electronic and paper mail.
+
+ If the program does terminal interaction, make it output a short
+notice like this when it starts in an interactive mode:
+
+ Copyright (C)
+ This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
+ This is free software, and you are welcome to redistribute it
+ under certain conditions; type `show c' for details.
+
+The hypothetical commands `show w' and `show c' should show the appropriate
+parts of the General Public License. Of course, your program's commands
+might be different; for a GUI interface, you would use an "about box".
+
+ You should also get your employer (if you work as a programmer) or school,
+if any, to sign a "copyright disclaimer" for the program, if necessary.
+For more information on this, and how to apply and follow the GNU GPL, see
+.
+
+ The GNU General Public License does not permit incorporating your program
+into proprietary programs. If your program is a subroutine library, you
+may consider it more useful to permit linking proprietary applications with
+the library. If this is what you want to do, use the GNU Lesser General
+Public License instead of this License. But first, please read
+.
diff --git a/modules/sale_opportunity/MANIFEST.in b/modules/sale_opportunity/MANIFEST.in
new file mode 100644
index 0000000000..94499680c6
--- /dev/null
+++ b/modules/sale_opportunity/MANIFEST.in
@@ -0,0 +1,6 @@
+include CHANGELOG
+include COPYRIGHT
+include LICENSE
+include README.rst
+include doc/*
+include icons/LICENSE
diff --git a/modules/sale_opportunity/README.rst b/modules/sale_opportunity/README.rst
new file mode 120000
index 0000000000..176d9c2695
--- /dev/null
+++ b/modules/sale_opportunity/README.rst
@@ -0,0 +1 @@
+doc/index.rst
\ No newline at end of file
diff --git a/modules/sale_opportunity/__init__.py b/modules/sale_opportunity/__init__.py
new file mode 100644
index 0000000000..7b2948584e
--- /dev/null
+++ b/modules/sale_opportunity/__init__.py
@@ -0,0 +1,36 @@
+# This file is part of Tryton. The COPYRIGHT file at the top level of
+# this repository contains the full copyright notices and license terms.
+
+from trytond.pool import Pool
+from . import opportunity
+from . import configuration
+from . import sale
+from . import party
+from . import account
+from . import product
+from . import company
+
+
+def register():
+ Pool.register(
+ opportunity.SaleOpportunity,
+ opportunity.SaleOpportunityLine,
+ opportunity.SaleOpportunityEmployee,
+ opportunity.SaleOpportunityEmployeeContext,
+ opportunity.SaleOpportunityMonthly,
+ opportunity.SaleOpportunityEmployeeMonthly,
+ configuration.Configuration,
+ configuration.ConfigurationSequence,
+ sale.Sale,
+ party.Party,
+ party.Address,
+ account.PaymentTerm,
+ account.PaymentTermLine,
+ product.Template,
+ product.Product,
+ company.Company,
+ company.Employee,
+ module='sale_opportunity', type_='model')
+ Pool.register(
+ party.Replace,
+ module='sale_opportunity', type_='wizard')
diff --git a/modules/sale_opportunity/account.py b/modules/sale_opportunity/account.py
new file mode 100644
index 0000000000..8ff01ebb95
--- /dev/null
+++ b/modules/sale_opportunity/account.py
@@ -0,0 +1,13 @@
+# This file is part of Tryton. The COPYRIGHT file at the top level of
+# this repository contains the full copyright notices and license terms.
+from trytond.pool import PoolMeta
+
+
+class PaymentTerm(metaclass=PoolMeta):
+ __name__ = 'account.invoice.payment_term'
+ _history = True
+
+
+class PaymentTermLine(metaclass=PoolMeta):
+ __name__ = 'account.invoice.payment_term.line'
+ _history = True
diff --git a/modules/sale_opportunity/company.py b/modules/sale_opportunity/company.py
new file mode 100644
index 0000000000..5136f7e242
--- /dev/null
+++ b/modules/sale_opportunity/company.py
@@ -0,0 +1,13 @@
+# This file is part of Tryton. The COPYRIGHT file at the top level of
+# this repository contains the full copyright notices and license terms.
+from trytond.pool import PoolMeta
+
+
+class Company(metaclass=PoolMeta):
+ __name__ = 'company.company'
+ _history = True
+
+
+class Employee(metaclass=PoolMeta):
+ __name__ = 'company.employee'
+ _history = True
diff --git a/modules/sale_opportunity/configuration.py b/modules/sale_opportunity/configuration.py
new file mode 100644
index 0000000000..ae90fed2c3
--- /dev/null
+++ b/modules/sale_opportunity/configuration.py
@@ -0,0 +1,72 @@
+# This file is part of Tryton. The COPYRIGHT file at the top level of
+# this repository contains the full copyright notices and license terms.
+from trytond import backend
+from trytond.model import fields
+from trytond.pyson import Eval, Id
+from trytond.pool import PoolMeta, Pool
+
+
+class Configuration(metaclass=PoolMeta):
+ 'Sale Configuration'
+ __name__ = 'sale.configuration'
+ sale_opportunity_sequence = fields.MultiValue(fields.Many2One(
+ 'ir.sequence', "Opportunity Sequence", required=True,
+ domain=[
+ ('company', 'in', [Eval('context', {}).get('company', -1),
+ None]),
+ ('sequence_type', '=',
+ Id('sale_opportunity', 'sequence_type_sale_opportunity')),
+ ]))
+
+ @classmethod
+ def multivalue_model(cls, field):
+ pool = Pool()
+ if field == 'sale_opportunity_sequence':
+ return pool.get('sale.configuration.sequence')
+ return super(Configuration, cls).multivalue_model(field)
+
+ @classmethod
+ def default_sale_opportunity_sequence(cls, **pattern):
+ return cls.multivalue_model(
+ 'sale_opportunity_sequence').default_sale_opportunity_sequence()
+
+
+class ConfigurationSequence(metaclass=PoolMeta):
+ __name__ = 'sale.configuration.sequence'
+ sale_opportunity_sequence = fields.Many2One(
+ 'ir.sequence', "Opportunity Sequence", required=True,
+ domain=[
+ ('company', 'in', [Eval('company', -1), None]),
+ ('sequence_type', '=',
+ Id('sale_opportunity', 'sequence_type_sale_opportunity')),
+ ],
+ depends=['company'])
+
+ @classmethod
+ def __register__(cls, module_name):
+ exist = backend.TableHandler.table_exist(cls._table)
+ if exist:
+ table = cls.__table_handler__(module_name)
+ exist &= table.column_exist('sale_opportunity_sequence')
+
+ super(ConfigurationSequence, cls).__register__(module_name)
+
+ if not exist:
+ cls._migrate_property([], [], [])
+
+ @classmethod
+ def _migrate_property(cls, field_names, value_names, fields):
+ field_names.append('sale_opportunity_sequence')
+ value_names.append('sale_opportunity_sequence')
+ super(ConfigurationSequence, cls)._migrate_property(
+ field_names, value_names, fields)
+
+ @classmethod
+ def default_sale_opportunity_sequence(cls):
+ pool = Pool()
+ ModelData = pool.get('ir.model.data')
+ try:
+ return ModelData.get_id(
+ 'sale_opportunity', 'sequence_sale_opportunity')
+ except KeyError:
+ return None
diff --git a/modules/sale_opportunity/configuration.xml b/modules/sale_opportunity/configuration.xml
new file mode 100644
index 0000000000..71f8fea64b
--- /dev/null
+++ b/modules/sale_opportunity/configuration.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+ sale.configuration
+
+ configuration_form
+
+
+
diff --git a/modules/sale_opportunity/doc/index.rst b/modules/sale_opportunity/doc/index.rst
new file mode 100644
index 0000000000..11ca27075a
--- /dev/null
+++ b/modules/sale_opportunity/doc/index.rst
@@ -0,0 +1,77 @@
+Sale Opportunity Module
+#######################
+
+The sale_opportunity module defines the lead/opportunity model.
+
+Lead/Opportunity
+****************
+
+The lead and opportunity are defined by the same record but with different state.
+Depending on the state, fields of the record become mandatory. Here is the
+extensive list of the fields, most of them are optional:
+
+- Party: The customer.
+- Contact: The contact who placed the order.
+- Address: The main address of the customer.
+- Description: The description of the lead/opportunity.
+- Number: The internal reference of the lead/opportunity (will be generated
+ automatically at creation).
+- Reference: The optional external reference of the order.
+- Amount: The estimated revenue amount.
+- Currency: Define the currency of the amount.
+- Probability: The probability of conversion.
+- Company: The company which issue the lead/opportunity.
+- Employee: The employee responsible of the lead/opportunity.
+- Start Date: When the lead started.
+- End Date: When the lead ends (automatically set on win, cancel or lost).
+- Payment Term: Define which payment term will be used for the future invoice.
+- Comment: A text field to add custom comments.
+- State: The state of the lead/opportunity. May take one of the following
+ values:
+
+ - Lead
+ - Opportunity
+ - Converted
+ - Won
+ - Cancelled
+ - Lost
+
+- Lines: A list of *Lead/Opportunity* line
+- Sales: The list of sales converted from this opportunity.
+- History: The list of changes made over time to the lead/opportunity.
+
+The first time an opportunity is converted, a sale is created base on the
+information of the opportunity and the lines.
+The amount of the opportunity is later updated with the sales amount.
+Once all the sales of an opportunity are confirmed (or cancelled with at least
+one confirmed), the opportunity is won.
+If all the sales of an opportunity are cancelled than the opportunity is lost.
+
+Lead/Opportunity Line
+*********************
+
+A lead/opportunity line define a quantity of product that are expected to be sold.
+
+Reports
+*******
+
+The sale_opportunity module defines also some reports:
+
+- Opportunities per Employee.
+- Opportunities per Month.
+- Opportunities per Employee per Month.
+
+which all show:
+
+- The number of leads/opportunities.
+- The number of converted opportunities.
+- The convertion rate.
+- The number of won opportunities.
+- The winning rate.
+- The number of lost opportunities.
+
+- The total amount of leads/opportunities.
+- The total amount of converted opportunities.
+- The convertion amount rate.
+- The total amount of won opportunities.
+- The winning amount rate.
diff --git a/modules/sale_opportunity/icons/LICENSE b/modules/sale_opportunity/icons/LICENSE
new file mode 100644
index 0000000000..7a4a3ea242
--- /dev/null
+++ b/modules/sale_opportunity/icons/LICENSE
@@ -0,0 +1,202 @@
+
+ Apache License
+ Version 2.0, January 2004
+ http://www.apache.org/licenses/
+
+ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+ 1. Definitions.
+
+ "License" shall mean the terms and conditions for use, reproduction,
+ and distribution as defined by Sections 1 through 9 of this document.
+
+ "Licensor" shall mean the copyright owner or entity authorized by
+ the copyright owner that is granting the License.
+
+ "Legal Entity" shall mean the union of the acting entity and all
+ other entities that control, are controlled by, or are under common
+ control with that entity. For the purposes of this definition,
+ "control" means (i) the power, direct or indirect, to cause the
+ direction or management of such entity, whether by contract or
+ otherwise, or (ii) ownership of fifty percent (50%) or more of the
+ outstanding shares, or (iii) beneficial ownership of such entity.
+
+ "You" (or "Your") shall mean an individual or Legal Entity
+ exercising permissions granted by this License.
+
+ "Source" form shall mean the preferred form for making modifications,
+ including but not limited to software source code, documentation
+ source, and configuration files.
+
+ "Object" form shall mean any form resulting from mechanical
+ transformation or translation of a Source form, including but
+ not limited to compiled object code, generated documentation,
+ and conversions to other media types.
+
+ "Work" shall mean the work of authorship, whether in Source or
+ Object form, made available under the License, as indicated by a
+ copyright notice that is included in or attached to the work
+ (an example is provided in the Appendix below).
+
+ "Derivative Works" shall mean any work, whether in Source or Object
+ form, that is based on (or derived from) the Work and for which the
+ editorial revisions, annotations, elaborations, or other modifications
+ represent, as a whole, an original work of authorship. For the purposes
+ of this License, Derivative Works shall not include works that remain
+ separable from, or merely link (or bind by name) to the interfaces of,
+ the Work and Derivative Works thereof.
+
+ "Contribution" shall mean any work of authorship, including
+ the original version of the Work and any modifications or additions
+ to that Work or Derivative Works thereof, that is intentionally
+ submitted to Licensor for inclusion in the Work by the copyright owner
+ or by an individual or Legal Entity authorized to submit on behalf of
+ the copyright owner. For the purposes of this definition, "submitted"
+ means any form of electronic, verbal, or written communication sent
+ to the Licensor or its representatives, including but not limited to
+ communication on electronic mailing lists, source code control systems,
+ and issue tracking systems that are managed by, or on behalf of, the
+ Licensor for the purpose of discussing and improving the Work, but
+ excluding communication that is conspicuously marked or otherwise
+ designated in writing by the copyright owner as "Not a Contribution."
+
+ "Contributor" shall mean Licensor and any individual or Legal Entity
+ on behalf of whom a Contribution has been received by Licensor and
+ subsequently incorporated within the Work.
+
+ 2. Grant of Copyright License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ copyright license to reproduce, prepare Derivative Works of,
+ publicly display, publicly perform, sublicense, and distribute the
+ Work and such Derivative Works in Source or Object form.
+
+ 3. Grant of Patent License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ (except as stated in this section) patent license to make, have made,
+ use, offer to sell, sell, import, and otherwise transfer the Work,
+ where such license applies only to those patent claims licensable
+ by such Contributor that are necessarily infringed by their
+ Contribution(s) alone or by combination of their Contribution(s)
+ with the Work to which such Contribution(s) was submitted. If You
+ institute patent litigation against any entity (including a
+ cross-claim or counterclaim in a lawsuit) alleging that the Work
+ or a Contribution incorporated within the Work constitutes direct
+ or contributory patent infringement, then any patent licenses
+ granted to You under this License for that Work shall terminate
+ as of the date such litigation is filed.
+
+ 4. Redistribution. You may reproduce and distribute copies of the
+ Work or Derivative Works thereof in any medium, with or without
+ modifications, and in Source or Object form, provided that You
+ meet the following conditions:
+
+ (a) You must give any other recipients of the Work or
+ Derivative Works a copy of this License; and
+
+ (b) You must cause any modified files to carry prominent notices
+ stating that You changed the files; and
+
+ (c) You must retain, in the Source form of any Derivative Works
+ that You distribute, all copyright, patent, trademark, and
+ attribution notices from the Source form of the Work,
+ excluding those notices that do not pertain to any part of
+ the Derivative Works; and
+
+ (d) If the Work includes a "NOTICE" text file as part of its
+ distribution, then any Derivative Works that You distribute must
+ include a readable copy of the attribution notices contained
+ within such NOTICE file, excluding those notices that do not
+ pertain to any part of the Derivative Works, in at least one
+ of the following places: within a NOTICE text file distributed
+ as part of the Derivative Works; within the Source form or
+ documentation, if provided along with the Derivative Works; or,
+ within a display generated by the Derivative Works, if and
+ wherever such third-party notices normally appear. The contents
+ of the NOTICE file are for informational purposes only and
+ do not modify the License. You may add Your own attribution
+ notices within Derivative Works that You distribute, alongside
+ or as an addendum to the NOTICE text from the Work, provided
+ that such additional attribution notices cannot be construed
+ as modifying the License.
+
+ You may add Your own copyright statement to Your modifications and
+ may provide additional or different license terms and conditions
+ for use, reproduction, or distribution of Your modifications, or
+ for any such Derivative Works as a whole, provided Your use,
+ reproduction, and distribution of the Work otherwise complies with
+ the conditions stated in this License.
+
+ 5. Submission of Contributions. Unless You explicitly state otherwise,
+ any Contribution intentionally submitted for inclusion in the Work
+ by You to the Licensor shall be under the terms and conditions of
+ this License, without any additional terms or conditions.
+ Notwithstanding the above, nothing herein shall supersede or modify
+ the terms of any separate license agreement you may have executed
+ with Licensor regarding such Contributions.
+
+ 6. Trademarks. This License does not grant permission to use the trade
+ names, trademarks, service marks, or product names of the Licensor,
+ except as required for reasonable and customary use in describing the
+ origin of the Work and reproducing the content of the NOTICE file.
+
+ 7. Disclaimer of Warranty. Unless required by applicable law or
+ agreed to in writing, Licensor provides the Work (and each
+ Contributor provides its Contributions) on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ implied, including, without limitation, any warranties or conditions
+ of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+ PARTICULAR PURPOSE. You are solely responsible for determining the
+ appropriateness of using or redistributing the Work and assume any
+ risks associated with Your exercise of permissions under this License.
+
+ 8. Limitation of Liability. In no event and under no legal theory,
+ whether in tort (including negligence), contract, or otherwise,
+ unless required by applicable law (such as deliberate and grossly
+ negligent acts) or agreed to in writing, shall any Contributor be
+ liable to You for damages, including any direct, indirect, special,
+ incidental, or consequential damages of any character arising as a
+ result of this License or out of the use or inability to use the
+ Work (including but not limited to damages for loss of goodwill,
+ work stoppage, computer failure or malfunction, or any and all
+ other commercial damages or losses), even if such Contributor
+ has been advised of the possibility of such damages.
+
+ 9. Accepting Warranty or Additional Liability. While redistributing
+ the Work or Derivative Works thereof, You may choose to offer,
+ and charge a fee for, acceptance of support, warranty, indemnity,
+ or other liability obligations and/or rights consistent with this
+ License. However, in accepting such obligations, You may act only
+ on Your own behalf and on Your sole responsibility, not on behalf
+ of any other Contributor, and only if You agree to indemnify,
+ defend, and hold each Contributor harmless for any liability
+ incurred by, or claims asserted against, such Contributor by reason
+ of your accepting any such warranty or additional liability.
+
+ END OF TERMS AND CONDITIONS
+
+ APPENDIX: How to apply the Apache License to your work.
+
+ To apply the Apache License to your work, attach the following
+ boilerplate notice, with the fields enclosed by brackets "[]"
+ replaced with your own identifying information. (Don't include
+ the brackets!) The text should be enclosed in the appropriate
+ comment syntax for the file format. We also recommend that a
+ file or class name and description of purpose be included on the
+ same "printed page" as the copyright notice for easier
+ identification within third-party archives.
+
+ Copyright [yyyy] [name of copyright owner]
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
\ No newline at end of file
diff --git a/modules/sale_opportunity/icons/tryton-sale-opportunity.svg b/modules/sale_opportunity/icons/tryton-sale-opportunity.svg
new file mode 100644
index 0000000000..5ab8c67304
--- /dev/null
+++ b/modules/sale_opportunity/icons/tryton-sale-opportunity.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/modules/sale_opportunity/locale/bg.po b/modules/sale_opportunity/locale/bg.po
new file mode 100644
index 0000000000..1c1d4d809e
--- /dev/null
+++ b/modules/sale_opportunity/locale/bg.po
@@ -0,0 +1,566 @@
+#
+msgid ""
+msgstr "Content-Type: text/plain; charset=utf-8\n"
+
+msgctxt "field:sale.configuration,sale_opportunity_sequence:"
+msgid "Opportunity Sequence"
+msgstr ""
+
+msgctxt "field:sale.configuration.sequence,sale_opportunity_sequence:"
+msgid "Opportunity Sequence"
+msgstr ""
+
+msgctxt "field:sale.opportunity,address:"
+msgid "Address"
+msgstr "Адрес"
+
+msgctxt "field:sale.opportunity,amount:"
+msgid "Amount"
+msgstr "Сума"
+
+msgctxt "field:sale.opportunity,comment:"
+msgid "Comment"
+msgstr "Коментар"
+
+msgctxt "field:sale.opportunity,company:"
+msgid "Company"
+msgstr "Фирма"
+
+msgctxt "field:sale.opportunity,contact:"
+msgid "Contact"
+msgstr ""
+
+msgctxt "field:sale.opportunity,conversion_probability:"
+msgid "Conversion Probability"
+msgstr ""
+
+#, fuzzy
+msgctxt "field:sale.opportunity,converted_by:"
+msgid "Converted By"
+msgstr "Конвертиран"
+
+msgctxt "field:sale.opportunity,currency:"
+msgid "Currency"
+msgstr "Валута"
+
+msgctxt "field:sale.opportunity,currency_digits:"
+msgid "Currency Digits"
+msgstr "Цифри за валута"
+
+msgctxt "field:sale.opportunity,description:"
+msgid "Description"
+msgstr "Описание"
+
+msgctxt "field:sale.opportunity,employee:"
+msgid "Employee"
+msgstr "Служител"
+
+msgctxt "field:sale.opportunity,end_date:"
+msgid "End Date"
+msgstr "Крайна дата"
+
+msgctxt "field:sale.opportunity,lines:"
+msgid "Lines"
+msgstr "Редове"
+
+msgctxt "field:sale.opportunity,lost_reason:"
+msgid "Reason for loss"
+msgstr "Причина за загуба"
+
+#, fuzzy
+msgctxt "field:sale.opportunity,number:"
+msgid "Number"
+msgstr "Номер"
+
+msgctxt "field:sale.opportunity,party:"
+msgid "Party"
+msgstr "Партньор"
+
+msgctxt "field:sale.opportunity,payment_term:"
+msgid "Payment Term"
+msgstr "Условие за плащане"
+
+#, fuzzy
+msgctxt "field:sale.opportunity,reference:"
+msgid "Reference"
+msgstr "Препратка"
+
+#, fuzzy
+msgctxt "field:sale.opportunity,sales:"
+msgid "Sales"
+msgstr "Управление на продажби"
+
+msgctxt "field:sale.opportunity,start_date:"
+msgid "Start Date"
+msgstr "Начална дата"
+
+msgctxt "field:sale.opportunity,state:"
+msgid "State"
+msgstr "Състояние"
+
+msgctxt "field:sale.opportunity.line,opportunity:"
+msgid "Opportunity"
+msgstr "Възможност"
+
+msgctxt "field:sale.opportunity.line,opportunity_state:"
+msgid "Opportunity State"
+msgstr ""
+
+msgctxt "field:sale.opportunity.line,product:"
+msgid "Product"
+msgstr "Продукт"
+
+msgctxt "field:sale.opportunity.line,quantity:"
+msgid "Quantity"
+msgstr "Количество"
+
+msgctxt "field:sale.opportunity.line,unit:"
+msgid "Unit"
+msgstr "Единица"
+
+msgctxt "field:sale.opportunity.line,unit_digits:"
+msgid "Unit Digits"
+msgstr "Десетични единици"
+
+msgctxt "field:sale.opportunity_employee,amount:"
+msgid "Amount"
+msgstr "Сума"
+
+msgctxt "field:sale.opportunity_employee,company:"
+msgid "Company"
+msgstr "Фирма"
+
+msgctxt "field:sale.opportunity_employee,conversion_amount_rate:"
+msgid "Conversion Amount Rate"
+msgstr "Обменен курс"
+
+msgctxt "field:sale.opportunity_employee,conversion_rate:"
+msgid "Conversion Rate"
+msgstr "Обменен курс"
+
+msgctxt "field:sale.opportunity_employee,converted:"
+msgid "Converted"
+msgstr "Конвертиран"
+
+msgctxt "field:sale.opportunity_employee,converted_amount:"
+msgid "Converted Amount"
+msgstr "Конвертирана сума"
+
+msgctxt "field:sale.opportunity_employee,currency:"
+msgid "Currency"
+msgstr "Валута"
+
+msgctxt "field:sale.opportunity_employee,currency_digits:"
+msgid "Currency Digits"
+msgstr "Цифри за валута"
+
+msgctxt "field:sale.opportunity_employee,employee:"
+msgid "Employee"
+msgstr "Служител"
+
+msgctxt "field:sale.opportunity_employee,lost:"
+msgid "Lost"
+msgstr "Изгубен"
+
+msgctxt "field:sale.opportunity_employee,number:"
+msgid "Number"
+msgstr "Номер"
+
+msgctxt "field:sale.opportunity_employee,winning_amount_rate:"
+msgid "Winning Amount Rate"
+msgstr ""
+
+msgctxt "field:sale.opportunity_employee,winning_rate:"
+msgid "Winning Rate"
+msgstr ""
+
+#, fuzzy
+msgctxt "field:sale.opportunity_employee,won:"
+msgid "Won"
+msgstr "Уон"
+
+msgctxt "field:sale.opportunity_employee,won_amount:"
+msgid "Won Amount"
+msgstr ""
+
+#, fuzzy
+msgctxt "field:sale.opportunity_employee.context,end_date:"
+msgid "End Date"
+msgstr "Крайна дата"
+
+#, fuzzy
+msgctxt "field:sale.opportunity_employee.context,start_date:"
+msgid "Start Date"
+msgstr "Начална дата"
+
+msgctxt "field:sale.opportunity_employee_monthly,amount:"
+msgid "Amount"
+msgstr "Сума"
+
+msgctxt "field:sale.opportunity_employee_monthly,company:"
+msgid "Company"
+msgstr "Фирма"
+
+msgctxt "field:sale.opportunity_employee_monthly,conversion_amount_rate:"
+msgid "Conversion Amount Rate"
+msgstr "Обменен курс"
+
+msgctxt "field:sale.opportunity_employee_monthly,conversion_rate:"
+msgid "Conversion Rate"
+msgstr "Обменен курс"
+
+msgctxt "field:sale.opportunity_employee_monthly,converted:"
+msgid "Converted"
+msgstr "Конвертиран"
+
+msgctxt "field:sale.opportunity_employee_monthly,converted_amount:"
+msgid "Converted Amount"
+msgstr "Конвертирана сума"
+
+msgctxt "field:sale.opportunity_employee_monthly,currency:"
+msgid "Currency"
+msgstr "Валута"
+
+msgctxt "field:sale.opportunity_employee_monthly,currency_digits:"
+msgid "Currency Digits"
+msgstr "Цифри за валута"
+
+msgctxt "field:sale.opportunity_employee_monthly,employee:"
+msgid "Employee"
+msgstr "Служител"
+
+msgctxt "field:sale.opportunity_employee_monthly,lost:"
+msgid "Lost"
+msgstr "Изгубен"
+
+msgctxt "field:sale.opportunity_employee_monthly,month:"
+msgid "Month"
+msgstr "Месец"
+
+msgctxt "field:sale.opportunity_employee_monthly,number:"
+msgid "Number"
+msgstr "Номер"
+
+msgctxt "field:sale.opportunity_employee_monthly,winning_amount_rate:"
+msgid "Winning Amount Rate"
+msgstr ""
+
+msgctxt "field:sale.opportunity_employee_monthly,winning_rate:"
+msgid "Winning Rate"
+msgstr ""
+
+#, fuzzy
+msgctxt "field:sale.opportunity_employee_monthly,won:"
+msgid "Won"
+msgstr "Уон"
+
+msgctxt "field:sale.opportunity_employee_monthly,won_amount:"
+msgid "Won Amount"
+msgstr ""
+
+msgctxt "field:sale.opportunity_employee_monthly,year:"
+msgid "Year"
+msgstr "Година"
+
+msgctxt "field:sale.opportunity_monthly,amount:"
+msgid "Amount"
+msgstr "Сума"
+
+msgctxt "field:sale.opportunity_monthly,company:"
+msgid "Company"
+msgstr "Фирма"
+
+msgctxt "field:sale.opportunity_monthly,conversion_amount_rate:"
+msgid "Conversion Amount Rate"
+msgstr "Обменен курс"
+
+msgctxt "field:sale.opportunity_monthly,conversion_rate:"
+msgid "Conversion Rate"
+msgstr "Обменен курс"
+
+msgctxt "field:sale.opportunity_monthly,converted:"
+msgid "Converted"
+msgstr "Конвертиран"
+
+msgctxt "field:sale.opportunity_monthly,converted_amount:"
+msgid "Converted Amount"
+msgstr "Конвертирана сума"
+
+msgctxt "field:sale.opportunity_monthly,currency:"
+msgid "Currency"
+msgstr "Валута"
+
+msgctxt "field:sale.opportunity_monthly,currency_digits:"
+msgid "Currency Digits"
+msgstr "Цифри за валута"
+
+msgctxt "field:sale.opportunity_monthly,lost:"
+msgid "Lost"
+msgstr "Изгубен"
+
+msgctxt "field:sale.opportunity_monthly,month:"
+msgid "Month"
+msgstr "Месец"
+
+msgctxt "field:sale.opportunity_monthly,number:"
+msgid "Number"
+msgstr "Номер"
+
+msgctxt "field:sale.opportunity_monthly,winning_amount_rate:"
+msgid "Winning Amount Rate"
+msgstr ""
+
+msgctxt "field:sale.opportunity_monthly,winning_rate:"
+msgid "Winning Rate"
+msgstr ""
+
+#, fuzzy
+msgctxt "field:sale.opportunity_monthly,won:"
+msgid "Won"
+msgstr "Уон"
+
+msgctxt "field:sale.opportunity_monthly,won_amount:"
+msgid "Won Amount"
+msgstr ""
+
+msgctxt "field:sale.opportunity_monthly,year:"
+msgid "Year"
+msgstr "Година"
+
+msgctxt "field:sale.opportunity_monthly,year_month:"
+msgid "Year-Month"
+msgstr "Година-Месец"
+
+#, fuzzy
+msgctxt "help:sale.opportunity,amount:"
+msgid "Estimated revenue amount."
+msgstr "Очаквани приходи"
+
+msgctxt "help:sale.opportunity,conversion_probability:"
+msgid "Percentage between 0 and 100."
+msgstr ""
+
+#, fuzzy
+msgctxt "model:ir.action,name:act_open_sale_form"
+msgid "Sales"
+msgstr "Управление на продажби"
+
+#, fuzzy
+msgctxt "model:ir.action,name:act_opportunity_employee_form"
+msgid "Opportunities per Employee"
+msgstr "Opportunities per Employee"
+
+#, fuzzy
+msgctxt "model:ir.action,name:act_opportunity_employee_monthly_form"
+msgid "Opportunities per Employee per Month"
+msgstr "Opportunities per Employee per Month"
+
+#, fuzzy
+msgctxt "model:ir.action,name:act_opportunity_form"
+msgid "Leads and Opportunities"
+msgstr "Leads and Opportunities"
+
+#, fuzzy
+msgctxt "model:ir.action,name:act_opportunity_form2"
+msgid "Sales Leads/Opportunities"
+msgstr "Sales Leads/Opportunities"
+
+#, fuzzy
+msgctxt "model:ir.action,name:act_opportunity_monthly_form"
+msgid "Opportunities per Month"
+msgstr "Opportunities per Month"
+
+msgctxt ""
+"model:ir.action.act_window.domain,name:act_opportunity_form_domain_all"
+msgid "All"
+msgstr "All"
+
+#, fuzzy
+msgctxt ""
+"model:ir.action.act_window.domain,name:act_opportunity_form_domain_cancelled"
+msgid "Cancelled"
+msgstr "Отказан"
+
+#, fuzzy
+msgctxt ""
+"model:ir.action.act_window.domain,name:act_opportunity_form_domain_converted"
+msgid "Converted"
+msgstr "Конвертиран"
+
+#, fuzzy
+msgctxt ""
+"model:ir.action.act_window.domain,name:act_opportunity_form_domain_leads"
+msgid "Leads"
+msgstr "Инициатива"
+
+#, fuzzy
+msgctxt ""
+"model:ir.action.act_window.domain,name:act_opportunity_form_domain_lost"
+msgid "Lost"
+msgstr "Изгубен"
+
+#, fuzzy
+msgctxt ""
+"model:ir.action.act_window.domain,name:act_opportunity_form_domain_opportunities"
+msgid "Opportunities"
+msgstr "Възможност"
+
+#, fuzzy
+msgctxt ""
+"model:ir.action.act_window.domain,name:act_opportunity_form_domain_won"
+msgid "Won"
+msgstr "Уон"
+
+msgctxt "model:ir.message,text:msg_modify_origin_opportunity"
+msgid "You cannot modify the opportunity origin of the sale \"%(sale)s\"."
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_opportunity_delete_cancel"
+msgid "To delete opportunity \"%(opportunity)s\", you must cancel it."
+msgstr ""
+
+msgctxt "model:ir.model.button,string:opportunity_cancel_button"
+msgid "Cancel"
+msgstr "Cancel"
+
+msgctxt "model:ir.model.button,string:opportunity_convert_button"
+msgid "Convert to Sale"
+msgstr "Convert to Sale"
+
+msgctxt "model:ir.model.button,string:opportunity_lead_button"
+msgid "Set as Lead"
+msgstr "Set as Lead"
+
+msgctxt "model:ir.model.button,string:opportunity_lost_button"
+msgid "Mark as Lost"
+msgstr "Mark as Lost"
+
+msgctxt "model:ir.model.button,string:opportunity_opportunity_button"
+msgid "Convert to Opportunity"
+msgstr "Convert to Opportunity"
+
+msgctxt "model:ir.rule.group,name:rule_group_opportunity_companies"
+msgid "User in companies"
+msgstr ""
+
+msgctxt "model:ir.rule.group,name:rule_group_opportunity_employee_companies"
+msgid "User in companies"
+msgstr ""
+
+msgctxt ""
+"model:ir.rule.group,name:rule_group_opportunity_employee_monthly_companies"
+msgid "User in companies"
+msgstr ""
+
+msgctxt "model:ir.rule.group,name:rule_group_opportunity_monthly_companies"
+msgid "User in companies"
+msgstr ""
+
+#, fuzzy
+msgctxt "model:ir.sequence,name:sequence_sale_opportunity"
+msgid "Sale Opportunity"
+msgstr "Възможност за продажба"
+
+#, fuzzy
+msgctxt "model:ir.sequence.type,name:sequence_type_sale_opportunity"
+msgid "Sale Opportunity"
+msgstr "Възможност за продажба"
+
+#, fuzzy
+msgctxt "model:ir.ui.menu,name:menu_opportunity_employee_monthly_form"
+msgid "Opportunities per Employee per Month"
+msgstr "Opportunities per Employee per Month"
+
+#, fuzzy
+msgctxt "model:ir.ui.menu,name:menu_opportunity_employee_open"
+msgid "Opportunities per Employee"
+msgstr "Opportunities per Employee"
+
+#, fuzzy
+msgctxt "model:ir.ui.menu,name:menu_opportunity_form"
+msgid "Leads and Opportunities"
+msgstr "Leads and Opportunities"
+
+#, fuzzy
+msgctxt "model:ir.ui.menu,name:menu_opportunity_monthly_form"
+msgid "Opportunities per Month"
+msgstr "Opportunities per Month"
+
+#, fuzzy
+msgctxt "model:res.group,name:group_opportunity"
+msgid "Sale Opportunity"
+msgstr "Sale Opportunity"
+
+msgctxt "model:sale.opportunity,name:"
+msgid "Sale Opportunity"
+msgstr "Възможност за продажба"
+
+msgctxt "model:sale.opportunity.line,name:"
+msgid "Sale Opportunity Line"
+msgstr "Ред от възможност за продажба"
+
+msgctxt "model:sale.opportunity_employee,name:"
+msgid "Sale Opportunity per Employee"
+msgstr "Възможност за продажба за служител"
+
+#, fuzzy
+msgctxt "model:sale.opportunity_employee.context,name:"
+msgid "Sale Opportunity per Employee Context"
+msgstr "Възможност за продажба за служител за месец"
+
+msgctxt "model:sale.opportunity_employee_monthly,name:"
+msgid "Sale Opportunity per Employee per Month"
+msgstr "Възможност за продажба за служител за месец"
+
+msgctxt "model:sale.opportunity_monthly,name:"
+msgid "Sale Opportunity per Month"
+msgstr "Възможност за продажа по месец"
+
+msgctxt "selection:sale.opportunity,state:"
+msgid "Cancelled"
+msgstr "Отказан"
+
+msgctxt "selection:sale.opportunity,state:"
+msgid "Converted"
+msgstr "Конвертиран"
+
+msgctxt "selection:sale.opportunity,state:"
+msgid "Lead"
+msgstr "Инициатива"
+
+msgctxt "selection:sale.opportunity,state:"
+msgid "Lost"
+msgstr "Изгубен"
+
+msgctxt "selection:sale.opportunity,state:"
+msgid "Opportunity"
+msgstr "Възможност"
+
+#, fuzzy
+msgctxt "selection:sale.opportunity,state:"
+msgid "Won"
+msgstr "Уон"
+
+#, fuzzy
+msgctxt "view:sale.opportunity:"
+msgid "%"
+msgstr "%"
+
+msgctxt "view:sale.opportunity:"
+msgid "Lead/Opportunity"
+msgstr "Инициатива/Възможност"
+
+#, fuzzy
+msgctxt "view:sale.opportunity_employee:"
+msgid "%"
+msgstr "%"
+
+#, fuzzy
+msgctxt "view:sale.opportunity_employee_monthly:"
+msgid "%"
+msgstr "%"
+
+#, fuzzy
+msgctxt "view:sale.opportunity_monthly:"
+msgid "%"
+msgstr "%"
diff --git a/modules/sale_opportunity/locale/ca.po b/modules/sale_opportunity/locale/ca.po
new file mode 100644
index 0000000000..afabf3c283
--- /dev/null
+++ b/modules/sale_opportunity/locale/ca.po
@@ -0,0 +1,532 @@
+#
+msgid ""
+msgstr "Content-Type: text/plain; charset=utf-8\n"
+
+msgctxt "field:sale.configuration,sale_opportunity_sequence:"
+msgid "Opportunity Sequence"
+msgstr "Seqüència d'oportunitat"
+
+msgctxt "field:sale.configuration.sequence,sale_opportunity_sequence:"
+msgid "Opportunity Sequence"
+msgstr "Seqüència d'oportunitat"
+
+msgctxt "field:sale.opportunity,address:"
+msgid "Address"
+msgstr "Adreça"
+
+msgctxt "field:sale.opportunity,amount:"
+msgid "Amount"
+msgstr "Import"
+
+msgctxt "field:sale.opportunity,comment:"
+msgid "Comment"
+msgstr "Comentari"
+
+msgctxt "field:sale.opportunity,company:"
+msgid "Company"
+msgstr "Empresa"
+
+msgctxt "field:sale.opportunity,contact:"
+msgid "Contact"
+msgstr "Contacte"
+
+msgctxt "field:sale.opportunity,conversion_probability:"
+msgid "Conversion Probability"
+msgstr "Probabilitat de conversió"
+
+msgctxt "field:sale.opportunity,converted_by:"
+msgid "Converted By"
+msgstr "Convertida per"
+
+msgctxt "field:sale.opportunity,currency:"
+msgid "Currency"
+msgstr "Moneda"
+
+msgctxt "field:sale.opportunity,currency_digits:"
+msgid "Currency Digits"
+msgstr "Decimals de la moneda"
+
+msgctxt "field:sale.opportunity,description:"
+msgid "Description"
+msgstr "Descripció"
+
+msgctxt "field:sale.opportunity,employee:"
+msgid "Employee"
+msgstr "Empleat"
+
+msgctxt "field:sale.opportunity,end_date:"
+msgid "End Date"
+msgstr "Data final"
+
+msgctxt "field:sale.opportunity,lines:"
+msgid "Lines"
+msgstr "Línies"
+
+msgctxt "field:sale.opportunity,lost_reason:"
+msgid "Reason for loss"
+msgstr "Motius de la pèrdua"
+
+msgctxt "field:sale.opportunity,number:"
+msgid "Number"
+msgstr "Número"
+
+msgctxt "field:sale.opportunity,party:"
+msgid "Party"
+msgstr "Tercer"
+
+msgctxt "field:sale.opportunity,payment_term:"
+msgid "Payment Term"
+msgstr "Termini de pagament"
+
+msgctxt "field:sale.opportunity,reference:"
+msgid "Reference"
+msgstr "Referència"
+
+msgctxt "field:sale.opportunity,sales:"
+msgid "Sales"
+msgstr "Vendes"
+
+msgctxt "field:sale.opportunity,start_date:"
+msgid "Start Date"
+msgstr "Data inicial"
+
+msgctxt "field:sale.opportunity,state:"
+msgid "State"
+msgstr "Estat"
+
+msgctxt "field:sale.opportunity.line,opportunity:"
+msgid "Opportunity"
+msgstr "Oportunitat"
+
+msgctxt "field:sale.opportunity.line,opportunity_state:"
+msgid "Opportunity State"
+msgstr "Estat de l'oportunitat"
+
+msgctxt "field:sale.opportunity.line,product:"
+msgid "Product"
+msgstr "Producte"
+
+msgctxt "field:sale.opportunity.line,quantity:"
+msgid "Quantity"
+msgstr "Quantitat"
+
+msgctxt "field:sale.opportunity.line,unit:"
+msgid "Unit"
+msgstr "Unitat"
+
+msgctxt "field:sale.opportunity.line,unit_digits:"
+msgid "Unit Digits"
+msgstr "Dígits de la unitat"
+
+msgctxt "field:sale.opportunity_employee,amount:"
+msgid "Amount"
+msgstr "Import"
+
+msgctxt "field:sale.opportunity_employee,company:"
+msgid "Company"
+msgstr "Empresa"
+
+msgctxt "field:sale.opportunity_employee,conversion_amount_rate:"
+msgid "Conversion Amount Rate"
+msgstr "Percentatge convertides (sobre import)"
+
+msgctxt "field:sale.opportunity_employee,conversion_rate:"
+msgid "Conversion Rate"
+msgstr "Percentatge convertides"
+
+msgctxt "field:sale.opportunity_employee,converted:"
+msgid "Converted"
+msgstr "Convertides"
+
+msgctxt "field:sale.opportunity_employee,converted_amount:"
+msgid "Converted Amount"
+msgstr "Import convertides"
+
+msgctxt "field:sale.opportunity_employee,currency:"
+msgid "Currency"
+msgstr "Moneda"
+
+msgctxt "field:sale.opportunity_employee,currency_digits:"
+msgid "Currency Digits"
+msgstr "Decimals de la moneda"
+
+msgctxt "field:sale.opportunity_employee,employee:"
+msgid "Employee"
+msgstr "Empleat"
+
+msgctxt "field:sale.opportunity_employee,lost:"
+msgid "Lost"
+msgstr "Perdudes"
+
+msgctxt "field:sale.opportunity_employee,number:"
+msgid "Number"
+msgstr "Número"
+
+msgctxt "field:sale.opportunity_employee,winning_amount_rate:"
+msgid "Winning Amount Rate"
+msgstr "Percentatge guanyades (sobre import)"
+
+msgctxt "field:sale.opportunity_employee,winning_rate:"
+msgid "Winning Rate"
+msgstr "Percentatge guanyades"
+
+msgctxt "field:sale.opportunity_employee,won:"
+msgid "Won"
+msgstr "Guanyades"
+
+msgctxt "field:sale.opportunity_employee,won_amount:"
+msgid "Won Amount"
+msgstr "Import guanyades"
+
+msgctxt "field:sale.opportunity_employee.context,end_date:"
+msgid "End Date"
+msgstr "Data final"
+
+msgctxt "field:sale.opportunity_employee.context,start_date:"
+msgid "Start Date"
+msgstr "Data inicial"
+
+msgctxt "field:sale.opportunity_employee_monthly,amount:"
+msgid "Amount"
+msgstr "Import"
+
+msgctxt "field:sale.opportunity_employee_monthly,company:"
+msgid "Company"
+msgstr "Empresa"
+
+msgctxt "field:sale.opportunity_employee_monthly,conversion_amount_rate:"
+msgid "Conversion Amount Rate"
+msgstr "Percentatge convertides (sobre import)"
+
+msgctxt "field:sale.opportunity_employee_monthly,conversion_rate:"
+msgid "Conversion Rate"
+msgstr "Percentatge convertides"
+
+msgctxt "field:sale.opportunity_employee_monthly,converted:"
+msgid "Converted"
+msgstr "Convertides"
+
+msgctxt "field:sale.opportunity_employee_monthly,converted_amount:"
+msgid "Converted Amount"
+msgstr "Import convertides"
+
+msgctxt "field:sale.opportunity_employee_monthly,currency:"
+msgid "Currency"
+msgstr "Moneda"
+
+msgctxt "field:sale.opportunity_employee_monthly,currency_digits:"
+msgid "Currency Digits"
+msgstr "Decimals de la moneda"
+
+msgctxt "field:sale.opportunity_employee_monthly,employee:"
+msgid "Employee"
+msgstr "Empleat"
+
+msgctxt "field:sale.opportunity_employee_monthly,lost:"
+msgid "Lost"
+msgstr "Perdudes"
+
+msgctxt "field:sale.opportunity_employee_monthly,month:"
+msgid "Month"
+msgstr "Mes"
+
+msgctxt "field:sale.opportunity_employee_monthly,number:"
+msgid "Number"
+msgstr "Número"
+
+msgctxt "field:sale.opportunity_employee_monthly,winning_amount_rate:"
+msgid "Winning Amount Rate"
+msgstr "Percentatge guanyades (sobre import)"
+
+msgctxt "field:sale.opportunity_employee_monthly,winning_rate:"
+msgid "Winning Rate"
+msgstr "Percentatge guanyades"
+
+msgctxt "field:sale.opportunity_employee_monthly,won:"
+msgid "Won"
+msgstr "Guanyades"
+
+msgctxt "field:sale.opportunity_employee_monthly,won_amount:"
+msgid "Won Amount"
+msgstr "Import guanyades"
+
+msgctxt "field:sale.opportunity_employee_monthly,year:"
+msgid "Year"
+msgstr "Any"
+
+msgctxt "field:sale.opportunity_monthly,amount:"
+msgid "Amount"
+msgstr "Import"
+
+msgctxt "field:sale.opportunity_monthly,company:"
+msgid "Company"
+msgstr "Empresa"
+
+msgctxt "field:sale.opportunity_monthly,conversion_amount_rate:"
+msgid "Conversion Amount Rate"
+msgstr "Percentatge convertides (sobre import)"
+
+msgctxt "field:sale.opportunity_monthly,conversion_rate:"
+msgid "Conversion Rate"
+msgstr "Percentatge convertides"
+
+msgctxt "field:sale.opportunity_monthly,converted:"
+msgid "Converted"
+msgstr "Convertides"
+
+msgctxt "field:sale.opportunity_monthly,converted_amount:"
+msgid "Converted Amount"
+msgstr "Import convertides"
+
+msgctxt "field:sale.opportunity_monthly,currency:"
+msgid "Currency"
+msgstr "Moneda"
+
+msgctxt "field:sale.opportunity_monthly,currency_digits:"
+msgid "Currency Digits"
+msgstr "Decimals de la moneda"
+
+msgctxt "field:sale.opportunity_monthly,lost:"
+msgid "Lost"
+msgstr "Perdudes"
+
+msgctxt "field:sale.opportunity_monthly,month:"
+msgid "Month"
+msgstr "Mes"
+
+msgctxt "field:sale.opportunity_monthly,number:"
+msgid "Number"
+msgstr "Número"
+
+msgctxt "field:sale.opportunity_monthly,winning_amount_rate:"
+msgid "Winning Amount Rate"
+msgstr "Percentatge guanyades (sobre import)"
+
+msgctxt "field:sale.opportunity_monthly,winning_rate:"
+msgid "Winning Rate"
+msgstr "Percentatge guanyades"
+
+msgctxt "field:sale.opportunity_monthly,won:"
+msgid "Won"
+msgstr "Guanyades"
+
+msgctxt "field:sale.opportunity_monthly,won_amount:"
+msgid "Won Amount"
+msgstr "Import guanyades"
+
+msgctxt "field:sale.opportunity_monthly,year:"
+msgid "Year"
+msgstr "Any"
+
+msgctxt "field:sale.opportunity_monthly,year_month:"
+msgid "Year-Month"
+msgstr "Any-Mes"
+
+msgctxt "help:sale.opportunity,amount:"
+msgid "Estimated revenue amount."
+msgstr "Import estimat d'ingressos."
+
+msgctxt "help:sale.opportunity,conversion_probability:"
+msgid "Percentage between 0 and 100."
+msgstr "Percentatge entre 0 i 100."
+
+msgctxt "model:ir.action,name:act_open_sale_form"
+msgid "Sales"
+msgstr "Vendes"
+
+msgctxt "model:ir.action,name:act_opportunity_employee_form"
+msgid "Opportunities per Employee"
+msgstr "Oportunitats per empleat"
+
+msgctxt "model:ir.action,name:act_opportunity_employee_monthly_form"
+msgid "Opportunities per Employee per Month"
+msgstr "Oportunitats per empleat i mes"
+
+msgctxt "model:ir.action,name:act_opportunity_form"
+msgid "Leads and Opportunities"
+msgstr "Iniciatives i oportunitats"
+
+msgctxt "model:ir.action,name:act_opportunity_form2"
+msgid "Sales Leads/Opportunities"
+msgstr "Iniciatives/Oportunitats"
+
+msgctxt "model:ir.action,name:act_opportunity_monthly_form"
+msgid "Opportunities per Month"
+msgstr "Oportunitats per mes"
+
+msgctxt ""
+"model:ir.action.act_window.domain,name:act_opportunity_form_domain_all"
+msgid "All"
+msgstr "Tot"
+
+msgctxt ""
+"model:ir.action.act_window.domain,name:act_opportunity_form_domain_cancelled"
+msgid "Cancelled"
+msgstr "Cancel·lada"
+
+msgctxt ""
+"model:ir.action.act_window.domain,name:act_opportunity_form_domain_converted"
+msgid "Converted"
+msgstr "Convertida"
+
+msgctxt ""
+"model:ir.action.act_window.domain,name:act_opportunity_form_domain_leads"
+msgid "Leads"
+msgstr "Iniciativa"
+
+msgctxt ""
+"model:ir.action.act_window.domain,name:act_opportunity_form_domain_lost"
+msgid "Lost"
+msgstr "Perduda"
+
+msgctxt ""
+"model:ir.action.act_window.domain,name:act_opportunity_form_domain_opportunities"
+msgid "Opportunities"
+msgstr "Oportunitats"
+
+msgctxt ""
+"model:ir.action.act_window.domain,name:act_opportunity_form_domain_won"
+msgid "Won"
+msgstr "Guanyada"
+
+msgctxt "model:ir.message,text:msg_modify_origin_opportunity"
+msgid "You cannot modify the opportunity origin of the sale \"%(sale)s\"."
+msgstr "No es pot modificar la oportunitat orígen de la venda \"%(sale)s\"."
+
+msgctxt "model:ir.message,text:msg_opportunity_delete_cancel"
+msgid "To delete opportunity \"%(opportunity)s\", you must cancel it."
+msgstr ""
+"Heu de cancel·lar l'oportunitat \"%(opportunity)s\" per poder-la eliminar."
+
+msgctxt "model:ir.model.button,string:opportunity_cancel_button"
+msgid "Cancel"
+msgstr "Cancel·la"
+
+msgctxt "model:ir.model.button,string:opportunity_convert_button"
+msgid "Convert to Sale"
+msgstr "Converteix a venda"
+
+msgctxt "model:ir.model.button,string:opportunity_lead_button"
+msgid "Set as Lead"
+msgstr "Convertir a iniciativa"
+
+msgctxt "model:ir.model.button,string:opportunity_lost_button"
+msgid "Mark as Lost"
+msgstr "Marca com a perduda"
+
+msgctxt "model:ir.model.button,string:opportunity_opportunity_button"
+msgid "Convert to Opportunity"
+msgstr "Converteix a oportunitat"
+
+msgctxt "model:ir.rule.group,name:rule_group_opportunity_companies"
+msgid "User in companies"
+msgstr "Usuari a les empreses"
+
+msgctxt "model:ir.rule.group,name:rule_group_opportunity_employee_companies"
+msgid "User in companies"
+msgstr "Usuari a les empreses"
+
+msgctxt ""
+"model:ir.rule.group,name:rule_group_opportunity_employee_monthly_companies"
+msgid "User in companies"
+msgstr "Usuari a les empreses"
+
+msgctxt "model:ir.rule.group,name:rule_group_opportunity_monthly_companies"
+msgid "User in companies"
+msgstr "Usuari a les empreses"
+
+msgctxt "model:ir.sequence,name:sequence_sale_opportunity"
+msgid "Sale Opportunity"
+msgstr "Oportunitat"
+
+msgctxt "model:ir.sequence.type,name:sequence_type_sale_opportunity"
+msgid "Sale Opportunity"
+msgstr "Oportunitat"
+
+msgctxt "model:ir.ui.menu,name:menu_opportunity_employee_monthly_form"
+msgid "Opportunities per Employee per Month"
+msgstr "Oportunitats per empleat i mes"
+
+msgctxt "model:ir.ui.menu,name:menu_opportunity_employee_open"
+msgid "Opportunities per Employee"
+msgstr "Oportunitats per empleat"
+
+msgctxt "model:ir.ui.menu,name:menu_opportunity_form"
+msgid "Leads and Opportunities"
+msgstr "Iniciatives i oportunitats"
+
+msgctxt "model:ir.ui.menu,name:menu_opportunity_monthly_form"
+msgid "Opportunities per Month"
+msgstr "Oportunitats per mes"
+
+msgctxt "model:res.group,name:group_opportunity"
+msgid "Sale Opportunity"
+msgstr "Iniciatives i oportunitats"
+
+msgctxt "model:sale.opportunity,name:"
+msgid "Sale Opportunity"
+msgstr "Oportunitat"
+
+msgctxt "model:sale.opportunity.line,name:"
+msgid "Sale Opportunity Line"
+msgstr "Línia d'oportunitat"
+
+msgctxt "model:sale.opportunity_employee,name:"
+msgid "Sale Opportunity per Employee"
+msgstr "Oportunitats per empleat"
+
+msgctxt "model:sale.opportunity_employee.context,name:"
+msgid "Sale Opportunity per Employee Context"
+msgstr "Context oportunitats per empleat i mes"
+
+msgctxt "model:sale.opportunity_employee_monthly,name:"
+msgid "Sale Opportunity per Employee per Month"
+msgstr "Oportunitats per empleat i mes"
+
+msgctxt "model:sale.opportunity_monthly,name:"
+msgid "Sale Opportunity per Month"
+msgstr "Oportunitats per mes"
+
+msgctxt "selection:sale.opportunity,state:"
+msgid "Cancelled"
+msgstr "Cancel·lada"
+
+msgctxt "selection:sale.opportunity,state:"
+msgid "Converted"
+msgstr "Convertida"
+
+msgctxt "selection:sale.opportunity,state:"
+msgid "Lead"
+msgstr "Iniciativa"
+
+msgctxt "selection:sale.opportunity,state:"
+msgid "Lost"
+msgstr "Perduda"
+
+msgctxt "selection:sale.opportunity,state:"
+msgid "Opportunity"
+msgstr "Oportunitat"
+
+msgctxt "selection:sale.opportunity,state:"
+msgid "Won"
+msgstr "Guanyat"
+
+msgctxt "view:sale.opportunity:"
+msgid "%"
+msgstr "%"
+
+msgctxt "view:sale.opportunity:"
+msgid "Lead/Opportunity"
+msgstr "Iniciativa/Oportunitat"
+
+msgctxt "view:sale.opportunity_employee:"
+msgid "%"
+msgstr "%"
+
+msgctxt "view:sale.opportunity_employee_monthly:"
+msgid "%"
+msgstr "%"
+
+msgctxt "view:sale.opportunity_monthly:"
+msgid "%"
+msgstr "%"
diff --git a/modules/sale_opportunity/locale/cs.po b/modules/sale_opportunity/locale/cs.po
new file mode 100644
index 0000000000..9e7d8d7f64
--- /dev/null
+++ b/modules/sale_opportunity/locale/cs.po
@@ -0,0 +1,560 @@
+#
+msgid ""
+msgstr "Content-Type: text/plain; charset=utf-8\n"
+
+msgctxt "field:sale.configuration,sale_opportunity_sequence:"
+msgid "Opportunity Sequence"
+msgstr ""
+
+msgctxt "field:sale.configuration.sequence,sale_opportunity_sequence:"
+msgid "Opportunity Sequence"
+msgstr ""
+
+msgctxt "field:sale.opportunity,address:"
+msgid "Address"
+msgstr ""
+
+msgctxt "field:sale.opportunity,amount:"
+msgid "Amount"
+msgstr ""
+
+msgctxt "field:sale.opportunity,comment:"
+msgid "Comment"
+msgstr ""
+
+msgctxt "field:sale.opportunity,company:"
+msgid "Company"
+msgstr ""
+
+msgctxt "field:sale.opportunity,contact:"
+msgid "Contact"
+msgstr ""
+
+msgctxt "field:sale.opportunity,conversion_probability:"
+msgid "Conversion Probability"
+msgstr ""
+
+#, fuzzy
+msgctxt "field:sale.opportunity,converted_by:"
+msgid "Converted By"
+msgstr "Converted"
+
+msgctxt "field:sale.opportunity,currency:"
+msgid "Currency"
+msgstr ""
+
+msgctxt "field:sale.opportunity,currency_digits:"
+msgid "Currency Digits"
+msgstr ""
+
+msgctxt "field:sale.opportunity,description:"
+msgid "Description"
+msgstr ""
+
+msgctxt "field:sale.opportunity,employee:"
+msgid "Employee"
+msgstr ""
+
+msgctxt "field:sale.opportunity,end_date:"
+msgid "End Date"
+msgstr ""
+
+msgctxt "field:sale.opportunity,lines:"
+msgid "Lines"
+msgstr ""
+
+msgctxt "field:sale.opportunity,lost_reason:"
+msgid "Reason for loss"
+msgstr ""
+
+msgctxt "field:sale.opportunity,number:"
+msgid "Number"
+msgstr ""
+
+msgctxt "field:sale.opportunity,party:"
+msgid "Party"
+msgstr ""
+
+msgctxt "field:sale.opportunity,payment_term:"
+msgid "Payment Term"
+msgstr ""
+
+msgctxt "field:sale.opportunity,reference:"
+msgid "Reference"
+msgstr ""
+
+#, fuzzy
+msgctxt "field:sale.opportunity,sales:"
+msgid "Sales"
+msgstr "Sales"
+
+msgctxt "field:sale.opportunity,start_date:"
+msgid "Start Date"
+msgstr ""
+
+msgctxt "field:sale.opportunity,state:"
+msgid "State"
+msgstr ""
+
+#, fuzzy
+msgctxt "field:sale.opportunity.line,opportunity:"
+msgid "Opportunity"
+msgstr "Opportunities"
+
+msgctxt "field:sale.opportunity.line,opportunity_state:"
+msgid "Opportunity State"
+msgstr ""
+
+msgctxt "field:sale.opportunity.line,product:"
+msgid "Product"
+msgstr ""
+
+msgctxt "field:sale.opportunity.line,quantity:"
+msgid "Quantity"
+msgstr ""
+
+msgctxt "field:sale.opportunity.line,unit:"
+msgid "Unit"
+msgstr ""
+
+msgctxt "field:sale.opportunity.line,unit_digits:"
+msgid "Unit Digits"
+msgstr ""
+
+msgctxt "field:sale.opportunity_employee,amount:"
+msgid "Amount"
+msgstr ""
+
+msgctxt "field:sale.opportunity_employee,company:"
+msgid "Company"
+msgstr ""
+
+msgctxt "field:sale.opportunity_employee,conversion_amount_rate:"
+msgid "Conversion Amount Rate"
+msgstr ""
+
+msgctxt "field:sale.opportunity_employee,conversion_rate:"
+msgid "Conversion Rate"
+msgstr ""
+
+#, fuzzy
+msgctxt "field:sale.opportunity_employee,converted:"
+msgid "Converted"
+msgstr "Converted"
+
+msgctxt "field:sale.opportunity_employee,converted_amount:"
+msgid "Converted Amount"
+msgstr ""
+
+msgctxt "field:sale.opportunity_employee,currency:"
+msgid "Currency"
+msgstr ""
+
+msgctxt "field:sale.opportunity_employee,currency_digits:"
+msgid "Currency Digits"
+msgstr ""
+
+msgctxt "field:sale.opportunity_employee,employee:"
+msgid "Employee"
+msgstr ""
+
+#, fuzzy
+msgctxt "field:sale.opportunity_employee,lost:"
+msgid "Lost"
+msgstr "Lost"
+
+msgctxt "field:sale.opportunity_employee,number:"
+msgid "Number"
+msgstr ""
+
+msgctxt "field:sale.opportunity_employee,winning_amount_rate:"
+msgid "Winning Amount Rate"
+msgstr ""
+
+msgctxt "field:sale.opportunity_employee,winning_rate:"
+msgid "Winning Rate"
+msgstr ""
+
+#, fuzzy
+msgctxt "field:sale.opportunity_employee,won:"
+msgid "Won"
+msgstr "Won"
+
+msgctxt "field:sale.opportunity_employee,won_amount:"
+msgid "Won Amount"
+msgstr ""
+
+msgctxt "field:sale.opportunity_employee.context,end_date:"
+msgid "End Date"
+msgstr ""
+
+msgctxt "field:sale.opportunity_employee.context,start_date:"
+msgid "Start Date"
+msgstr ""
+
+msgctxt "field:sale.opportunity_employee_monthly,amount:"
+msgid "Amount"
+msgstr ""
+
+msgctxt "field:sale.opportunity_employee_monthly,company:"
+msgid "Company"
+msgstr ""
+
+msgctxt "field:sale.opportunity_employee_monthly,conversion_amount_rate:"
+msgid "Conversion Amount Rate"
+msgstr ""
+
+msgctxt "field:sale.opportunity_employee_monthly,conversion_rate:"
+msgid "Conversion Rate"
+msgstr ""
+
+#, fuzzy
+msgctxt "field:sale.opportunity_employee_monthly,converted:"
+msgid "Converted"
+msgstr "Converted"
+
+msgctxt "field:sale.opportunity_employee_monthly,converted_amount:"
+msgid "Converted Amount"
+msgstr ""
+
+msgctxt "field:sale.opportunity_employee_monthly,currency:"
+msgid "Currency"
+msgstr ""
+
+msgctxt "field:sale.opportunity_employee_monthly,currency_digits:"
+msgid "Currency Digits"
+msgstr ""
+
+msgctxt "field:sale.opportunity_employee_monthly,employee:"
+msgid "Employee"
+msgstr ""
+
+#, fuzzy
+msgctxt "field:sale.opportunity_employee_monthly,lost:"
+msgid "Lost"
+msgstr "Lost"
+
+msgctxt "field:sale.opportunity_employee_monthly,month:"
+msgid "Month"
+msgstr ""
+
+msgctxt "field:sale.opportunity_employee_monthly,number:"
+msgid "Number"
+msgstr ""
+
+msgctxt "field:sale.opportunity_employee_monthly,winning_amount_rate:"
+msgid "Winning Amount Rate"
+msgstr ""
+
+msgctxt "field:sale.opportunity_employee_monthly,winning_rate:"
+msgid "Winning Rate"
+msgstr ""
+
+#, fuzzy
+msgctxt "field:sale.opportunity_employee_monthly,won:"
+msgid "Won"
+msgstr "Won"
+
+msgctxt "field:sale.opportunity_employee_monthly,won_amount:"
+msgid "Won Amount"
+msgstr ""
+
+msgctxt "field:sale.opportunity_employee_monthly,year:"
+msgid "Year"
+msgstr ""
+
+msgctxt "field:sale.opportunity_monthly,amount:"
+msgid "Amount"
+msgstr ""
+
+msgctxt "field:sale.opportunity_monthly,company:"
+msgid "Company"
+msgstr ""
+
+msgctxt "field:sale.opportunity_monthly,conversion_amount_rate:"
+msgid "Conversion Amount Rate"
+msgstr ""
+
+msgctxt "field:sale.opportunity_monthly,conversion_rate:"
+msgid "Conversion Rate"
+msgstr ""
+
+#, fuzzy
+msgctxt "field:sale.opportunity_monthly,converted:"
+msgid "Converted"
+msgstr "Converted"
+
+msgctxt "field:sale.opportunity_monthly,converted_amount:"
+msgid "Converted Amount"
+msgstr ""
+
+msgctxt "field:sale.opportunity_monthly,currency:"
+msgid "Currency"
+msgstr ""
+
+msgctxt "field:sale.opportunity_monthly,currency_digits:"
+msgid "Currency Digits"
+msgstr ""
+
+#, fuzzy
+msgctxt "field:sale.opportunity_monthly,lost:"
+msgid "Lost"
+msgstr "Lost"
+
+msgctxt "field:sale.opportunity_monthly,month:"
+msgid "Month"
+msgstr ""
+
+msgctxt "field:sale.opportunity_monthly,number:"
+msgid "Number"
+msgstr ""
+
+msgctxt "field:sale.opportunity_monthly,winning_amount_rate:"
+msgid "Winning Amount Rate"
+msgstr ""
+
+msgctxt "field:sale.opportunity_monthly,winning_rate:"
+msgid "Winning Rate"
+msgstr ""
+
+#, fuzzy
+msgctxt "field:sale.opportunity_monthly,won:"
+msgid "Won"
+msgstr "Won"
+
+msgctxt "field:sale.opportunity_monthly,won_amount:"
+msgid "Won Amount"
+msgstr ""
+
+msgctxt "field:sale.opportunity_monthly,year:"
+msgid "Year"
+msgstr ""
+
+msgctxt "field:sale.opportunity_monthly,year_month:"
+msgid "Year-Month"
+msgstr ""
+
+msgctxt "help:sale.opportunity,amount:"
+msgid "Estimated revenue amount."
+msgstr ""
+
+msgctxt "help:sale.opportunity,conversion_probability:"
+msgid "Percentage between 0 and 100."
+msgstr ""
+
+msgctxt "model:ir.action,name:act_open_sale_form"
+msgid "Sales"
+msgstr "Sales"
+
+msgctxt "model:ir.action,name:act_opportunity_employee_form"
+msgid "Opportunities per Employee"
+msgstr "Opportunities per Employee"
+
+msgctxt "model:ir.action,name:act_opportunity_employee_monthly_form"
+msgid "Opportunities per Employee per Month"
+msgstr "Opportunities per Employee per Month"
+
+msgctxt "model:ir.action,name:act_opportunity_form"
+msgid "Leads and Opportunities"
+msgstr "Leads and Opportunities"
+
+msgctxt "model:ir.action,name:act_opportunity_form2"
+msgid "Sales Leads/Opportunities"
+msgstr "Sales Leads/Opportunities"
+
+msgctxt "model:ir.action,name:act_opportunity_monthly_form"
+msgid "Opportunities per Month"
+msgstr "Opportunities per Month"
+
+msgctxt ""
+"model:ir.action.act_window.domain,name:act_opportunity_form_domain_all"
+msgid "All"
+msgstr "All"
+
+msgctxt ""
+"model:ir.action.act_window.domain,name:act_opportunity_form_domain_cancelled"
+msgid "Cancelled"
+msgstr "Cancelled"
+
+msgctxt ""
+"model:ir.action.act_window.domain,name:act_opportunity_form_domain_converted"
+msgid "Converted"
+msgstr "Converted"
+
+msgctxt ""
+"model:ir.action.act_window.domain,name:act_opportunity_form_domain_leads"
+msgid "Leads"
+msgstr "Leads"
+
+msgctxt ""
+"model:ir.action.act_window.domain,name:act_opportunity_form_domain_lost"
+msgid "Lost"
+msgstr "Lost"
+
+msgctxt ""
+"model:ir.action.act_window.domain,name:act_opportunity_form_domain_opportunities"
+msgid "Opportunities"
+msgstr "Opportunities"
+
+#, fuzzy
+msgctxt ""
+"model:ir.action.act_window.domain,name:act_opportunity_form_domain_won"
+msgid "Won"
+msgstr "Won"
+
+msgctxt "model:ir.message,text:msg_modify_origin_opportunity"
+msgid "You cannot modify the opportunity origin of the sale \"%(sale)s\"."
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_opportunity_delete_cancel"
+msgid "To delete opportunity \"%(opportunity)s\", you must cancel it."
+msgstr ""
+
+msgctxt "model:ir.model.button,string:opportunity_cancel_button"
+msgid "Cancel"
+msgstr "Cancel"
+
+msgctxt "model:ir.model.button,string:opportunity_convert_button"
+msgid "Convert to Sale"
+msgstr "Convert to Sale"
+
+msgctxt "model:ir.model.button,string:opportunity_lead_button"
+msgid "Set as Lead"
+msgstr "Set as Lead"
+
+msgctxt "model:ir.model.button,string:opportunity_lost_button"
+msgid "Mark as Lost"
+msgstr "Mark as Lost"
+
+msgctxt "model:ir.model.button,string:opportunity_opportunity_button"
+msgid "Convert to Opportunity"
+msgstr "Convert to Opportunity"
+
+msgctxt "model:ir.rule.group,name:rule_group_opportunity_companies"
+msgid "User in companies"
+msgstr ""
+
+msgctxt "model:ir.rule.group,name:rule_group_opportunity_employee_companies"
+msgid "User in companies"
+msgstr ""
+
+msgctxt ""
+"model:ir.rule.group,name:rule_group_opportunity_employee_monthly_companies"
+msgid "User in companies"
+msgstr ""
+
+msgctxt "model:ir.rule.group,name:rule_group_opportunity_monthly_companies"
+msgid "User in companies"
+msgstr ""
+
+msgctxt "model:ir.sequence,name:sequence_sale_opportunity"
+msgid "Sale Opportunity"
+msgstr "Sale Opportunity"
+
+msgctxt "model:ir.sequence.type,name:sequence_type_sale_opportunity"
+msgid "Sale Opportunity"
+msgstr "Sale Opportunity"
+
+msgctxt "model:ir.ui.menu,name:menu_opportunity_employee_monthly_form"
+msgid "Opportunities per Employee per Month"
+msgstr "Opportunities per Employee per Month"
+
+msgctxt "model:ir.ui.menu,name:menu_opportunity_employee_open"
+msgid "Opportunities per Employee"
+msgstr "Opportunities per Employee"
+
+msgctxt "model:ir.ui.menu,name:menu_opportunity_form"
+msgid "Leads and Opportunities"
+msgstr "Leads and Opportunities"
+
+msgctxt "model:ir.ui.menu,name:menu_opportunity_monthly_form"
+msgid "Opportunities per Month"
+msgstr "Opportunities per Month"
+
+msgctxt "model:res.group,name:group_opportunity"
+msgid "Sale Opportunity"
+msgstr "Sale Opportunity"
+
+#, fuzzy
+msgctxt "model:sale.opportunity,name:"
+msgid "Sale Opportunity"
+msgstr "Sale Opportunity"
+
+#, fuzzy
+msgctxt "model:sale.opportunity.line,name:"
+msgid "Sale Opportunity Line"
+msgstr "Sale Opportunity"
+
+#, fuzzy
+msgctxt "model:sale.opportunity_employee,name:"
+msgid "Sale Opportunity per Employee"
+msgstr "Opportunities per Employee per Month"
+
+#, fuzzy
+msgctxt "model:sale.opportunity_employee.context,name:"
+msgid "Sale Opportunity per Employee Context"
+msgstr "Opportunities per Employee per Month"
+
+#, fuzzy
+msgctxt "model:sale.opportunity_employee_monthly,name:"
+msgid "Sale Opportunity per Employee per Month"
+msgstr "Opportunities per Employee per Month"
+
+#, fuzzy
+msgctxt "model:sale.opportunity_monthly,name:"
+msgid "Sale Opportunity per Month"
+msgstr "Opportunities per Employee per Month"
+
+#, fuzzy
+msgctxt "selection:sale.opportunity,state:"
+msgid "Cancelled"
+msgstr "Cancelled"
+
+#, fuzzy
+msgctxt "selection:sale.opportunity,state:"
+msgid "Converted"
+msgstr "Converted"
+
+#, fuzzy
+msgctxt "selection:sale.opportunity,state:"
+msgid "Lead"
+msgstr "Leads"
+
+#, fuzzy
+msgctxt "selection:sale.opportunity,state:"
+msgid "Lost"
+msgstr "Lost"
+
+#, fuzzy
+msgctxt "selection:sale.opportunity,state:"
+msgid "Opportunity"
+msgstr "Opportunities"
+
+#, fuzzy
+msgctxt "selection:sale.opportunity,state:"
+msgid "Won"
+msgstr "Won"
+
+#, fuzzy
+msgctxt "view:sale.opportunity:"
+msgid "%"
+msgstr "%"
+
+msgctxt "view:sale.opportunity:"
+msgid "Lead/Opportunity"
+msgstr ""
+
+#, fuzzy
+msgctxt "view:sale.opportunity_employee:"
+msgid "%"
+msgstr "%"
+
+#, fuzzy
+msgctxt "view:sale.opportunity_employee_monthly:"
+msgid "%"
+msgstr "%"
+
+#, fuzzy
+msgctxt "view:sale.opportunity_monthly:"
+msgid "%"
+msgstr "%"
diff --git a/modules/sale_opportunity/locale/de.po b/modules/sale_opportunity/locale/de.po
new file mode 100644
index 0000000000..aea613dfad
--- /dev/null
+++ b/modules/sale_opportunity/locale/de.po
@@ -0,0 +1,535 @@
+#
+msgid ""
+msgstr "Content-Type: text/plain; charset=utf-8\n"
+
+msgctxt "field:sale.configuration,sale_opportunity_sequence:"
+msgid "Opportunity Sequence"
+msgstr "Nummernkreis Verkaufschance"
+
+msgctxt "field:sale.configuration.sequence,sale_opportunity_sequence:"
+msgid "Opportunity Sequence"
+msgstr "Nummernkreis Verkaufschance"
+
+msgctxt "field:sale.opportunity,address:"
+msgid "Address"
+msgstr "Adresse"
+
+msgctxt "field:sale.opportunity,amount:"
+msgid "Amount"
+msgstr "Betrag"
+
+msgctxt "field:sale.opportunity,comment:"
+msgid "Comment"
+msgstr "Kommentar"
+
+msgctxt "field:sale.opportunity,company:"
+msgid "Company"
+msgstr "Unternehmen"
+
+msgctxt "field:sale.opportunity,contact:"
+msgid "Contact"
+msgstr "Kontakt"
+
+msgctxt "field:sale.opportunity,conversion_probability:"
+msgid "Conversion Probability"
+msgstr "Umwandlungswahrscheinlichkeit"
+
+msgctxt "field:sale.opportunity,converted_by:"
+msgid "Converted By"
+msgstr "Umgewandelt von"
+
+msgctxt "field:sale.opportunity,currency:"
+msgid "Currency"
+msgstr "Währung"
+
+msgctxt "field:sale.opportunity,currency_digits:"
+msgid "Currency Digits"
+msgstr "Nachkommastellen Währung"
+
+msgctxt "field:sale.opportunity,description:"
+msgid "Description"
+msgstr "Beschreibung"
+
+msgctxt "field:sale.opportunity,employee:"
+msgid "Employee"
+msgstr "Mitarbeiter"
+
+msgctxt "field:sale.opportunity,end_date:"
+msgid "End Date"
+msgstr "Enddatum"
+
+msgctxt "field:sale.opportunity,lines:"
+msgid "Lines"
+msgstr "Positionen"
+
+msgctxt "field:sale.opportunity,lost_reason:"
+msgid "Reason for loss"
+msgstr "Ursache für Verlust"
+
+msgctxt "field:sale.opportunity,number:"
+msgid "Number"
+msgstr "Nummer"
+
+msgctxt "field:sale.opportunity,party:"
+msgid "Party"
+msgstr "Partei"
+
+msgctxt "field:sale.opportunity,payment_term:"
+msgid "Payment Term"
+msgstr "Zahlungsbedingung"
+
+msgctxt "field:sale.opportunity,reference:"
+msgid "Reference"
+msgstr "Referenz"
+
+msgctxt "field:sale.opportunity,sales:"
+msgid "Sales"
+msgstr "Verkäufe"
+
+msgctxt "field:sale.opportunity,start_date:"
+msgid "Start Date"
+msgstr "Startdatum"
+
+msgctxt "field:sale.opportunity,state:"
+msgid "State"
+msgstr "Status"
+
+msgctxt "field:sale.opportunity.line,opportunity:"
+msgid "Opportunity"
+msgstr "Verkaufschance"
+
+msgctxt "field:sale.opportunity.line,opportunity_state:"
+msgid "Opportunity State"
+msgstr "Status Verkaufschance"
+
+msgctxt "field:sale.opportunity.line,product:"
+msgid "Product"
+msgstr "Artikel"
+
+msgctxt "field:sale.opportunity.line,quantity:"
+msgid "Quantity"
+msgstr "Menge"
+
+msgctxt "field:sale.opportunity.line,unit:"
+msgid "Unit"
+msgstr "Einheit"
+
+msgctxt "field:sale.opportunity.line,unit_digits:"
+msgid "Unit Digits"
+msgstr "Nachkommastellen"
+
+msgctxt "field:sale.opportunity_employee,amount:"
+msgid "Amount"
+msgstr "Betrag"
+
+msgctxt "field:sale.opportunity_employee,company:"
+msgid "Company"
+msgstr "Unternehmen"
+
+msgctxt "field:sale.opportunity_employee,conversion_amount_rate:"
+msgid "Conversion Amount Rate"
+msgstr "Umwandlungsrate Betrag"
+
+msgctxt "field:sale.opportunity_employee,conversion_rate:"
+msgid "Conversion Rate"
+msgstr "Umwandlungsrate"
+
+msgctxt "field:sale.opportunity_employee,converted:"
+msgid "Converted"
+msgstr "Umgewandelt"
+
+msgctxt "field:sale.opportunity_employee,converted_amount:"
+msgid "Converted Amount"
+msgstr "Umgewandelter Betrag"
+
+msgctxt "field:sale.opportunity_employee,currency:"
+msgid "Currency"
+msgstr "Währung"
+
+msgctxt "field:sale.opportunity_employee,currency_digits:"
+msgid "Currency Digits"
+msgstr "Nachkommastellen Währung"
+
+msgctxt "field:sale.opportunity_employee,employee:"
+msgid "Employee"
+msgstr "Mitarbeiter"
+
+msgctxt "field:sale.opportunity_employee,lost:"
+msgid "Lost"
+msgstr "Verlust"
+
+msgctxt "field:sale.opportunity_employee,number:"
+msgid "Number"
+msgstr "Anzahl"
+
+msgctxt "field:sale.opportunity_employee,winning_amount_rate:"
+msgid "Winning Amount Rate"
+msgstr "Prozentsatz gewonnener Betrag"
+
+msgctxt "field:sale.opportunity_employee,winning_rate:"
+msgid "Winning Rate"
+msgstr "Prozentsatz gewonnen"
+
+msgctxt "field:sale.opportunity_employee,won:"
+msgid "Won"
+msgstr "Gewonnen"
+
+msgctxt "field:sale.opportunity_employee,won_amount:"
+msgid "Won Amount"
+msgstr "Gewonnener Betrag"
+
+msgctxt "field:sale.opportunity_employee.context,end_date:"
+msgid "End Date"
+msgstr "Enddatum"
+
+msgctxt "field:sale.opportunity_employee.context,start_date:"
+msgid "Start Date"
+msgstr "Startdatum"
+
+msgctxt "field:sale.opportunity_employee_monthly,amount:"
+msgid "Amount"
+msgstr "Betrag"
+
+msgctxt "field:sale.opportunity_employee_monthly,company:"
+msgid "Company"
+msgstr "Unternehmen"
+
+msgctxt "field:sale.opportunity_employee_monthly,conversion_amount_rate:"
+msgid "Conversion Amount Rate"
+msgstr "Umwandlungsrate Betrag"
+
+msgctxt "field:sale.opportunity_employee_monthly,conversion_rate:"
+msgid "Conversion Rate"
+msgstr "Umwandlungsrate"
+
+msgctxt "field:sale.opportunity_employee_monthly,converted:"
+msgid "Converted"
+msgstr "Umgewandelt"
+
+msgctxt "field:sale.opportunity_employee_monthly,converted_amount:"
+msgid "Converted Amount"
+msgstr "Umgewandelter Betrag"
+
+msgctxt "field:sale.opportunity_employee_monthly,currency:"
+msgid "Currency"
+msgstr "Währung"
+
+msgctxt "field:sale.opportunity_employee_monthly,currency_digits:"
+msgid "Currency Digits"
+msgstr "Nachkommastellen Währung"
+
+msgctxt "field:sale.opportunity_employee_monthly,employee:"
+msgid "Employee"
+msgstr "Mitarbeiter"
+
+msgctxt "field:sale.opportunity_employee_monthly,lost:"
+msgid "Lost"
+msgstr "Verlust"
+
+msgctxt "field:sale.opportunity_employee_monthly,month:"
+msgid "Month"
+msgstr "Monat"
+
+msgctxt "field:sale.opportunity_employee_monthly,number:"
+msgid "Number"
+msgstr "Anzahl"
+
+msgctxt "field:sale.opportunity_employee_monthly,winning_amount_rate:"
+msgid "Winning Amount Rate"
+msgstr "Prozentsatz gewonnener Betrag"
+
+msgctxt "field:sale.opportunity_employee_monthly,winning_rate:"
+msgid "Winning Rate"
+msgstr "Prozentsatz gewonnen"
+
+msgctxt "field:sale.opportunity_employee_monthly,won:"
+msgid "Won"
+msgstr "Gewonnen"
+
+msgctxt "field:sale.opportunity_employee_monthly,won_amount:"
+msgid "Won Amount"
+msgstr "Gewonnener Betrag"
+
+msgctxt "field:sale.opportunity_employee_monthly,year:"
+msgid "Year"
+msgstr "Jahr"
+
+msgctxt "field:sale.opportunity_monthly,amount:"
+msgid "Amount"
+msgstr "Betrag"
+
+msgctxt "field:sale.opportunity_monthly,company:"
+msgid "Company"
+msgstr "Unternehmen"
+
+msgctxt "field:sale.opportunity_monthly,conversion_amount_rate:"
+msgid "Conversion Amount Rate"
+msgstr "Umwandlungsrate Betrag"
+
+msgctxt "field:sale.opportunity_monthly,conversion_rate:"
+msgid "Conversion Rate"
+msgstr "Umwandlungsrate"
+
+msgctxt "field:sale.opportunity_monthly,converted:"
+msgid "Converted"
+msgstr "Umgewandelt"
+
+msgctxt "field:sale.opportunity_monthly,converted_amount:"
+msgid "Converted Amount"
+msgstr "Umgewandelter Betrag"
+
+msgctxt "field:sale.opportunity_monthly,currency:"
+msgid "Currency"
+msgstr "Währung"
+
+msgctxt "field:sale.opportunity_monthly,currency_digits:"
+msgid "Currency Digits"
+msgstr "Nachkommastellen Währung"
+
+msgctxt "field:sale.opportunity_monthly,lost:"
+msgid "Lost"
+msgstr "Verlust"
+
+msgctxt "field:sale.opportunity_monthly,month:"
+msgid "Month"
+msgstr "Monat"
+
+msgctxt "field:sale.opportunity_monthly,number:"
+msgid "Number"
+msgstr "Anzahl"
+
+msgctxt "field:sale.opportunity_monthly,winning_amount_rate:"
+msgid "Winning Amount Rate"
+msgstr "Prozentsatz gewonnener Betrag"
+
+msgctxt "field:sale.opportunity_monthly,winning_rate:"
+msgid "Winning Rate"
+msgstr "Prozentsatz gewonnen"
+
+msgctxt "field:sale.opportunity_monthly,won:"
+msgid "Won"
+msgstr "Gewonnen"
+
+msgctxt "field:sale.opportunity_monthly,won_amount:"
+msgid "Won Amount"
+msgstr "Gewonnener Betrag"
+
+msgctxt "field:sale.opportunity_monthly,year:"
+msgid "Year"
+msgstr "Jahr"
+
+msgctxt "field:sale.opportunity_monthly,year_month:"
+msgid "Year-Month"
+msgstr "Jahr-Monat"
+
+msgctxt "help:sale.opportunity,amount:"
+msgid "Estimated revenue amount."
+msgstr "Geschätzter Ertrag."
+
+msgctxt "help:sale.opportunity,conversion_probability:"
+msgid "Percentage between 0 and 100."
+msgstr "Prozentsatz zwischen 0 und 100."
+
+msgctxt "model:ir.action,name:act_open_sale_form"
+msgid "Sales"
+msgstr "Verkauf"
+
+msgctxt "model:ir.action,name:act_opportunity_employee_form"
+msgid "Opportunities per Employee"
+msgstr "Verkaufschancen pro Mitarbeiter"
+
+msgctxt "model:ir.action,name:act_opportunity_employee_monthly_form"
+msgid "Opportunities per Employee per Month"
+msgstr "Verkaufschancen pro Mitarbeiter pro Monat"
+
+msgctxt "model:ir.action,name:act_opportunity_form"
+msgid "Leads and Opportunities"
+msgstr "Interessenten und Verkaufschancen"
+
+msgctxt "model:ir.action,name:act_opportunity_form2"
+msgid "Sales Leads/Opportunities"
+msgstr "Interessenten/Verkaufschancen"
+
+msgctxt "model:ir.action,name:act_opportunity_monthly_form"
+msgid "Opportunities per Month"
+msgstr "Verkaufschancen pro Monat"
+
+msgctxt ""
+"model:ir.action.act_window.domain,name:act_opportunity_form_domain_all"
+msgid "All"
+msgstr "Alle"
+
+msgctxt ""
+"model:ir.action.act_window.domain,name:act_opportunity_form_domain_cancelled"
+msgid "Cancelled"
+msgstr "Annulliert"
+
+msgctxt ""
+"model:ir.action.act_window.domain,name:act_opportunity_form_domain_converted"
+msgid "Converted"
+msgstr "Umgewandelt"
+
+msgctxt ""
+"model:ir.action.act_window.domain,name:act_opportunity_form_domain_leads"
+msgid "Leads"
+msgstr "Interessenten"
+
+msgctxt ""
+"model:ir.action.act_window.domain,name:act_opportunity_form_domain_lost"
+msgid "Lost"
+msgstr "Verloren"
+
+msgctxt ""
+"model:ir.action.act_window.domain,name:act_opportunity_form_domain_opportunities"
+msgid "Opportunities"
+msgstr "Verkaufschancen"
+
+msgctxt ""
+"model:ir.action.act_window.domain,name:act_opportunity_form_domain_won"
+msgid "Won"
+msgstr "Gewonnen"
+
+msgctxt "model:ir.message,text:msg_modify_origin_opportunity"
+msgid "You cannot modify the opportunity origin of the sale \"%(sale)s\"."
+msgstr ""
+"Die Verkaufschancenherkunft von Verkauf \"%(sale)s\" kann nicht geändert "
+"werden."
+
+msgctxt "model:ir.message,text:msg_opportunity_delete_cancel"
+msgid "To delete opportunity \"%(opportunity)s\", you must cancel it."
+msgstr ""
+"Damit die Verkaufschance \"%(opportunity)s\" gelöscht werden kann, muss sie "
+"zuerst annulliert werden."
+
+msgctxt "model:ir.model.button,string:opportunity_cancel_button"
+msgid "Cancel"
+msgstr "Annullieren"
+
+msgctxt "model:ir.model.button,string:opportunity_convert_button"
+msgid "Convert to Sale"
+msgstr "In Verkauf umwandeln"
+
+msgctxt "model:ir.model.button,string:opportunity_lead_button"
+msgid "Set as Lead"
+msgstr "Auf Interessent setzen"
+
+msgctxt "model:ir.model.button,string:opportunity_lost_button"
+msgid "Mark as Lost"
+msgstr "Als Verlust markieren"
+
+msgctxt "model:ir.model.button,string:opportunity_opportunity_button"
+msgid "Convert to Opportunity"
+msgstr "In Verkaufschance umwandeln"
+
+msgctxt "model:ir.rule.group,name:rule_group_opportunity_companies"
+msgid "User in companies"
+msgstr "Benutzer im Unternehmen"
+
+msgctxt "model:ir.rule.group,name:rule_group_opportunity_employee_companies"
+msgid "User in companies"
+msgstr "Benutzer im Unternehmen"
+
+msgctxt ""
+"model:ir.rule.group,name:rule_group_opportunity_employee_monthly_companies"
+msgid "User in companies"
+msgstr "Benutzer im Unternehmen"
+
+msgctxt "model:ir.rule.group,name:rule_group_opportunity_monthly_companies"
+msgid "User in companies"
+msgstr "Benutzer im Unternehmen"
+
+msgctxt "model:ir.sequence,name:sequence_sale_opportunity"
+msgid "Sale Opportunity"
+msgstr "Verkaufschance"
+
+msgctxt "model:ir.sequence.type,name:sequence_type_sale_opportunity"
+msgid "Sale Opportunity"
+msgstr "Verkaufschance"
+
+msgctxt "model:ir.ui.menu,name:menu_opportunity_employee_monthly_form"
+msgid "Opportunities per Employee per Month"
+msgstr "Verkaufschancen pro Mitarbeiter pro Monat"
+
+msgctxt "model:ir.ui.menu,name:menu_opportunity_employee_open"
+msgid "Opportunities per Employee"
+msgstr "Verkaufschancen pro Mitarbeiter"
+
+msgctxt "model:ir.ui.menu,name:menu_opportunity_form"
+msgid "Leads and Opportunities"
+msgstr "Interessenten und Verkaufschancen"
+
+msgctxt "model:ir.ui.menu,name:menu_opportunity_monthly_form"
+msgid "Opportunities per Month"
+msgstr "Verkaufschancen pro Monat"
+
+msgctxt "model:res.group,name:group_opportunity"
+msgid "Sale Opportunity"
+msgstr "Verkaufschance"
+
+msgctxt "model:sale.opportunity,name:"
+msgid "Sale Opportunity"
+msgstr "Verkaufschance"
+
+msgctxt "model:sale.opportunity.line,name:"
+msgid "Sale Opportunity Line"
+msgstr "Verkaufschancenposition"
+
+msgctxt "model:sale.opportunity_employee,name:"
+msgid "Sale Opportunity per Employee"
+msgstr "Verkaufschance pro Mitarbeiter"
+
+msgctxt "model:sale.opportunity_employee.context,name:"
+msgid "Sale Opportunity per Employee Context"
+msgstr "Verkaufschance pro Mitarbeiter Kontext"
+
+msgctxt "model:sale.opportunity_employee_monthly,name:"
+msgid "Sale Opportunity per Employee per Month"
+msgstr "Verkaufschance pro Mitarbeiter pro Monat"
+
+msgctxt "model:sale.opportunity_monthly,name:"
+msgid "Sale Opportunity per Month"
+msgstr "Verkaufschance pro Monat"
+
+msgctxt "selection:sale.opportunity,state:"
+msgid "Cancelled"
+msgstr "Annulliert"
+
+msgctxt "selection:sale.opportunity,state:"
+msgid "Converted"
+msgstr "Umgewandelt"
+
+msgctxt "selection:sale.opportunity,state:"
+msgid "Lead"
+msgstr "Interessent"
+
+msgctxt "selection:sale.opportunity,state:"
+msgid "Lost"
+msgstr "Verlust"
+
+msgctxt "selection:sale.opportunity,state:"
+msgid "Opportunity"
+msgstr "Verkaufschance"
+
+msgctxt "selection:sale.opportunity,state:"
+msgid "Won"
+msgstr "Gewonnen"
+
+msgctxt "view:sale.opportunity:"
+msgid "%"
+msgstr "%"
+
+msgctxt "view:sale.opportunity:"
+msgid "Lead/Opportunity"
+msgstr "Interessent/Chance"
+
+msgctxt "view:sale.opportunity_employee:"
+msgid "%"
+msgstr "%"
+
+msgctxt "view:sale.opportunity_employee_monthly:"
+msgid "%"
+msgstr "%"
+
+msgctxt "view:sale.opportunity_monthly:"
+msgid "%"
+msgstr "%"
diff --git a/modules/sale_opportunity/locale/es.po b/modules/sale_opportunity/locale/es.po
new file mode 100644
index 0000000000..65eee8983a
--- /dev/null
+++ b/modules/sale_opportunity/locale/es.po
@@ -0,0 +1,531 @@
+#
+msgid ""
+msgstr "Content-Type: text/plain; charset=utf-8\n"
+
+msgctxt "field:sale.configuration,sale_opportunity_sequence:"
+msgid "Opportunity Sequence"
+msgstr "Secuencia de oportunidad"
+
+msgctxt "field:sale.configuration.sequence,sale_opportunity_sequence:"
+msgid "Opportunity Sequence"
+msgstr "Secuencia de oportunidad"
+
+msgctxt "field:sale.opportunity,address:"
+msgid "Address"
+msgstr "Dirección"
+
+msgctxt "field:sale.opportunity,amount:"
+msgid "Amount"
+msgstr "Importe"
+
+msgctxt "field:sale.opportunity,comment:"
+msgid "Comment"
+msgstr "Comentario"
+
+msgctxt "field:sale.opportunity,company:"
+msgid "Company"
+msgstr "Empresa"
+
+msgctxt "field:sale.opportunity,contact:"
+msgid "Contact"
+msgstr "Contacto"
+
+msgctxt "field:sale.opportunity,conversion_probability:"
+msgid "Conversion Probability"
+msgstr "Probabilidad de conversión"
+
+msgctxt "field:sale.opportunity,converted_by:"
+msgid "Converted By"
+msgstr "Convertida por"
+
+msgctxt "field:sale.opportunity,currency:"
+msgid "Currency"
+msgstr "Moneda"
+
+msgctxt "field:sale.opportunity,currency_digits:"
+msgid "Currency Digits"
+msgstr "Decimales de la moneda"
+
+msgctxt "field:sale.opportunity,description:"
+msgid "Description"
+msgstr "Descripción"
+
+msgctxt "field:sale.opportunity,employee:"
+msgid "Employee"
+msgstr "Empleado"
+
+msgctxt "field:sale.opportunity,end_date:"
+msgid "End Date"
+msgstr "Fecha final"
+
+msgctxt "field:sale.opportunity,lines:"
+msgid "Lines"
+msgstr "Líneas"
+
+msgctxt "field:sale.opportunity,lost_reason:"
+msgid "Reason for loss"
+msgstr "Motivos de la pérdida"
+
+msgctxt "field:sale.opportunity,number:"
+msgid "Number"
+msgstr "Número"
+
+msgctxt "field:sale.opportunity,party:"
+msgid "Party"
+msgstr "Tercero"
+
+msgctxt "field:sale.opportunity,payment_term:"
+msgid "Payment Term"
+msgstr "Plazo de pago"
+
+msgctxt "field:sale.opportunity,reference:"
+msgid "Reference"
+msgstr "Referencia"
+
+msgctxt "field:sale.opportunity,sales:"
+msgid "Sales"
+msgstr "Ventas"
+
+msgctxt "field:sale.opportunity,start_date:"
+msgid "Start Date"
+msgstr "Fecha inicial"
+
+msgctxt "field:sale.opportunity,state:"
+msgid "State"
+msgstr "Estado"
+
+msgctxt "field:sale.opportunity.line,opportunity:"
+msgid "Opportunity"
+msgstr "Oportunidad"
+
+msgctxt "field:sale.opportunity.line,opportunity_state:"
+msgid "Opportunity State"
+msgstr "Estado de la oportunidad"
+
+msgctxt "field:sale.opportunity.line,product:"
+msgid "Product"
+msgstr "Producto"
+
+msgctxt "field:sale.opportunity.line,quantity:"
+msgid "Quantity"
+msgstr "Cantidad"
+
+msgctxt "field:sale.opportunity.line,unit:"
+msgid "Unit"
+msgstr "Unidad"
+
+msgctxt "field:sale.opportunity.line,unit_digits:"
+msgid "Unit Digits"
+msgstr "Dígitos de la unidad"
+
+msgctxt "field:sale.opportunity_employee,amount:"
+msgid "Amount"
+msgstr "Importe"
+
+msgctxt "field:sale.opportunity_employee,company:"
+msgid "Company"
+msgstr "Empresa"
+
+msgctxt "field:sale.opportunity_employee,conversion_amount_rate:"
+msgid "Conversion Amount Rate"
+msgstr "Porcentaje convertidas (sobre importe)"
+
+msgctxt "field:sale.opportunity_employee,conversion_rate:"
+msgid "Conversion Rate"
+msgstr "Porcentaje convertidas"
+
+msgctxt "field:sale.opportunity_employee,converted:"
+msgid "Converted"
+msgstr "Convertidas"
+
+msgctxt "field:sale.opportunity_employee,converted_amount:"
+msgid "Converted Amount"
+msgstr "Importe convertidas"
+
+msgctxt "field:sale.opportunity_employee,currency:"
+msgid "Currency"
+msgstr "Moneda"
+
+msgctxt "field:sale.opportunity_employee,currency_digits:"
+msgid "Currency Digits"
+msgstr "Decimales de la moneda"
+
+msgctxt "field:sale.opportunity_employee,employee:"
+msgid "Employee"
+msgstr "Empleado"
+
+msgctxt "field:sale.opportunity_employee,lost:"
+msgid "Lost"
+msgstr "Perdidas"
+
+msgctxt "field:sale.opportunity_employee,number:"
+msgid "Number"
+msgstr "Número"
+
+msgctxt "field:sale.opportunity_employee,winning_amount_rate:"
+msgid "Winning Amount Rate"
+msgstr "Porcentaje ganadas (sobre importe)"
+
+msgctxt "field:sale.opportunity_employee,winning_rate:"
+msgid "Winning Rate"
+msgstr "Porcentaje ganadas"
+
+msgctxt "field:sale.opportunity_employee,won:"
+msgid "Won"
+msgstr "Ganadas"
+
+msgctxt "field:sale.opportunity_employee,won_amount:"
+msgid "Won Amount"
+msgstr "Importe ganadas"
+
+msgctxt "field:sale.opportunity_employee.context,end_date:"
+msgid "End Date"
+msgstr "Fecha final"
+
+msgctxt "field:sale.opportunity_employee.context,start_date:"
+msgid "Start Date"
+msgstr "Fecha inicial"
+
+msgctxt "field:sale.opportunity_employee_monthly,amount:"
+msgid "Amount"
+msgstr "Importe"
+
+msgctxt "field:sale.opportunity_employee_monthly,company:"
+msgid "Company"
+msgstr "Empresa"
+
+msgctxt "field:sale.opportunity_employee_monthly,conversion_amount_rate:"
+msgid "Conversion Amount Rate"
+msgstr "Porcentaje convertidas (sobre importe)"
+
+msgctxt "field:sale.opportunity_employee_monthly,conversion_rate:"
+msgid "Conversion Rate"
+msgstr "Porcentaje convertidas"
+
+msgctxt "field:sale.opportunity_employee_monthly,converted:"
+msgid "Converted"
+msgstr "Convertidas"
+
+msgctxt "field:sale.opportunity_employee_monthly,converted_amount:"
+msgid "Converted Amount"
+msgstr "Importe convertidas"
+
+msgctxt "field:sale.opportunity_employee_monthly,currency:"
+msgid "Currency"
+msgstr "Moneda"
+
+msgctxt "field:sale.opportunity_employee_monthly,currency_digits:"
+msgid "Currency Digits"
+msgstr "Decimales de la moneda"
+
+msgctxt "field:sale.opportunity_employee_monthly,employee:"
+msgid "Employee"
+msgstr "Empleado"
+
+msgctxt "field:sale.opportunity_employee_monthly,lost:"
+msgid "Lost"
+msgstr "Perdidas"
+
+msgctxt "field:sale.opportunity_employee_monthly,month:"
+msgid "Month"
+msgstr "Mes"
+
+msgctxt "field:sale.opportunity_employee_monthly,number:"
+msgid "Number"
+msgstr "Número"
+
+msgctxt "field:sale.opportunity_employee_monthly,winning_amount_rate:"
+msgid "Winning Amount Rate"
+msgstr "Porcentaje ganadas (sobre importe)"
+
+msgctxt "field:sale.opportunity_employee_monthly,winning_rate:"
+msgid "Winning Rate"
+msgstr "Porcentaje ganadas"
+
+msgctxt "field:sale.opportunity_employee_monthly,won:"
+msgid "Won"
+msgstr "Ganadas"
+
+msgctxt "field:sale.opportunity_employee_monthly,won_amount:"
+msgid "Won Amount"
+msgstr "Importe ganadas"
+
+msgctxt "field:sale.opportunity_employee_monthly,year:"
+msgid "Year"
+msgstr "Año"
+
+msgctxt "field:sale.opportunity_monthly,amount:"
+msgid "Amount"
+msgstr "Importe"
+
+msgctxt "field:sale.opportunity_monthly,company:"
+msgid "Company"
+msgstr "Empresa"
+
+msgctxt "field:sale.opportunity_monthly,conversion_amount_rate:"
+msgid "Conversion Amount Rate"
+msgstr "Porcentaje convertidas (sobre importe)"
+
+msgctxt "field:sale.opportunity_monthly,conversion_rate:"
+msgid "Conversion Rate"
+msgstr "Porcentaje convertidas"
+
+msgctxt "field:sale.opportunity_monthly,converted:"
+msgid "Converted"
+msgstr "Convertidas"
+
+msgctxt "field:sale.opportunity_monthly,converted_amount:"
+msgid "Converted Amount"
+msgstr "Importe convertidas"
+
+msgctxt "field:sale.opportunity_monthly,currency:"
+msgid "Currency"
+msgstr "Moneda"
+
+msgctxt "field:sale.opportunity_monthly,currency_digits:"
+msgid "Currency Digits"
+msgstr "Decimales de la moneda"
+
+msgctxt "field:sale.opportunity_monthly,lost:"
+msgid "Lost"
+msgstr "Perdidas"
+
+msgctxt "field:sale.opportunity_monthly,month:"
+msgid "Month"
+msgstr "Mes"
+
+msgctxt "field:sale.opportunity_monthly,number:"
+msgid "Number"
+msgstr "Número"
+
+msgctxt "field:sale.opportunity_monthly,winning_amount_rate:"
+msgid "Winning Amount Rate"
+msgstr "Porcentaje ganadas (sobre importe)"
+
+msgctxt "field:sale.opportunity_monthly,winning_rate:"
+msgid "Winning Rate"
+msgstr "Porcentaje ganadas"
+
+msgctxt "field:sale.opportunity_monthly,won:"
+msgid "Won"
+msgstr "Ganadas"
+
+msgctxt "field:sale.opportunity_monthly,won_amount:"
+msgid "Won Amount"
+msgstr "Importe ganadas"
+
+msgctxt "field:sale.opportunity_monthly,year:"
+msgid "Year"
+msgstr "Año"
+
+msgctxt "field:sale.opportunity_monthly,year_month:"
+msgid "Year-Month"
+msgstr "Año-Mes"
+
+msgctxt "help:sale.opportunity,amount:"
+msgid "Estimated revenue amount."
+msgstr "Importe estimado de ingresos."
+
+msgctxt "help:sale.opportunity,conversion_probability:"
+msgid "Percentage between 0 and 100."
+msgstr "Porcentaje entre 0 y 100."
+
+msgctxt "model:ir.action,name:act_open_sale_form"
+msgid "Sales"
+msgstr "Ventas"
+
+msgctxt "model:ir.action,name:act_opportunity_employee_form"
+msgid "Opportunities per Employee"
+msgstr "Oportunidades por empleado"
+
+msgctxt "model:ir.action,name:act_opportunity_employee_monthly_form"
+msgid "Opportunities per Employee per Month"
+msgstr "Oportunidades por empleado y mes"
+
+msgctxt "model:ir.action,name:act_opportunity_form"
+msgid "Leads and Opportunities"
+msgstr "Iniciativas y oportunidades"
+
+msgctxt "model:ir.action,name:act_opportunity_form2"
+msgid "Sales Leads/Opportunities"
+msgstr "Iniciativas/Oportunidades"
+
+msgctxt "model:ir.action,name:act_opportunity_monthly_form"
+msgid "Opportunities per Month"
+msgstr "Oportunidades por mes"
+
+msgctxt ""
+"model:ir.action.act_window.domain,name:act_opportunity_form_domain_all"
+msgid "All"
+msgstr "Todo"
+
+msgctxt ""
+"model:ir.action.act_window.domain,name:act_opportunity_form_domain_cancelled"
+msgid "Cancelled"
+msgstr "Cancelada"
+
+msgctxt ""
+"model:ir.action.act_window.domain,name:act_opportunity_form_domain_converted"
+msgid "Converted"
+msgstr "Convertida"
+
+msgctxt ""
+"model:ir.action.act_window.domain,name:act_opportunity_form_domain_leads"
+msgid "Leads"
+msgstr "Iniciativa"
+
+msgctxt ""
+"model:ir.action.act_window.domain,name:act_opportunity_form_domain_lost"
+msgid "Lost"
+msgstr "Perdida"
+
+msgctxt ""
+"model:ir.action.act_window.domain,name:act_opportunity_form_domain_opportunities"
+msgid "Opportunities"
+msgstr "Oportunidades"
+
+msgctxt ""
+"model:ir.action.act_window.domain,name:act_opportunity_form_domain_won"
+msgid "Won"
+msgstr "Ganada"
+
+msgctxt "model:ir.message,text:msg_modify_origin_opportunity"
+msgid "You cannot modify the opportunity origin of the sale \"%(sale)s\"."
+msgstr "No se puede modificar la oportunidad origen de la venta \"%(sale)s\"."
+
+msgctxt "model:ir.message,text:msg_opportunity_delete_cancel"
+msgid "To delete opportunity \"%(opportunity)s\", you must cancel it."
+msgstr "Debéis cancelar la oportunidad \"%(opportunity)s\" para poderla eliminar."
+
+msgctxt "model:ir.model.button,string:opportunity_cancel_button"
+msgid "Cancel"
+msgstr "Cancelar"
+
+msgctxt "model:ir.model.button,string:opportunity_convert_button"
+msgid "Convert to Sale"
+msgstr "Convertir a venta"
+
+msgctxt "model:ir.model.button,string:opportunity_lead_button"
+msgid "Set as Lead"
+msgstr "Convertir a iniciativa"
+
+msgctxt "model:ir.model.button,string:opportunity_lost_button"
+msgid "Mark as Lost"
+msgstr "Marcar como perdida"
+
+msgctxt "model:ir.model.button,string:opportunity_opportunity_button"
+msgid "Convert to Opportunity"
+msgstr "Convertir a oportunidad"
+
+msgctxt "model:ir.rule.group,name:rule_group_opportunity_companies"
+msgid "User in companies"
+msgstr "Usuario en las empresas"
+
+msgctxt "model:ir.rule.group,name:rule_group_opportunity_employee_companies"
+msgid "User in companies"
+msgstr "Usuario en las empresas"
+
+msgctxt ""
+"model:ir.rule.group,name:rule_group_opportunity_employee_monthly_companies"
+msgid "User in companies"
+msgstr "Usuario en las empresas"
+
+msgctxt "model:ir.rule.group,name:rule_group_opportunity_monthly_companies"
+msgid "User in companies"
+msgstr "Usuario en las empresas"
+
+msgctxt "model:ir.sequence,name:sequence_sale_opportunity"
+msgid "Sale Opportunity"
+msgstr "Oportunidad"
+
+msgctxt "model:ir.sequence.type,name:sequence_type_sale_opportunity"
+msgid "Sale Opportunity"
+msgstr "Oportunidad"
+
+msgctxt "model:ir.ui.menu,name:menu_opportunity_employee_monthly_form"
+msgid "Opportunities per Employee per Month"
+msgstr "Oportunidades por empleado y mes"
+
+msgctxt "model:ir.ui.menu,name:menu_opportunity_employee_open"
+msgid "Opportunities per Employee"
+msgstr "Oportunidades por empleado"
+
+msgctxt "model:ir.ui.menu,name:menu_opportunity_form"
+msgid "Leads and Opportunities"
+msgstr "Iniciativas y oportunidades"
+
+msgctxt "model:ir.ui.menu,name:menu_opportunity_monthly_form"
+msgid "Opportunities per Month"
+msgstr "Oportunidades por mes"
+
+msgctxt "model:res.group,name:group_opportunity"
+msgid "Sale Opportunity"
+msgstr "Iniciativas y oportunidades"
+
+msgctxt "model:sale.opportunity,name:"
+msgid "Sale Opportunity"
+msgstr "Oportunidad"
+
+msgctxt "model:sale.opportunity.line,name:"
+msgid "Sale Opportunity Line"
+msgstr "Línea de oportunidad"
+
+msgctxt "model:sale.opportunity_employee,name:"
+msgid "Sale Opportunity per Employee"
+msgstr "Oportunidades por empleado"
+
+msgctxt "model:sale.opportunity_employee.context,name:"
+msgid "Sale Opportunity per Employee Context"
+msgstr "Contexto Oportunidades por empleado y mes"
+
+msgctxt "model:sale.opportunity_employee_monthly,name:"
+msgid "Sale Opportunity per Employee per Month"
+msgstr "Oportunidades por empleado y mes"
+
+msgctxt "model:sale.opportunity_monthly,name:"
+msgid "Sale Opportunity per Month"
+msgstr "Oportunidades por mes"
+
+msgctxt "selection:sale.opportunity,state:"
+msgid "Cancelled"
+msgstr "Cancelada"
+
+msgctxt "selection:sale.opportunity,state:"
+msgid "Converted"
+msgstr "Convertida"
+
+msgctxt "selection:sale.opportunity,state:"
+msgid "Lead"
+msgstr "Iniciativa"
+
+msgctxt "selection:sale.opportunity,state:"
+msgid "Lost"
+msgstr "Perdida"
+
+msgctxt "selection:sale.opportunity,state:"
+msgid "Opportunity"
+msgstr "Oportunidad"
+
+msgctxt "selection:sale.opportunity,state:"
+msgid "Won"
+msgstr "Ganada"
+
+msgctxt "view:sale.opportunity:"
+msgid "%"
+msgstr "%"
+
+msgctxt "view:sale.opportunity:"
+msgid "Lead/Opportunity"
+msgstr "Iniciativa/Oportunidad"
+
+msgctxt "view:sale.opportunity_employee:"
+msgid "%"
+msgstr "%"
+
+msgctxt "view:sale.opportunity_employee_monthly:"
+msgid "%"
+msgstr "%"
+
+msgctxt "view:sale.opportunity_monthly:"
+msgid "%"
+msgstr "%"
diff --git a/modules/sale_opportunity/locale/es_419.po b/modules/sale_opportunity/locale/es_419.po
new file mode 100644
index 0000000000..a834fedf87
--- /dev/null
+++ b/modules/sale_opportunity/locale/es_419.po
@@ -0,0 +1,547 @@
+#
+msgid ""
+msgstr "Content-Type: text/plain; charset=utf-8\n"
+
+msgctxt "field:sale.configuration,sale_opportunity_sequence:"
+msgid "Opportunity Sequence"
+msgstr ""
+
+msgctxt "field:sale.configuration.sequence,sale_opportunity_sequence:"
+msgid "Opportunity Sequence"
+msgstr ""
+
+msgctxt "field:sale.opportunity,address:"
+msgid "Address"
+msgstr ""
+
+msgctxt "field:sale.opportunity,amount:"
+msgid "Amount"
+msgstr ""
+
+msgctxt "field:sale.opportunity,comment:"
+msgid "Comment"
+msgstr ""
+
+msgctxt "field:sale.opportunity,company:"
+msgid "Company"
+msgstr ""
+
+msgctxt "field:sale.opportunity,contact:"
+msgid "Contact"
+msgstr ""
+
+msgctxt "field:sale.opportunity,conversion_probability:"
+msgid "Conversion Probability"
+msgstr ""
+
+#, fuzzy
+msgctxt "field:sale.opportunity,converted_by:"
+msgid "Converted By"
+msgstr "Creado por usuario"
+
+msgctxt "field:sale.opportunity,currency:"
+msgid "Currency"
+msgstr ""
+
+msgctxt "field:sale.opportunity,currency_digits:"
+msgid "Currency Digits"
+msgstr ""
+
+msgctxt "field:sale.opportunity,description:"
+msgid "Description"
+msgstr ""
+
+msgctxt "field:sale.opportunity,employee:"
+msgid "Employee"
+msgstr ""
+
+msgctxt "field:sale.opportunity,end_date:"
+msgid "End Date"
+msgstr ""
+
+msgctxt "field:sale.opportunity,lines:"
+msgid "Lines"
+msgstr ""
+
+msgctxt "field:sale.opportunity,lost_reason:"
+msgid "Reason for loss"
+msgstr "Motivo de la pérdida"
+
+msgctxt "field:sale.opportunity,number:"
+msgid "Number"
+msgstr ""
+
+msgctxt "field:sale.opportunity,party:"
+msgid "Party"
+msgstr ""
+
+msgctxt "field:sale.opportunity,payment_term:"
+msgid "Payment Term"
+msgstr "Término de pago"
+
+msgctxt "field:sale.opportunity,reference:"
+msgid "Reference"
+msgstr ""
+
+msgctxt "field:sale.opportunity,sales:"
+msgid "Sales"
+msgstr ""
+
+msgctxt "field:sale.opportunity,start_date:"
+msgid "Start Date"
+msgstr ""
+
+msgctxt "field:sale.opportunity,state:"
+msgid "State"
+msgstr ""
+
+msgctxt "field:sale.opportunity.line,opportunity:"
+msgid "Opportunity"
+msgstr ""
+
+msgctxt "field:sale.opportunity.line,opportunity_state:"
+msgid "Opportunity State"
+msgstr ""
+
+msgctxt "field:sale.opportunity.line,product:"
+msgid "Product"
+msgstr ""
+
+msgctxt "field:sale.opportunity.line,quantity:"
+msgid "Quantity"
+msgstr ""
+
+msgctxt "field:sale.opportunity.line,unit:"
+msgid "Unit"
+msgstr ""
+
+msgctxt "field:sale.opportunity.line,unit_digits:"
+msgid "Unit Digits"
+msgstr ""
+
+msgctxt "field:sale.opportunity_employee,amount:"
+msgid "Amount"
+msgstr ""
+
+msgctxt "field:sale.opportunity_employee,company:"
+msgid "Company"
+msgstr ""
+
+msgctxt "field:sale.opportunity_employee,conversion_amount_rate:"
+msgid "Conversion Amount Rate"
+msgstr ""
+
+msgctxt "field:sale.opportunity_employee,conversion_rate:"
+msgid "Conversion Rate"
+msgstr ""
+
+msgctxt "field:sale.opportunity_employee,converted:"
+msgid "Converted"
+msgstr ""
+
+msgctxt "field:sale.opportunity_employee,converted_amount:"
+msgid "Converted Amount"
+msgstr ""
+
+msgctxt "field:sale.opportunity_employee,currency:"
+msgid "Currency"
+msgstr ""
+
+msgctxt "field:sale.opportunity_employee,currency_digits:"
+msgid "Currency Digits"
+msgstr ""
+
+msgctxt "field:sale.opportunity_employee,employee:"
+msgid "Employee"
+msgstr ""
+
+msgctxt "field:sale.opportunity_employee,lost:"
+msgid "Lost"
+msgstr "Perdida"
+
+msgctxt "field:sale.opportunity_employee,number:"
+msgid "Number"
+msgstr ""
+
+msgctxt "field:sale.opportunity_employee,winning_amount_rate:"
+msgid "Winning Amount Rate"
+msgstr ""
+
+msgctxt "field:sale.opportunity_employee,winning_rate:"
+msgid "Winning Rate"
+msgstr ""
+
+#, fuzzy
+msgctxt "field:sale.opportunity_employee,won:"
+msgid "Won"
+msgstr "Ganada"
+
+msgctxt "field:sale.opportunity_employee,won_amount:"
+msgid "Won Amount"
+msgstr ""
+
+msgctxt "field:sale.opportunity_employee.context,end_date:"
+msgid "End Date"
+msgstr ""
+
+msgctxt "field:sale.opportunity_employee.context,start_date:"
+msgid "Start Date"
+msgstr ""
+
+msgctxt "field:sale.opportunity_employee_monthly,amount:"
+msgid "Amount"
+msgstr ""
+
+msgctxt "field:sale.opportunity_employee_monthly,company:"
+msgid "Company"
+msgstr ""
+
+msgctxt "field:sale.opportunity_employee_monthly,conversion_amount_rate:"
+msgid "Conversion Amount Rate"
+msgstr ""
+
+msgctxt "field:sale.opportunity_employee_monthly,conversion_rate:"
+msgid "Conversion Rate"
+msgstr ""
+
+msgctxt "field:sale.opportunity_employee_monthly,converted:"
+msgid "Converted"
+msgstr ""
+
+msgctxt "field:sale.opportunity_employee_monthly,converted_amount:"
+msgid "Converted Amount"
+msgstr ""
+
+msgctxt "field:sale.opportunity_employee_monthly,currency:"
+msgid "Currency"
+msgstr ""
+
+msgctxt "field:sale.opportunity_employee_monthly,currency_digits:"
+msgid "Currency Digits"
+msgstr ""
+
+msgctxt "field:sale.opportunity_employee_monthly,employee:"
+msgid "Employee"
+msgstr ""
+
+msgctxt "field:sale.opportunity_employee_monthly,lost:"
+msgid "Lost"
+msgstr "Perdida"
+
+msgctxt "field:sale.opportunity_employee_monthly,month:"
+msgid "Month"
+msgstr ""
+
+msgctxt "field:sale.opportunity_employee_monthly,number:"
+msgid "Number"
+msgstr ""
+
+msgctxt "field:sale.opportunity_employee_monthly,winning_amount_rate:"
+msgid "Winning Amount Rate"
+msgstr ""
+
+msgctxt "field:sale.opportunity_employee_monthly,winning_rate:"
+msgid "Winning Rate"
+msgstr ""
+
+msgctxt "field:sale.opportunity_employee_monthly,won:"
+msgid "Won"
+msgstr "Ganada"
+
+msgctxt "field:sale.opportunity_employee_monthly,won_amount:"
+msgid "Won Amount"
+msgstr ""
+
+msgctxt "field:sale.opportunity_employee_monthly,year:"
+msgid "Year"
+msgstr ""
+
+msgctxt "field:sale.opportunity_monthly,amount:"
+msgid "Amount"
+msgstr ""
+
+msgctxt "field:sale.opportunity_monthly,company:"
+msgid "Company"
+msgstr ""
+
+msgctxt "field:sale.opportunity_monthly,conversion_amount_rate:"
+msgid "Conversion Amount Rate"
+msgstr ""
+
+msgctxt "field:sale.opportunity_monthly,conversion_rate:"
+msgid "Conversion Rate"
+msgstr ""
+
+msgctxt "field:sale.opportunity_monthly,converted:"
+msgid "Converted"
+msgstr ""
+
+msgctxt "field:sale.opportunity_monthly,converted_amount:"
+msgid "Converted Amount"
+msgstr ""
+
+msgctxt "field:sale.opportunity_monthly,currency:"
+msgid "Currency"
+msgstr ""
+
+msgctxt "field:sale.opportunity_monthly,currency_digits:"
+msgid "Currency Digits"
+msgstr ""
+
+msgctxt "field:sale.opportunity_monthly,lost:"
+msgid "Lost"
+msgstr "Perdida"
+
+msgctxt "field:sale.opportunity_monthly,month:"
+msgid "Month"
+msgstr ""
+
+msgctxt "field:sale.opportunity_monthly,number:"
+msgid "Number"
+msgstr ""
+
+msgctxt "field:sale.opportunity_monthly,winning_amount_rate:"
+msgid "Winning Amount Rate"
+msgstr ""
+
+msgctxt "field:sale.opportunity_monthly,winning_rate:"
+msgid "Winning Rate"
+msgstr ""
+
+#, fuzzy
+msgctxt "field:sale.opportunity_monthly,won:"
+msgid "Won"
+msgstr "Ganada"
+
+msgctxt "field:sale.opportunity_monthly,won_amount:"
+msgid "Won Amount"
+msgstr ""
+
+msgctxt "field:sale.opportunity_monthly,year:"
+msgid "Year"
+msgstr ""
+
+msgctxt "field:sale.opportunity_monthly,year_month:"
+msgid "Year-Month"
+msgstr ""
+
+msgctxt "help:sale.opportunity,amount:"
+msgid "Estimated revenue amount."
+msgstr ""
+
+msgctxt "help:sale.opportunity,conversion_probability:"
+msgid "Percentage between 0 and 100."
+msgstr ""
+
+msgctxt "model:ir.action,name:act_open_sale_form"
+msgid "Sales"
+msgstr ""
+
+msgctxt "model:ir.action,name:act_opportunity_employee_form"
+msgid "Opportunities per Employee"
+msgstr ""
+
+#, fuzzy
+msgctxt "model:ir.action,name:act_opportunity_employee_monthly_form"
+msgid "Opportunities per Employee per Month"
+msgstr "Oportunidades por empleado por mes"
+
+msgctxt "model:ir.action,name:act_opportunity_form"
+msgid "Leads and Opportunities"
+msgstr ""
+
+msgctxt "model:ir.action,name:act_opportunity_form2"
+msgid "Sales Leads/Opportunities"
+msgstr ""
+
+msgctxt "model:ir.action,name:act_opportunity_monthly_form"
+msgid "Opportunities per Month"
+msgstr ""
+
+msgctxt ""
+"model:ir.action.act_window.domain,name:act_opportunity_form_domain_all"
+msgid "All"
+msgstr ""
+
+msgctxt ""
+"model:ir.action.act_window.domain,name:act_opportunity_form_domain_cancelled"
+msgid "Cancelled"
+msgstr ""
+
+msgctxt ""
+"model:ir.action.act_window.domain,name:act_opportunity_form_domain_converted"
+msgid "Converted"
+msgstr ""
+
+msgctxt ""
+"model:ir.action.act_window.domain,name:act_opportunity_form_domain_leads"
+msgid "Leads"
+msgstr ""
+
+#, fuzzy
+msgctxt ""
+"model:ir.action.act_window.domain,name:act_opportunity_form_domain_lost"
+msgid "Lost"
+msgstr "Perdida"
+
+msgctxt ""
+"model:ir.action.act_window.domain,name:act_opportunity_form_domain_opportunities"
+msgid "Opportunities"
+msgstr ""
+
+#, fuzzy
+msgctxt ""
+"model:ir.action.act_window.domain,name:act_opportunity_form_domain_won"
+msgid "Won"
+msgstr "Ganada"
+
+msgctxt "model:ir.message,text:msg_modify_origin_opportunity"
+msgid "You cannot modify the opportunity origin of the sale \"%(sale)s\"."
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_opportunity_delete_cancel"
+msgid "To delete opportunity \"%(opportunity)s\", you must cancel it."
+msgstr ""
+
+msgctxt "model:ir.model.button,string:opportunity_cancel_button"
+msgid "Cancel"
+msgstr ""
+
+#, fuzzy
+msgctxt "model:ir.model.button,string:opportunity_convert_button"
+msgid "Convert to Sale"
+msgstr "Convertir a venta"
+
+msgctxt "model:ir.model.button,string:opportunity_lead_button"
+msgid "Set as Lead"
+msgstr ""
+
+msgctxt "model:ir.model.button,string:opportunity_lost_button"
+msgid "Mark as Lost"
+msgstr ""
+
+msgctxt "model:ir.model.button,string:opportunity_opportunity_button"
+msgid "Convert to Opportunity"
+msgstr ""
+
+msgctxt "model:ir.rule.group,name:rule_group_opportunity_companies"
+msgid "User in companies"
+msgstr ""
+
+msgctxt "model:ir.rule.group,name:rule_group_opportunity_employee_companies"
+msgid "User in companies"
+msgstr ""
+
+msgctxt ""
+"model:ir.rule.group,name:rule_group_opportunity_employee_monthly_companies"
+msgid "User in companies"
+msgstr ""
+
+msgctxt "model:ir.rule.group,name:rule_group_opportunity_monthly_companies"
+msgid "User in companies"
+msgstr ""
+
+#, fuzzy
+msgctxt "model:ir.sequence,name:sequence_sale_opportunity"
+msgid "Sale Opportunity"
+msgstr "Oportunidad de venta"
+
+#, fuzzy
+msgctxt "model:ir.sequence.type,name:sequence_type_sale_opportunity"
+msgid "Sale Opportunity"
+msgstr "Oportunidad de venta"
+
+#, fuzzy
+msgctxt "model:ir.ui.menu,name:menu_opportunity_employee_monthly_form"
+msgid "Opportunities per Employee per Month"
+msgstr "Oportunidades por empleado por mes"
+
+msgctxt "model:ir.ui.menu,name:menu_opportunity_employee_open"
+msgid "Opportunities per Employee"
+msgstr ""
+
+msgctxt "model:ir.ui.menu,name:menu_opportunity_form"
+msgid "Leads and Opportunities"
+msgstr ""
+
+msgctxt "model:ir.ui.menu,name:menu_opportunity_monthly_form"
+msgid "Opportunities per Month"
+msgstr ""
+
+#, fuzzy
+msgctxt "model:res.group,name:group_opportunity"
+msgid "Sale Opportunity"
+msgstr "Oportunidad de venta"
+
+msgctxt "model:sale.opportunity,name:"
+msgid "Sale Opportunity"
+msgstr "Oportunidad de venta"
+
+msgctxt "model:sale.opportunity.line,name:"
+msgid "Sale Opportunity Line"
+msgstr "Línea de oportunidad de venta"
+
+msgctxt "model:sale.opportunity_employee,name:"
+msgid "Sale Opportunity per Employee"
+msgstr "Oportunidad de venta por empleado"
+
+msgctxt "model:sale.opportunity_employee.context,name:"
+msgid "Sale Opportunity per Employee Context"
+msgstr "Contexto de oportunidades de venta por empleado"
+
+msgctxt "model:sale.opportunity_employee_monthly,name:"
+msgid "Sale Opportunity per Employee per Month"
+msgstr "Oportunidades de venta por empleado por mes"
+
+msgctxt "model:sale.opportunity_monthly,name:"
+msgid "Sale Opportunity per Month"
+msgstr "Oportunidades de venta por mes"
+
+msgctxt "selection:sale.opportunity,state:"
+msgid "Cancelled"
+msgstr ""
+
+msgctxt "selection:sale.opportunity,state:"
+msgid "Converted"
+msgstr ""
+
+msgctxt "selection:sale.opportunity,state:"
+msgid "Lead"
+msgstr ""
+
+#, fuzzy
+msgctxt "selection:sale.opportunity,state:"
+msgid "Lost"
+msgstr "Perdida"
+
+msgctxt "selection:sale.opportunity,state:"
+msgid "Opportunity"
+msgstr ""
+
+#, fuzzy
+msgctxt "selection:sale.opportunity,state:"
+msgid "Won"
+msgstr "Ganada"
+
+msgctxt "view:sale.opportunity:"
+msgid "%"
+msgstr ""
+
+msgctxt "view:sale.opportunity:"
+msgid "Lead/Opportunity"
+msgstr ""
+
+#, fuzzy
+msgctxt "view:sale.opportunity_employee:"
+msgid "%"
+msgstr "%"
+
+#, fuzzy
+msgctxt "view:sale.opportunity_employee_monthly:"
+msgid "%"
+msgstr "%"
+
+#, fuzzy
+msgctxt "view:sale.opportunity_monthly:"
+msgid "%"
+msgstr "%"
diff --git a/modules/sale_opportunity/locale/et.po b/modules/sale_opportunity/locale/et.po
new file mode 100644
index 0000000000..f7bf94642b
--- /dev/null
+++ b/modules/sale_opportunity/locale/et.po
@@ -0,0 +1,541 @@
+#
+msgid ""
+msgstr "Content-Type: text/plain; charset=utf-8\n"
+
+msgctxt "field:sale.configuration,sale_opportunity_sequence:"
+msgid "Opportunity Sequence"
+msgstr "Võimaluse jada"
+
+msgctxt "field:sale.configuration.sequence,sale_opportunity_sequence:"
+msgid "Opportunity Sequence"
+msgstr "Võimaluse jada"
+
+msgctxt "field:sale.opportunity,address:"
+msgid "Address"
+msgstr "Aadress"
+
+msgctxt "field:sale.opportunity,amount:"
+msgid "Amount"
+msgstr "Väärtus"
+
+msgctxt "field:sale.opportunity,comment:"
+msgid "Comment"
+msgstr "Kommentaar"
+
+msgctxt "field:sale.opportunity,company:"
+msgid "Company"
+msgstr "Ettevõte"
+
+msgctxt "field:sale.opportunity,contact:"
+msgid "Contact"
+msgstr ""
+
+msgctxt "field:sale.opportunity,conversion_probability:"
+msgid "Conversion Probability"
+msgstr "Pöördumise tõenäosus"
+
+#, fuzzy
+msgctxt "field:sale.opportunity,converted_by:"
+msgid "Converted By"
+msgstr "Muudetud"
+
+msgctxt "field:sale.opportunity,currency:"
+msgid "Currency"
+msgstr "Valuuta"
+
+msgctxt "field:sale.opportunity,currency_digits:"
+msgid "Currency Digits"
+msgstr "Valuuta numbriväärtus"
+
+msgctxt "field:sale.opportunity,description:"
+msgid "Description"
+msgstr "Selgitus"
+
+msgctxt "field:sale.opportunity,employee:"
+msgid "Employee"
+msgstr "Töötaja"
+
+msgctxt "field:sale.opportunity,end_date:"
+msgid "End Date"
+msgstr "Lõppkuupäev"
+
+msgctxt "field:sale.opportunity,lines:"
+msgid "Lines"
+msgstr "Read"
+
+msgctxt "field:sale.opportunity,lost_reason:"
+msgid "Reason for loss"
+msgstr "Kaotamise põhjus"
+
+msgctxt "field:sale.opportunity,number:"
+msgid "Number"
+msgstr "Number"
+
+msgctxt "field:sale.opportunity,party:"
+msgid "Party"
+msgstr "Osapool"
+
+msgctxt "field:sale.opportunity,payment_term:"
+msgid "Payment Term"
+msgstr "Makstingimus"
+
+msgctxt "field:sale.opportunity,reference:"
+msgid "Reference"
+msgstr "Viide"
+
+msgctxt "field:sale.opportunity,sales:"
+msgid "Sales"
+msgstr "Müügid"
+
+msgctxt "field:sale.opportunity,start_date:"
+msgid "Start Date"
+msgstr "Alguskuupäev"
+
+msgctxt "field:sale.opportunity,state:"
+msgid "State"
+msgstr "Olek"
+
+msgctxt "field:sale.opportunity.line,opportunity:"
+msgid "Opportunity"
+msgstr "Võimalus"
+
+msgctxt "field:sale.opportunity.line,opportunity_state:"
+msgid "Opportunity State"
+msgstr "Võimaluse olek"
+
+msgctxt "field:sale.opportunity.line,product:"
+msgid "Product"
+msgstr "Toode"
+
+msgctxt "field:sale.opportunity.line,quantity:"
+msgid "Quantity"
+msgstr "Kogus"
+
+msgctxt "field:sale.opportunity.line,unit:"
+msgid "Unit"
+msgstr "Ühik"
+
+msgctxt "field:sale.opportunity.line,unit_digits:"
+msgid "Unit Digits"
+msgstr "Ühiku numbriväärtus"
+
+msgctxt "field:sale.opportunity_employee,amount:"
+msgid "Amount"
+msgstr "Väärtus"
+
+msgctxt "field:sale.opportunity_employee,company:"
+msgid "Company"
+msgstr "Ettevõte"
+
+msgctxt "field:sale.opportunity_employee,conversion_amount_rate:"
+msgid "Conversion Amount Rate"
+msgstr ""
+
+msgctxt "field:sale.opportunity_employee,conversion_rate:"
+msgid "Conversion Rate"
+msgstr ""
+
+#, fuzzy
+msgctxt "field:sale.opportunity_employee,converted:"
+msgid "Converted"
+msgstr "Muudetud"
+
+msgctxt "field:sale.opportunity_employee,converted_amount:"
+msgid "Converted Amount"
+msgstr ""
+
+msgctxt "field:sale.opportunity_employee,currency:"
+msgid "Currency"
+msgstr "Valuuta"
+
+msgctxt "field:sale.opportunity_employee,currency_digits:"
+msgid "Currency Digits"
+msgstr "Valuuta numbriväärtus"
+
+msgctxt "field:sale.opportunity_employee,employee:"
+msgid "Employee"
+msgstr "Töötaja"
+
+msgctxt "field:sale.opportunity_employee,lost:"
+msgid "Lost"
+msgstr "Kaotatud"
+
+msgctxt "field:sale.opportunity_employee,number:"
+msgid "Number"
+msgstr "Number"
+
+msgctxt "field:sale.opportunity_employee,winning_amount_rate:"
+msgid "Winning Amount Rate"
+msgstr ""
+
+msgctxt "field:sale.opportunity_employee,winning_rate:"
+msgid "Winning Rate"
+msgstr ""
+
+msgctxt "field:sale.opportunity_employee,won:"
+msgid "Won"
+msgstr "Võidetud"
+
+msgctxt "field:sale.opportunity_employee,won_amount:"
+msgid "Won Amount"
+msgstr "Võidetud väärtus"
+
+msgctxt "field:sale.opportunity_employee.context,end_date:"
+msgid "End Date"
+msgstr "Lõppkuupäev"
+
+msgctxt "field:sale.opportunity_employee.context,start_date:"
+msgid "Start Date"
+msgstr "Alguskuupäev"
+
+msgctxt "field:sale.opportunity_employee_monthly,amount:"
+msgid "Amount"
+msgstr "Väärtus"
+
+msgctxt "field:sale.opportunity_employee_monthly,company:"
+msgid "Company"
+msgstr "Ettevõte"
+
+msgctxt "field:sale.opportunity_employee_monthly,conversion_amount_rate:"
+msgid "Conversion Amount Rate"
+msgstr ""
+
+msgctxt "field:sale.opportunity_employee_monthly,conversion_rate:"
+msgid "Conversion Rate"
+msgstr ""
+
+#, fuzzy
+msgctxt "field:sale.opportunity_employee_monthly,converted:"
+msgid "Converted"
+msgstr "Muudetud"
+
+msgctxt "field:sale.opportunity_employee_monthly,converted_amount:"
+msgid "Converted Amount"
+msgstr ""
+
+msgctxt "field:sale.opportunity_employee_monthly,currency:"
+msgid "Currency"
+msgstr "Valuuta"
+
+msgctxt "field:sale.opportunity_employee_monthly,currency_digits:"
+msgid "Currency Digits"
+msgstr "Valuuta numbriväärtus"
+
+msgctxt "field:sale.opportunity_employee_monthly,employee:"
+msgid "Employee"
+msgstr "Töötaja"
+
+msgctxt "field:sale.opportunity_employee_monthly,lost:"
+msgid "Lost"
+msgstr "Kaotatud"
+
+msgctxt "field:sale.opportunity_employee_monthly,month:"
+msgid "Month"
+msgstr "Kuu"
+
+msgctxt "field:sale.opportunity_employee_monthly,number:"
+msgid "Number"
+msgstr "Number"
+
+msgctxt "field:sale.opportunity_employee_monthly,winning_amount_rate:"
+msgid "Winning Amount Rate"
+msgstr ""
+
+msgctxt "field:sale.opportunity_employee_monthly,winning_rate:"
+msgid "Winning Rate"
+msgstr ""
+
+msgctxt "field:sale.opportunity_employee_monthly,won:"
+msgid "Won"
+msgstr "Võidetud"
+
+msgctxt "field:sale.opportunity_employee_monthly,won_amount:"
+msgid "Won Amount"
+msgstr "Võidetud väärtus"
+
+msgctxt "field:sale.opportunity_employee_monthly,year:"
+msgid "Year"
+msgstr "Aasta"
+
+msgctxt "field:sale.opportunity_monthly,amount:"
+msgid "Amount"
+msgstr "Väärtus"
+
+msgctxt "field:sale.opportunity_monthly,company:"
+msgid "Company"
+msgstr "Ettevõte"
+
+msgctxt "field:sale.opportunity_monthly,conversion_amount_rate:"
+msgid "Conversion Amount Rate"
+msgstr ""
+
+msgctxt "field:sale.opportunity_monthly,conversion_rate:"
+msgid "Conversion Rate"
+msgstr ""
+
+#, fuzzy
+msgctxt "field:sale.opportunity_monthly,converted:"
+msgid "Converted"
+msgstr "Muudetud"
+
+msgctxt "field:sale.opportunity_monthly,converted_amount:"
+msgid "Converted Amount"
+msgstr ""
+
+msgctxt "field:sale.opportunity_monthly,currency:"
+msgid "Currency"
+msgstr "Valuuta"
+
+msgctxt "field:sale.opportunity_monthly,currency_digits:"
+msgid "Currency Digits"
+msgstr "Valuuta numbriväärtus"
+
+msgctxt "field:sale.opportunity_monthly,lost:"
+msgid "Lost"
+msgstr "Kaotatud"
+
+msgctxt "field:sale.opportunity_monthly,month:"
+msgid "Month"
+msgstr "Kuu"
+
+msgctxt "field:sale.opportunity_monthly,number:"
+msgid "Number"
+msgstr "Number"
+
+msgctxt "field:sale.opportunity_monthly,winning_amount_rate:"
+msgid "Winning Amount Rate"
+msgstr ""
+
+msgctxt "field:sale.opportunity_monthly,winning_rate:"
+msgid "Winning Rate"
+msgstr ""
+
+msgctxt "field:sale.opportunity_monthly,won:"
+msgid "Won"
+msgstr "Võidetud"
+
+msgctxt "field:sale.opportunity_monthly,won_amount:"
+msgid "Won Amount"
+msgstr "Võidetud väärtus"
+
+msgctxt "field:sale.opportunity_monthly,year:"
+msgid "Year"
+msgstr "Aasta"
+
+msgctxt "field:sale.opportunity_monthly,year_month:"
+msgid "Year-Month"
+msgstr "Aasta-Kuu"
+
+msgctxt "help:sale.opportunity,amount:"
+msgid "Estimated revenue amount."
+msgstr ""
+
+#, fuzzy
+msgctxt "help:sale.opportunity,conversion_probability:"
+msgid "Percentage between 0 and 100."
+msgstr "Protsent 0 kuni 100"
+
+msgctxt "model:ir.action,name:act_open_sale_form"
+msgid "Sales"
+msgstr "Müük"
+
+msgctxt "model:ir.action,name:act_opportunity_employee_form"
+msgid "Opportunities per Employee"
+msgstr "Võimlaused töötaja lõikes"
+
+msgctxt "model:ir.action,name:act_opportunity_employee_monthly_form"
+msgid "Opportunities per Employee per Month"
+msgstr "Võimalused töötaja ja kuu lõikes"
+
+msgctxt "model:ir.action,name:act_opportunity_form"
+msgid "Leads and Opportunities"
+msgstr "Potensiaalid ja võimalused"
+
+msgctxt "model:ir.action,name:act_opportunity_form2"
+msgid "Sales Leads/Opportunities"
+msgstr "Müügid potensiaalid/võimalused"
+
+msgctxt "model:ir.action,name:act_opportunity_monthly_form"
+msgid "Opportunities per Month"
+msgstr "Võimalused kuude lõikes"
+
+msgctxt ""
+"model:ir.action.act_window.domain,name:act_opportunity_form_domain_all"
+msgid "All"
+msgstr "Kõik"
+
+msgctxt ""
+"model:ir.action.act_window.domain,name:act_opportunity_form_domain_cancelled"
+msgid "Cancelled"
+msgstr "Tühistatud"
+
+#, fuzzy
+msgctxt ""
+"model:ir.action.act_window.domain,name:act_opportunity_form_domain_converted"
+msgid "Converted"
+msgstr "Muudetud"
+
+msgctxt ""
+"model:ir.action.act_window.domain,name:act_opportunity_form_domain_leads"
+msgid "Leads"
+msgstr "Potensiaalid"
+
+msgctxt ""
+"model:ir.action.act_window.domain,name:act_opportunity_form_domain_lost"
+msgid "Lost"
+msgstr "Kaotatud"
+
+msgctxt ""
+"model:ir.action.act_window.domain,name:act_opportunity_form_domain_opportunities"
+msgid "Opportunities"
+msgstr "Võimalused"
+
+msgctxt ""
+"model:ir.action.act_window.domain,name:act_opportunity_form_domain_won"
+msgid "Won"
+msgstr "Võidetud"
+
+msgctxt "model:ir.message,text:msg_modify_origin_opportunity"
+msgid "You cannot modify the opportunity origin of the sale \"%(sale)s\"."
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_opportunity_delete_cancel"
+msgid "To delete opportunity \"%(opportunity)s\", you must cancel it."
+msgstr ""
+
+msgctxt "model:ir.model.button,string:opportunity_cancel_button"
+msgid "Cancel"
+msgstr "Tühista"
+
+msgctxt "model:ir.model.button,string:opportunity_convert_button"
+msgid "Convert to Sale"
+msgstr "Muuda müügiks"
+
+msgctxt "model:ir.model.button,string:opportunity_lead_button"
+msgid "Set as Lead"
+msgstr "Märgi potensiaaliks"
+
+msgctxt "model:ir.model.button,string:opportunity_lost_button"
+msgid "Mark as Lost"
+msgstr "Märgi kaotatuks"
+
+msgctxt "model:ir.model.button,string:opportunity_opportunity_button"
+msgid "Convert to Opportunity"
+msgstr "Muuda võimaluseks"
+
+#, fuzzy
+msgctxt "model:ir.rule.group,name:rule_group_opportunity_companies"
+msgid "User in companies"
+msgstr "Kasutaja ettevõttes"
+
+#, fuzzy
+msgctxt "model:ir.rule.group,name:rule_group_opportunity_employee_companies"
+msgid "User in companies"
+msgstr "Kasutaja ettevõttes"
+
+#, fuzzy
+msgctxt ""
+"model:ir.rule.group,name:rule_group_opportunity_employee_monthly_companies"
+msgid "User in companies"
+msgstr "Kasutaja ettevõttes"
+
+#, fuzzy
+msgctxt "model:ir.rule.group,name:rule_group_opportunity_monthly_companies"
+msgid "User in companies"
+msgstr "Kasutaja ettevõttes"
+
+msgctxt "model:ir.sequence,name:sequence_sale_opportunity"
+msgid "Sale Opportunity"
+msgstr "Müügivõimalus"
+
+msgctxt "model:ir.sequence.type,name:sequence_type_sale_opportunity"
+msgid "Sale Opportunity"
+msgstr "Müügivõimalus"
+
+msgctxt "model:ir.ui.menu,name:menu_opportunity_employee_monthly_form"
+msgid "Opportunities per Employee per Month"
+msgstr "Võimalused töötaja ja kuu lõikes"
+
+msgctxt "model:ir.ui.menu,name:menu_opportunity_employee_open"
+msgid "Opportunities per Employee"
+msgstr "Võimalused töötaja"
+
+msgctxt "model:ir.ui.menu,name:menu_opportunity_form"
+msgid "Leads and Opportunities"
+msgstr "Potentsiaalid ja võimalused"
+
+msgctxt "model:ir.ui.menu,name:menu_opportunity_monthly_form"
+msgid "Opportunities per Month"
+msgstr "Võimalused kuude lõikes"
+
+msgctxt "model:res.group,name:group_opportunity"
+msgid "Sale Opportunity"
+msgstr "Müügi võimalus"
+
+msgctxt "model:sale.opportunity,name:"
+msgid "Sale Opportunity"
+msgstr "Müügi võimalus"
+
+msgctxt "model:sale.opportunity.line,name:"
+msgid "Sale Opportunity Line"
+msgstr "Müügi võimaluse rida"
+
+msgctxt "model:sale.opportunity_employee,name:"
+msgid "Sale Opportunity per Employee"
+msgstr "Müügi võimalus töötaja lõikes"
+
+msgctxt "model:sale.opportunity_employee.context,name:"
+msgid "Sale Opportunity per Employee Context"
+msgstr "Müügi võimalus töötaja lõikes - sisu"
+
+msgctxt "model:sale.opportunity_employee_monthly,name:"
+msgid "Sale Opportunity per Employee per Month"
+msgstr "Müügi võimalus töötaja ja kuu lõikes"
+
+msgctxt "model:sale.opportunity_monthly,name:"
+msgid "Sale Opportunity per Month"
+msgstr "Müügi võimalus kuu lõikes"
+
+msgctxt "selection:sale.opportunity,state:"
+msgid "Cancelled"
+msgstr "Tühistatud"
+
+msgctxt "selection:sale.opportunity,state:"
+msgid "Converted"
+msgstr "Muudetud"
+
+msgctxt "selection:sale.opportunity,state:"
+msgid "Lead"
+msgstr "Potentsiaal"
+
+msgctxt "selection:sale.opportunity,state:"
+msgid "Lost"
+msgstr "Kaotatud"
+
+msgctxt "selection:sale.opportunity,state:"
+msgid "Opportunity"
+msgstr "Võimalus"
+
+msgctxt "selection:sale.opportunity,state:"
+msgid "Won"
+msgstr "Võidetud"
+
+msgctxt "view:sale.opportunity:"
+msgid "%"
+msgstr "%"
+
+msgctxt "view:sale.opportunity:"
+msgid "Lead/Opportunity"
+msgstr "Potesntsiaal/Võimalus"
+
+msgctxt "view:sale.opportunity_employee:"
+msgid "%"
+msgstr "%"
+
+msgctxt "view:sale.opportunity_employee_monthly:"
+msgid "%"
+msgstr "%"
+
+msgctxt "view:sale.opportunity_monthly:"
+msgid "%"
+msgstr "%"
diff --git a/modules/sale_opportunity/locale/fa.po b/modules/sale_opportunity/locale/fa.po
new file mode 100644
index 0000000000..22a957e0cb
--- /dev/null
+++ b/modules/sale_opportunity/locale/fa.po
@@ -0,0 +1,534 @@
+#
+msgid ""
+msgstr "Content-Type: text/plain; charset=utf-8\n"
+
+msgctxt "field:sale.configuration,sale_opportunity_sequence:"
+msgid "Opportunity Sequence"
+msgstr "ادامه فرصت"
+
+msgctxt "field:sale.configuration.sequence,sale_opportunity_sequence:"
+msgid "Opportunity Sequence"
+msgstr "ادامه فرصت"
+
+msgctxt "field:sale.opportunity,address:"
+msgid "Address"
+msgstr "آدرس"
+
+msgctxt "field:sale.opportunity,amount:"
+msgid "Amount"
+msgstr "مقدار"
+
+msgctxt "field:sale.opportunity,comment:"
+msgid "Comment"
+msgstr "اظهار نظر"
+
+msgctxt "field:sale.opportunity,company:"
+msgid "Company"
+msgstr "شرکت"
+
+msgctxt "field:sale.opportunity,contact:"
+msgid "Contact"
+msgstr ""
+
+msgctxt "field:sale.opportunity,conversion_probability:"
+msgid "Conversion Probability"
+msgstr "احتمال تبدیل"
+
+#, fuzzy
+msgctxt "field:sale.opportunity,converted_by:"
+msgid "Converted By"
+msgstr "تبدیل شده"
+
+msgctxt "field:sale.opportunity,currency:"
+msgid "Currency"
+msgstr "واحد پول"
+
+msgctxt "field:sale.opportunity,currency_digits:"
+msgid "Currency Digits"
+msgstr "رقم های واحد پول"
+
+msgctxt "field:sale.opportunity,description:"
+msgid "Description"
+msgstr "شرح"
+
+msgctxt "field:sale.opportunity,employee:"
+msgid "Employee"
+msgstr "کارمند"
+
+msgctxt "field:sale.opportunity,end_date:"
+msgid "End Date"
+msgstr "تاریخ پایان"
+
+msgctxt "field:sale.opportunity,lines:"
+msgid "Lines"
+msgstr "سطرها"
+
+msgctxt "field:sale.opportunity,lost_reason:"
+msgid "Reason for loss"
+msgstr "دلیل شکست"
+
+msgctxt "field:sale.opportunity,number:"
+msgid "Number"
+msgstr "شماره"
+
+msgctxt "field:sale.opportunity,party:"
+msgid "Party"
+msgstr "نهاد/سازمان"
+
+msgctxt "field:sale.opportunity,payment_term:"
+msgid "Payment Term"
+msgstr "نحوه پرداخت"
+
+msgctxt "field:sale.opportunity,reference:"
+msgid "Reference"
+msgstr "مرجع"
+
+msgctxt "field:sale.opportunity,sales:"
+msgid "Sales"
+msgstr "فروش ها"
+
+msgctxt "field:sale.opportunity,start_date:"
+msgid "Start Date"
+msgstr "تاریخ شروع"
+
+msgctxt "field:sale.opportunity,state:"
+msgid "State"
+msgstr "وضعیت"
+
+msgctxt "field:sale.opportunity.line,opportunity:"
+msgid "Opportunity"
+msgstr "فرصت"
+
+msgctxt "field:sale.opportunity.line,opportunity_state:"
+msgid "Opportunity State"
+msgstr "وضعیت فرصت"
+
+msgctxt "field:sale.opportunity.line,product:"
+msgid "Product"
+msgstr "محصول"
+
+msgctxt "field:sale.opportunity.line,quantity:"
+msgid "Quantity"
+msgstr "مقدار/تعداد"
+
+msgctxt "field:sale.opportunity.line,unit:"
+msgid "Unit"
+msgstr "واحد"
+
+msgctxt "field:sale.opportunity.line,unit_digits:"
+msgid "Unit Digits"
+msgstr "ارقام واحد"
+
+msgctxt "field:sale.opportunity_employee,amount:"
+msgid "Amount"
+msgstr "مقدار"
+
+msgctxt "field:sale.opportunity_employee,company:"
+msgid "Company"
+msgstr "شرکت"
+
+msgctxt "field:sale.opportunity_employee,conversion_amount_rate:"
+msgid "Conversion Amount Rate"
+msgstr "نرخ تغییر مبلغ"
+
+msgctxt "field:sale.opportunity_employee,conversion_rate:"
+msgid "Conversion Rate"
+msgstr "نرخ تبدیل"
+
+msgctxt "field:sale.opportunity_employee,converted:"
+msgid "Converted"
+msgstr "تبدیل شده"
+
+msgctxt "field:sale.opportunity_employee,converted_amount:"
+msgid "Converted Amount"
+msgstr "مقدار تبدیل شده"
+
+msgctxt "field:sale.opportunity_employee,currency:"
+msgid "Currency"
+msgstr "واحد پول"
+
+msgctxt "field:sale.opportunity_employee,currency_digits:"
+msgid "Currency Digits"
+msgstr "رقم های واحد پول"
+
+msgctxt "field:sale.opportunity_employee,employee:"
+msgid "Employee"
+msgstr "کارمند"
+
+msgctxt "field:sale.opportunity_employee,lost:"
+msgid "Lost"
+msgstr "گم شده"
+
+msgctxt "field:sale.opportunity_employee,number:"
+msgid "Number"
+msgstr "شماره"
+
+msgctxt "field:sale.opportunity_employee,winning_amount_rate:"
+msgid "Winning Amount Rate"
+msgstr "نرخ برد مبلغ"
+
+msgctxt "field:sale.opportunity_employee,winning_rate:"
+msgid "Winning Rate"
+msgstr "نرخ برد"
+
+msgctxt "field:sale.opportunity_employee,won:"
+msgid "Won"
+msgstr "برد"
+
+msgctxt "field:sale.opportunity_employee,won_amount:"
+msgid "Won Amount"
+msgstr "مقدار برد"
+
+msgctxt "field:sale.opportunity_employee.context,end_date:"
+msgid "End Date"
+msgstr "تاریخ پایان"
+
+msgctxt "field:sale.opportunity_employee.context,start_date:"
+msgid "Start Date"
+msgstr "تاریخ شروع"
+
+msgctxt "field:sale.opportunity_employee_monthly,amount:"
+msgid "Amount"
+msgstr "مقدار"
+
+msgctxt "field:sale.opportunity_employee_monthly,company:"
+msgid "Company"
+msgstr "شرکت"
+
+msgctxt "field:sale.opportunity_employee_monthly,conversion_amount_rate:"
+msgid "Conversion Amount Rate"
+msgstr "نرخ تبدیل مقدار"
+
+msgctxt "field:sale.opportunity_employee_monthly,conversion_rate:"
+msgid "Conversion Rate"
+msgstr "نرخ تبدیل"
+
+msgctxt "field:sale.opportunity_employee_monthly,converted:"
+msgid "Converted"
+msgstr "تبدیل شده"
+
+msgctxt "field:sale.opportunity_employee_monthly,converted_amount:"
+msgid "Converted Amount"
+msgstr "مقدار تبدیل شده"
+
+msgctxt "field:sale.opportunity_employee_monthly,currency:"
+msgid "Currency"
+msgstr "واحد پول"
+
+msgctxt "field:sale.opportunity_employee_monthly,currency_digits:"
+msgid "Currency Digits"
+msgstr "رقم های واحد پول"
+
+msgctxt "field:sale.opportunity_employee_monthly,employee:"
+msgid "Employee"
+msgstr "کارمند"
+
+msgctxt "field:sale.opportunity_employee_monthly,lost:"
+msgid "Lost"
+msgstr "گم شده"
+
+msgctxt "field:sale.opportunity_employee_monthly,month:"
+msgid "Month"
+msgstr "ماه"
+
+msgctxt "field:sale.opportunity_employee_monthly,number:"
+msgid "Number"
+msgstr "شماره"
+
+msgctxt "field:sale.opportunity_employee_monthly,winning_amount_rate:"
+msgid "Winning Amount Rate"
+msgstr "نرخ برد مبلغ"
+
+msgctxt "field:sale.opportunity_employee_monthly,winning_rate:"
+msgid "Winning Rate"
+msgstr "نرخ برد"
+
+msgctxt "field:sale.opportunity_employee_monthly,won:"
+msgid "Won"
+msgstr "برد"
+
+msgctxt "field:sale.opportunity_employee_monthly,won_amount:"
+msgid "Won Amount"
+msgstr "مقدار برد"
+
+msgctxt "field:sale.opportunity_employee_monthly,year:"
+msgid "Year"
+msgstr "سال"
+
+msgctxt "field:sale.opportunity_monthly,amount:"
+msgid "Amount"
+msgstr "مقدار"
+
+msgctxt "field:sale.opportunity_monthly,company:"
+msgid "Company"
+msgstr "شرکت"
+
+msgctxt "field:sale.opportunity_monthly,conversion_amount_rate:"
+msgid "Conversion Amount Rate"
+msgstr "نرخ تبدیل مقدار"
+
+msgctxt "field:sale.opportunity_monthly,conversion_rate:"
+msgid "Conversion Rate"
+msgstr "نرخ تبدیل"
+
+msgctxt "field:sale.opportunity_monthly,converted:"
+msgid "Converted"
+msgstr "تبدیل شده"
+
+msgctxt "field:sale.opportunity_monthly,converted_amount:"
+msgid "Converted Amount"
+msgstr "مقدار تبدیل شده"
+
+msgctxt "field:sale.opportunity_monthly,currency:"
+msgid "Currency"
+msgstr "واحد پول"
+
+msgctxt "field:sale.opportunity_monthly,currency_digits:"
+msgid "Currency Digits"
+msgstr "رقم های واحد پول"
+
+msgctxt "field:sale.opportunity_monthly,lost:"
+msgid "Lost"
+msgstr "گم شده"
+
+msgctxt "field:sale.opportunity_monthly,month:"
+msgid "Month"
+msgstr "ماه"
+
+msgctxt "field:sale.opportunity_monthly,number:"
+msgid "Number"
+msgstr "شماره"
+
+msgctxt "field:sale.opportunity_monthly,winning_amount_rate:"
+msgid "Winning Amount Rate"
+msgstr "نرخ برد مبلغ"
+
+msgctxt "field:sale.opportunity_monthly,winning_rate:"
+msgid "Winning Rate"
+msgstr "نرخ برد"
+
+msgctxt "field:sale.opportunity_monthly,won:"
+msgid "Won"
+msgstr "برد"
+
+msgctxt "field:sale.opportunity_monthly,won_amount:"
+msgid "Won Amount"
+msgstr "مقدار برد"
+
+msgctxt "field:sale.opportunity_monthly,year:"
+msgid "Year"
+msgstr "سال"
+
+msgctxt "field:sale.opportunity_monthly,year_month:"
+msgid "Year-Month"
+msgstr "سال - ماه"
+
+#, fuzzy
+msgctxt "help:sale.opportunity,amount:"
+msgid "Estimated revenue amount."
+msgstr "مقدار درآمد تخمینی"
+
+#, fuzzy
+msgctxt "help:sale.opportunity,conversion_probability:"
+msgid "Percentage between 0 and 100."
+msgstr "درصد بین 0 و 100"
+
+msgctxt "model:ir.action,name:act_open_sale_form"
+msgid "Sales"
+msgstr "فروش ها"
+
+msgctxt "model:ir.action,name:act_opportunity_employee_form"
+msgid "Opportunities per Employee"
+msgstr "فرصت ها در هر کارمند"
+
+msgctxt "model:ir.action,name:act_opportunity_employee_monthly_form"
+msgid "Opportunities per Employee per Month"
+msgstr "فرصت های هر کارمند در هر ماه"
+
+msgctxt "model:ir.action,name:act_opportunity_form"
+msgid "Leads and Opportunities"
+msgstr "فرصت ها و راهبردها"
+
+msgctxt "model:ir.action,name:act_opportunity_form2"
+msgid "Sales Leads/Opportunities"
+msgstr "فرصت ها/راهبردهای فروش"
+
+msgctxt "model:ir.action,name:act_opportunity_monthly_form"
+msgid "Opportunities per Month"
+msgstr "فرصت ها در هر ماه"
+
+msgctxt ""
+"model:ir.action.act_window.domain,name:act_opportunity_form_domain_all"
+msgid "All"
+msgstr "همه"
+
+msgctxt ""
+"model:ir.action.act_window.domain,name:act_opportunity_form_domain_cancelled"
+msgid "Cancelled"
+msgstr "لغو شده"
+
+msgctxt ""
+"model:ir.action.act_window.domain,name:act_opportunity_form_domain_converted"
+msgid "Converted"
+msgstr "تبدیل شده"
+
+msgctxt ""
+"model:ir.action.act_window.domain,name:act_opportunity_form_domain_leads"
+msgid "Leads"
+msgstr "راهبردها"
+
+msgctxt ""
+"model:ir.action.act_window.domain,name:act_opportunity_form_domain_lost"
+msgid "Lost"
+msgstr "گم شده"
+
+msgctxt ""
+"model:ir.action.act_window.domain,name:act_opportunity_form_domain_opportunities"
+msgid "Opportunities"
+msgstr "فرصت ها"
+
+msgctxt ""
+"model:ir.action.act_window.domain,name:act_opportunity_form_domain_won"
+msgid "Won"
+msgstr "برد"
+
+msgctxt "model:ir.message,text:msg_modify_origin_opportunity"
+msgid "You cannot modify the opportunity origin of the sale \"%(sale)s\"."
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_opportunity_delete_cancel"
+msgid "To delete opportunity \"%(opportunity)s\", you must cancel it."
+msgstr "برای حذف فرصت :\"%(opportunity)s\" شما باید ابتدا آنرا لغو کنید."
+
+msgctxt "model:ir.model.button,string:opportunity_cancel_button"
+msgid "Cancel"
+msgstr "Cancel"
+
+msgctxt "model:ir.model.button,string:opportunity_convert_button"
+msgid "Convert to Sale"
+msgstr "Convert to Sale"
+
+msgctxt "model:ir.model.button,string:opportunity_lead_button"
+msgid "Set as Lead"
+msgstr "Set as Lead"
+
+msgctxt "model:ir.model.button,string:opportunity_lost_button"
+msgid "Mark as Lost"
+msgstr "Mark as Lost"
+
+msgctxt "model:ir.model.button,string:opportunity_opportunity_button"
+msgid "Convert to Opportunity"
+msgstr "Convert to Opportunity"
+
+msgctxt "model:ir.rule.group,name:rule_group_opportunity_companies"
+msgid "User in companies"
+msgstr ""
+
+msgctxt "model:ir.rule.group,name:rule_group_opportunity_employee_companies"
+msgid "User in companies"
+msgstr ""
+
+msgctxt ""
+"model:ir.rule.group,name:rule_group_opportunity_employee_monthly_companies"
+msgid "User in companies"
+msgstr ""
+
+msgctxt "model:ir.rule.group,name:rule_group_opportunity_monthly_companies"
+msgid "User in companies"
+msgstr ""
+
+msgctxt "model:ir.sequence,name:sequence_sale_opportunity"
+msgid "Sale Opportunity"
+msgstr "فرصت فروش"
+
+msgctxt "model:ir.sequence.type,name:sequence_type_sale_opportunity"
+msgid "Sale Opportunity"
+msgstr "فرصت فروش"
+
+msgctxt "model:ir.ui.menu,name:menu_opportunity_employee_monthly_form"
+msgid "Opportunities per Employee per Month"
+msgstr "فرصت های هر کارمند در هر ماه"
+
+msgctxt "model:ir.ui.menu,name:menu_opportunity_employee_open"
+msgid "Opportunities per Employee"
+msgstr "فرصت ها در هر کارمند"
+
+msgctxt "model:ir.ui.menu,name:menu_opportunity_form"
+msgid "Leads and Opportunities"
+msgstr "فرصت ها و راهبردها"
+
+msgctxt "model:ir.ui.menu,name:menu_opportunity_monthly_form"
+msgid "Opportunities per Month"
+msgstr "فرصت ها در هر ماه"
+
+msgctxt "model:res.group,name:group_opportunity"
+msgid "Sale Opportunity"
+msgstr "فرصت فروش"
+
+msgctxt "model:sale.opportunity,name:"
+msgid "Sale Opportunity"
+msgstr "فرصت فروش"
+
+msgctxt "model:sale.opportunity.line,name:"
+msgid "Sale Opportunity Line"
+msgstr "سطر فرصت فروش"
+
+msgctxt "model:sale.opportunity_employee,name:"
+msgid "Sale Opportunity per Employee"
+msgstr "فرصت فروش در هر کارمند"
+
+msgctxt "model:sale.opportunity_employee.context,name:"
+msgid "Sale Opportunity per Employee Context"
+msgstr "مفاد فرصت فروش در هر کارمند"
+
+msgctxt "model:sale.opportunity_employee_monthly,name:"
+msgid "Sale Opportunity per Employee per Month"
+msgstr "فرصت های فروش هر کارمند در هر ماه"
+
+msgctxt "model:sale.opportunity_monthly,name:"
+msgid "Sale Opportunity per Month"
+msgstr "فرصت های فروش در هر ماه"
+
+msgctxt "selection:sale.opportunity,state:"
+msgid "Cancelled"
+msgstr "لغو شده"
+
+msgctxt "selection:sale.opportunity,state:"
+msgid "Converted"
+msgstr "تبدیل شده"
+
+msgctxt "selection:sale.opportunity,state:"
+msgid "Lead"
+msgstr "هدایت کردن"
+
+msgctxt "selection:sale.opportunity,state:"
+msgid "Lost"
+msgstr "گم شده"
+
+msgctxt "selection:sale.opportunity,state:"
+msgid "Opportunity"
+msgstr "فرصت"
+
+msgctxt "selection:sale.opportunity,state:"
+msgid "Won"
+msgstr "برنده"
+
+msgctxt "view:sale.opportunity:"
+msgid "%"
+msgstr "%"
+
+msgctxt "view:sale.opportunity:"
+msgid "Lead/Opportunity"
+msgstr "هدایت / فرصت"
+
+msgctxt "view:sale.opportunity_employee:"
+msgid "%"
+msgstr "%"
+
+msgctxt "view:sale.opportunity_employee_monthly:"
+msgid "%"
+msgstr "%"
+
+msgctxt "view:sale.opportunity_monthly:"
+msgid "%"
+msgstr "%"
diff --git a/modules/sale_opportunity/locale/fi.po b/modules/sale_opportunity/locale/fi.po
new file mode 100644
index 0000000000..86cbbd814d
--- /dev/null
+++ b/modules/sale_opportunity/locale/fi.po
@@ -0,0 +1,559 @@
+#
+msgid ""
+msgstr "Content-Type: text/plain; charset=utf-8\n"
+
+msgctxt "field:sale.configuration,sale_opportunity_sequence:"
+msgid "Opportunity Sequence"
+msgstr ""
+
+msgctxt "field:sale.configuration.sequence,sale_opportunity_sequence:"
+msgid "Opportunity Sequence"
+msgstr ""
+
+msgctxt "field:sale.opportunity,address:"
+msgid "Address"
+msgstr ""
+
+msgctxt "field:sale.opportunity,amount:"
+msgid "Amount"
+msgstr ""
+
+msgctxt "field:sale.opportunity,comment:"
+msgid "Comment"
+msgstr ""
+
+msgctxt "field:sale.opportunity,company:"
+msgid "Company"
+msgstr ""
+
+msgctxt "field:sale.opportunity,contact:"
+msgid "Contact"
+msgstr ""
+
+msgctxt "field:sale.opportunity,conversion_probability:"
+msgid "Conversion Probability"
+msgstr ""
+
+#, fuzzy
+msgctxt "field:sale.opportunity,converted_by:"
+msgid "Converted By"
+msgstr "Converted"
+
+msgctxt "field:sale.opportunity,currency:"
+msgid "Currency"
+msgstr ""
+
+msgctxt "field:sale.opportunity,currency_digits:"
+msgid "Currency Digits"
+msgstr ""
+
+msgctxt "field:sale.opportunity,description:"
+msgid "Description"
+msgstr ""
+
+msgctxt "field:sale.opportunity,employee:"
+msgid "Employee"
+msgstr ""
+
+msgctxt "field:sale.opportunity,end_date:"
+msgid "End Date"
+msgstr ""
+
+msgctxt "field:sale.opportunity,lines:"
+msgid "Lines"
+msgstr ""
+
+msgctxt "field:sale.opportunity,lost_reason:"
+msgid "Reason for loss"
+msgstr ""
+
+msgctxt "field:sale.opportunity,number:"
+msgid "Number"
+msgstr ""
+
+msgctxt "field:sale.opportunity,party:"
+msgid "Party"
+msgstr ""
+
+msgctxt "field:sale.opportunity,payment_term:"
+msgid "Payment Term"
+msgstr ""
+
+msgctxt "field:sale.opportunity,reference:"
+msgid "Reference"
+msgstr ""
+
+#, fuzzy
+msgctxt "field:sale.opportunity,sales:"
+msgid "Sales"
+msgstr "Sales"
+
+msgctxt "field:sale.opportunity,start_date:"
+msgid "Start Date"
+msgstr ""
+
+msgctxt "field:sale.opportunity,state:"
+msgid "State"
+msgstr ""
+
+#, fuzzy
+msgctxt "field:sale.opportunity.line,opportunity:"
+msgid "Opportunity"
+msgstr "Opportunities"
+
+msgctxt "field:sale.opportunity.line,opportunity_state:"
+msgid "Opportunity State"
+msgstr ""
+
+msgctxt "field:sale.opportunity.line,product:"
+msgid "Product"
+msgstr ""
+
+msgctxt "field:sale.opportunity.line,quantity:"
+msgid "Quantity"
+msgstr ""
+
+msgctxt "field:sale.opportunity.line,unit:"
+msgid "Unit"
+msgstr ""
+
+msgctxt "field:sale.opportunity.line,unit_digits:"
+msgid "Unit Digits"
+msgstr ""
+
+msgctxt "field:sale.opportunity_employee,amount:"
+msgid "Amount"
+msgstr ""
+
+msgctxt "field:sale.opportunity_employee,company:"
+msgid "Company"
+msgstr ""
+
+msgctxt "field:sale.opportunity_employee,conversion_amount_rate:"
+msgid "Conversion Amount Rate"
+msgstr ""
+
+msgctxt "field:sale.opportunity_employee,conversion_rate:"
+msgid "Conversion Rate"
+msgstr ""
+
+#, fuzzy
+msgctxt "field:sale.opportunity_employee,converted:"
+msgid "Converted"
+msgstr "Converted"
+
+msgctxt "field:sale.opportunity_employee,converted_amount:"
+msgid "Converted Amount"
+msgstr ""
+
+msgctxt "field:sale.opportunity_employee,currency:"
+msgid "Currency"
+msgstr ""
+
+msgctxt "field:sale.opportunity_employee,currency_digits:"
+msgid "Currency Digits"
+msgstr ""
+
+msgctxt "field:sale.opportunity_employee,employee:"
+msgid "Employee"
+msgstr ""
+
+#, fuzzy
+msgctxt "field:sale.opportunity_employee,lost:"
+msgid "Lost"
+msgstr "Lost"
+
+msgctxt "field:sale.opportunity_employee,number:"
+msgid "Number"
+msgstr ""
+
+msgctxt "field:sale.opportunity_employee,winning_amount_rate:"
+msgid "Winning Amount Rate"
+msgstr ""
+
+msgctxt "field:sale.opportunity_employee,winning_rate:"
+msgid "Winning Rate"
+msgstr ""
+
+#, fuzzy
+msgctxt "field:sale.opportunity_employee,won:"
+msgid "Won"
+msgstr "Won"
+
+msgctxt "field:sale.opportunity_employee,won_amount:"
+msgid "Won Amount"
+msgstr ""
+
+msgctxt "field:sale.opportunity_employee.context,end_date:"
+msgid "End Date"
+msgstr ""
+
+msgctxt "field:sale.opportunity_employee.context,start_date:"
+msgid "Start Date"
+msgstr ""
+
+msgctxt "field:sale.opportunity_employee_monthly,amount:"
+msgid "Amount"
+msgstr ""
+
+msgctxt "field:sale.opportunity_employee_monthly,company:"
+msgid "Company"
+msgstr ""
+
+msgctxt "field:sale.opportunity_employee_monthly,conversion_amount_rate:"
+msgid "Conversion Amount Rate"
+msgstr ""
+
+msgctxt "field:sale.opportunity_employee_monthly,conversion_rate:"
+msgid "Conversion Rate"
+msgstr ""
+
+#, fuzzy
+msgctxt "field:sale.opportunity_employee_monthly,converted:"
+msgid "Converted"
+msgstr "Converted"
+
+msgctxt "field:sale.opportunity_employee_monthly,converted_amount:"
+msgid "Converted Amount"
+msgstr ""
+
+msgctxt "field:sale.opportunity_employee_monthly,currency:"
+msgid "Currency"
+msgstr ""
+
+msgctxt "field:sale.opportunity_employee_monthly,currency_digits:"
+msgid "Currency Digits"
+msgstr ""
+
+msgctxt "field:sale.opportunity_employee_monthly,employee:"
+msgid "Employee"
+msgstr ""
+
+#, fuzzy
+msgctxt "field:sale.opportunity_employee_monthly,lost:"
+msgid "Lost"
+msgstr "Lost"
+
+msgctxt "field:sale.opportunity_employee_monthly,month:"
+msgid "Month"
+msgstr ""
+
+msgctxt "field:sale.opportunity_employee_monthly,number:"
+msgid "Number"
+msgstr ""
+
+msgctxt "field:sale.opportunity_employee_monthly,winning_amount_rate:"
+msgid "Winning Amount Rate"
+msgstr ""
+
+msgctxt "field:sale.opportunity_employee_monthly,winning_rate:"
+msgid "Winning Rate"
+msgstr ""
+
+#, fuzzy
+msgctxt "field:sale.opportunity_employee_monthly,won:"
+msgid "Won"
+msgstr "Won"
+
+msgctxt "field:sale.opportunity_employee_monthly,won_amount:"
+msgid "Won Amount"
+msgstr ""
+
+msgctxt "field:sale.opportunity_employee_monthly,year:"
+msgid "Year"
+msgstr ""
+
+msgctxt "field:sale.opportunity_monthly,amount:"
+msgid "Amount"
+msgstr ""
+
+msgctxt "field:sale.opportunity_monthly,company:"
+msgid "Company"
+msgstr ""
+
+msgctxt "field:sale.opportunity_monthly,conversion_amount_rate:"
+msgid "Conversion Amount Rate"
+msgstr ""
+
+msgctxt "field:sale.opportunity_monthly,conversion_rate:"
+msgid "Conversion Rate"
+msgstr ""
+
+#, fuzzy
+msgctxt "field:sale.opportunity_monthly,converted:"
+msgid "Converted"
+msgstr "Converted"
+
+msgctxt "field:sale.opportunity_monthly,converted_amount:"
+msgid "Converted Amount"
+msgstr ""
+
+msgctxt "field:sale.opportunity_monthly,currency:"
+msgid "Currency"
+msgstr ""
+
+msgctxt "field:sale.opportunity_monthly,currency_digits:"
+msgid "Currency Digits"
+msgstr ""
+
+#, fuzzy
+msgctxt "field:sale.opportunity_monthly,lost:"
+msgid "Lost"
+msgstr "Lost"
+
+msgctxt "field:sale.opportunity_monthly,month:"
+msgid "Month"
+msgstr ""
+
+msgctxt "field:sale.opportunity_monthly,number:"
+msgid "Number"
+msgstr ""
+
+msgctxt "field:sale.opportunity_monthly,winning_amount_rate:"
+msgid "Winning Amount Rate"
+msgstr ""
+
+msgctxt "field:sale.opportunity_monthly,winning_rate:"
+msgid "Winning Rate"
+msgstr ""
+
+#, fuzzy
+msgctxt "field:sale.opportunity_monthly,won:"
+msgid "Won"
+msgstr "Won"
+
+msgctxt "field:sale.opportunity_monthly,won_amount:"
+msgid "Won Amount"
+msgstr ""
+
+msgctxt "field:sale.opportunity_monthly,year:"
+msgid "Year"
+msgstr ""
+
+msgctxt "field:sale.opportunity_monthly,year_month:"
+msgid "Year-Month"
+msgstr ""
+
+msgctxt "help:sale.opportunity,amount:"
+msgid "Estimated revenue amount."
+msgstr ""
+
+msgctxt "help:sale.opportunity,conversion_probability:"
+msgid "Percentage between 0 and 100."
+msgstr ""
+
+msgctxt "model:ir.action,name:act_open_sale_form"
+msgid "Sales"
+msgstr "Sales"
+
+msgctxt "model:ir.action,name:act_opportunity_employee_form"
+msgid "Opportunities per Employee"
+msgstr "Opportunities per Employee"
+
+msgctxt "model:ir.action,name:act_opportunity_employee_monthly_form"
+msgid "Opportunities per Employee per Month"
+msgstr "Opportunities per Employee per Month"
+
+msgctxt "model:ir.action,name:act_opportunity_form"
+msgid "Leads and Opportunities"
+msgstr "Leads and Opportunities"
+
+msgctxt "model:ir.action,name:act_opportunity_form2"
+msgid "Sales Leads/Opportunities"
+msgstr "Sales Leads/Opportunities"
+
+msgctxt "model:ir.action,name:act_opportunity_monthly_form"
+msgid "Opportunities per Month"
+msgstr "Opportunities per Month"
+
+msgctxt ""
+"model:ir.action.act_window.domain,name:act_opportunity_form_domain_all"
+msgid "All"
+msgstr "All"
+
+msgctxt ""
+"model:ir.action.act_window.domain,name:act_opportunity_form_domain_cancelled"
+msgid "Cancelled"
+msgstr "Cancelled"
+
+msgctxt ""
+"model:ir.action.act_window.domain,name:act_opportunity_form_domain_converted"
+msgid "Converted"
+msgstr "Converted"
+
+msgctxt ""
+"model:ir.action.act_window.domain,name:act_opportunity_form_domain_leads"
+msgid "Leads"
+msgstr "Leads"
+
+msgctxt ""
+"model:ir.action.act_window.domain,name:act_opportunity_form_domain_lost"
+msgid "Lost"
+msgstr "Lost"
+
+msgctxt ""
+"model:ir.action.act_window.domain,name:act_opportunity_form_domain_opportunities"
+msgid "Opportunities"
+msgstr "Opportunities"
+
+msgctxt ""
+"model:ir.action.act_window.domain,name:act_opportunity_form_domain_won"
+msgid "Won"
+msgstr "Won"
+
+msgctxt "model:ir.message,text:msg_modify_origin_opportunity"
+msgid "You cannot modify the opportunity origin of the sale \"%(sale)s\"."
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_opportunity_delete_cancel"
+msgid "To delete opportunity \"%(opportunity)s\", you must cancel it."
+msgstr ""
+
+msgctxt "model:ir.model.button,string:opportunity_cancel_button"
+msgid "Cancel"
+msgstr "Cancel"
+
+msgctxt "model:ir.model.button,string:opportunity_convert_button"
+msgid "Convert to Sale"
+msgstr "Convert to Sale"
+
+msgctxt "model:ir.model.button,string:opportunity_lead_button"
+msgid "Set as Lead"
+msgstr "Set as Lead"
+
+msgctxt "model:ir.model.button,string:opportunity_lost_button"
+msgid "Mark as Lost"
+msgstr "Mark as Lost"
+
+msgctxt "model:ir.model.button,string:opportunity_opportunity_button"
+msgid "Convert to Opportunity"
+msgstr "Convert to Opportunity"
+
+msgctxt "model:ir.rule.group,name:rule_group_opportunity_companies"
+msgid "User in companies"
+msgstr ""
+
+msgctxt "model:ir.rule.group,name:rule_group_opportunity_employee_companies"
+msgid "User in companies"
+msgstr ""
+
+msgctxt ""
+"model:ir.rule.group,name:rule_group_opportunity_employee_monthly_companies"
+msgid "User in companies"
+msgstr ""
+
+msgctxt "model:ir.rule.group,name:rule_group_opportunity_monthly_companies"
+msgid "User in companies"
+msgstr ""
+
+msgctxt "model:ir.sequence,name:sequence_sale_opportunity"
+msgid "Sale Opportunity"
+msgstr "Sale Opportunity"
+
+msgctxt "model:ir.sequence.type,name:sequence_type_sale_opportunity"
+msgid "Sale Opportunity"
+msgstr "Sale Opportunity"
+
+msgctxt "model:ir.ui.menu,name:menu_opportunity_employee_monthly_form"
+msgid "Opportunities per Employee per Month"
+msgstr "Opportunities per Employee per Month"
+
+msgctxt "model:ir.ui.menu,name:menu_opportunity_employee_open"
+msgid "Opportunities per Employee"
+msgstr "Opportunities per Employee"
+
+msgctxt "model:ir.ui.menu,name:menu_opportunity_form"
+msgid "Leads and Opportunities"
+msgstr "Leads and Opportunities"
+
+msgctxt "model:ir.ui.menu,name:menu_opportunity_monthly_form"
+msgid "Opportunities per Month"
+msgstr "Opportunities per Month"
+
+msgctxt "model:res.group,name:group_opportunity"
+msgid "Sale Opportunity"
+msgstr "Sale Opportunity"
+
+#, fuzzy
+msgctxt "model:sale.opportunity,name:"
+msgid "Sale Opportunity"
+msgstr "Sale Opportunity"
+
+#, fuzzy
+msgctxt "model:sale.opportunity.line,name:"
+msgid "Sale Opportunity Line"
+msgstr "Sale Opportunity"
+
+#, fuzzy
+msgctxt "model:sale.opportunity_employee,name:"
+msgid "Sale Opportunity per Employee"
+msgstr "Opportunities per Employee per Month"
+
+#, fuzzy
+msgctxt "model:sale.opportunity_employee.context,name:"
+msgid "Sale Opportunity per Employee Context"
+msgstr "Opportunities per Employee per Month"
+
+#, fuzzy
+msgctxt "model:sale.opportunity_employee_monthly,name:"
+msgid "Sale Opportunity per Employee per Month"
+msgstr "Opportunities per Employee per Month"
+
+#, fuzzy
+msgctxt "model:sale.opportunity_monthly,name:"
+msgid "Sale Opportunity per Month"
+msgstr "Opportunities per Employee per Month"
+
+#, fuzzy
+msgctxt "selection:sale.opportunity,state:"
+msgid "Cancelled"
+msgstr "Cancelled"
+
+#, fuzzy
+msgctxt "selection:sale.opportunity,state:"
+msgid "Converted"
+msgstr "Converted"
+
+#, fuzzy
+msgctxt "selection:sale.opportunity,state:"
+msgid "Lead"
+msgstr "Leads"
+
+#, fuzzy
+msgctxt "selection:sale.opportunity,state:"
+msgid "Lost"
+msgstr "Lost"
+
+#, fuzzy
+msgctxt "selection:sale.opportunity,state:"
+msgid "Opportunity"
+msgstr "Opportunities"
+
+#, fuzzy
+msgctxt "selection:sale.opportunity,state:"
+msgid "Won"
+msgstr "Won"
+
+#, fuzzy
+msgctxt "view:sale.opportunity:"
+msgid "%"
+msgstr "%"
+
+msgctxt "view:sale.opportunity:"
+msgid "Lead/Opportunity"
+msgstr ""
+
+#, fuzzy
+msgctxt "view:sale.opportunity_employee:"
+msgid "%"
+msgstr "%"
+
+#, fuzzy
+msgctxt "view:sale.opportunity_employee_monthly:"
+msgid "%"
+msgstr "%"
+
+#, fuzzy
+msgctxt "view:sale.opportunity_monthly:"
+msgid "%"
+msgstr "%"
diff --git a/modules/sale_opportunity/locale/fr.po b/modules/sale_opportunity/locale/fr.po
new file mode 100644
index 0000000000..1fff67ee69
--- /dev/null
+++ b/modules/sale_opportunity/locale/fr.po
@@ -0,0 +1,534 @@
+#
+msgid ""
+msgstr "Content-Type: text/plain; charset=utf-8\n"
+
+msgctxt "field:sale.configuration,sale_opportunity_sequence:"
+msgid "Opportunity Sequence"
+msgstr "Séquence d'opportunité"
+
+msgctxt "field:sale.configuration.sequence,sale_opportunity_sequence:"
+msgid "Opportunity Sequence"
+msgstr "Séquence d'opportunité"
+
+msgctxt "field:sale.opportunity,address:"
+msgid "Address"
+msgstr "Adresse"
+
+msgctxt "field:sale.opportunity,amount:"
+msgid "Amount"
+msgstr "Montant"
+
+msgctxt "field:sale.opportunity,comment:"
+msgid "Comment"
+msgstr "Commentaire"
+
+msgctxt "field:sale.opportunity,company:"
+msgid "Company"
+msgstr "Société"
+
+msgctxt "field:sale.opportunity,contact:"
+msgid "Contact"
+msgstr "Contact"
+
+msgctxt "field:sale.opportunity,conversion_probability:"
+msgid "Conversion Probability"
+msgstr "Probabilité de conversion"
+
+msgctxt "field:sale.opportunity,converted_by:"
+msgid "Converted By"
+msgstr "Convertie par"
+
+msgctxt "field:sale.opportunity,currency:"
+msgid "Currency"
+msgstr "Devise"
+
+msgctxt "field:sale.opportunity,currency_digits:"
+msgid "Currency Digits"
+msgstr "Décimales de la devise"
+
+msgctxt "field:sale.opportunity,description:"
+msgid "Description"
+msgstr "Description"
+
+msgctxt "field:sale.opportunity,employee:"
+msgid "Employee"
+msgstr "Employé"
+
+msgctxt "field:sale.opportunity,end_date:"
+msgid "End Date"
+msgstr "Date de fin"
+
+msgctxt "field:sale.opportunity,lines:"
+msgid "Lines"
+msgstr "Lignes"
+
+msgctxt "field:sale.opportunity,lost_reason:"
+msgid "Reason for loss"
+msgstr "Raison de la perte"
+
+msgctxt "field:sale.opportunity,number:"
+msgid "Number"
+msgstr "Numéro"
+
+msgctxt "field:sale.opportunity,party:"
+msgid "Party"
+msgstr "Tiers"
+
+msgctxt "field:sale.opportunity,payment_term:"
+msgid "Payment Term"
+msgstr "Conditions de paiement"
+
+msgctxt "field:sale.opportunity,reference:"
+msgid "Reference"
+msgstr "Référence"
+
+msgctxt "field:sale.opportunity,sales:"
+msgid "Sales"
+msgstr "Ventes"
+
+msgctxt "field:sale.opportunity,start_date:"
+msgid "Start Date"
+msgstr "Date de début"
+
+msgctxt "field:sale.opportunity,state:"
+msgid "State"
+msgstr "État"
+
+msgctxt "field:sale.opportunity.line,opportunity:"
+msgid "Opportunity"
+msgstr "Opportunité"
+
+msgctxt "field:sale.opportunity.line,opportunity_state:"
+msgid "Opportunity State"
+msgstr "État de l'opportunité"
+
+msgctxt "field:sale.opportunity.line,product:"
+msgid "Product"
+msgstr "Produit"
+
+msgctxt "field:sale.opportunity.line,quantity:"
+msgid "Quantity"
+msgstr "Quantité"
+
+msgctxt "field:sale.opportunity.line,unit:"
+msgid "Unit"
+msgstr "Unité"
+
+msgctxt "field:sale.opportunity.line,unit_digits:"
+msgid "Unit Digits"
+msgstr "Décimales de l'unité"
+
+msgctxt "field:sale.opportunity_employee,amount:"
+msgid "Amount"
+msgstr "Montant"
+
+msgctxt "field:sale.opportunity_employee,company:"
+msgid "Company"
+msgstr "Société"
+
+msgctxt "field:sale.opportunity_employee,conversion_amount_rate:"
+msgid "Conversion Amount Rate"
+msgstr "Taux de conversion des montants"
+
+msgctxt "field:sale.opportunity_employee,conversion_rate:"
+msgid "Conversion Rate"
+msgstr "Taux de conversion"
+
+msgctxt "field:sale.opportunity_employee,converted:"
+msgid "Converted"
+msgstr "Convertie"
+
+msgctxt "field:sale.opportunity_employee,converted_amount:"
+msgid "Converted Amount"
+msgstr "Montant convertit"
+
+msgctxt "field:sale.opportunity_employee,currency:"
+msgid "Currency"
+msgstr "Devise"
+
+msgctxt "field:sale.opportunity_employee,currency_digits:"
+msgid "Currency Digits"
+msgstr "Décimales de la devise"
+
+msgctxt "field:sale.opportunity_employee,employee:"
+msgid "Employee"
+msgstr "Employé"
+
+msgctxt "field:sale.opportunity_employee,lost:"
+msgid "Lost"
+msgstr "Perdue"
+
+msgctxt "field:sale.opportunity_employee,number:"
+msgid "Number"
+msgstr "Nombre"
+
+msgctxt "field:sale.opportunity_employee,winning_amount_rate:"
+msgid "Winning Amount Rate"
+msgstr "Taux du montant gagné"
+
+msgctxt "field:sale.opportunity_employee,winning_rate:"
+msgid "Winning Rate"
+msgstr "Taux gagnant"
+
+msgctxt "field:sale.opportunity_employee,won:"
+msgid "Won"
+msgstr "Gagnée"
+
+msgctxt "field:sale.opportunity_employee,won_amount:"
+msgid "Won Amount"
+msgstr "Montant gagné"
+
+msgctxt "field:sale.opportunity_employee.context,end_date:"
+msgid "End Date"
+msgstr "Date de fin"
+
+msgctxt "field:sale.opportunity_employee.context,start_date:"
+msgid "Start Date"
+msgstr "Date de début"
+
+msgctxt "field:sale.opportunity_employee_monthly,amount:"
+msgid "Amount"
+msgstr "Montant"
+
+msgctxt "field:sale.opportunity_employee_monthly,company:"
+msgid "Company"
+msgstr "Société"
+
+msgctxt "field:sale.opportunity_employee_monthly,conversion_amount_rate:"
+msgid "Conversion Amount Rate"
+msgstr "Taux de conversion des montants"
+
+msgctxt "field:sale.opportunity_employee_monthly,conversion_rate:"
+msgid "Conversion Rate"
+msgstr "Taux de conversion"
+
+msgctxt "field:sale.opportunity_employee_monthly,converted:"
+msgid "Converted"
+msgstr "Convertie"
+
+msgctxt "field:sale.opportunity_employee_monthly,converted_amount:"
+msgid "Converted Amount"
+msgstr "Montant converti"
+
+msgctxt "field:sale.opportunity_employee_monthly,currency:"
+msgid "Currency"
+msgstr "Devise"
+
+msgctxt "field:sale.opportunity_employee_monthly,currency_digits:"
+msgid "Currency Digits"
+msgstr "Décimales de la devise"
+
+msgctxt "field:sale.opportunity_employee_monthly,employee:"
+msgid "Employee"
+msgstr "Employé"
+
+msgctxt "field:sale.opportunity_employee_monthly,lost:"
+msgid "Lost"
+msgstr "Perdue"
+
+msgctxt "field:sale.opportunity_employee_monthly,month:"
+msgid "Month"
+msgstr "Mois"
+
+msgctxt "field:sale.opportunity_employee_monthly,number:"
+msgid "Number"
+msgstr "Nombre"
+
+msgctxt "field:sale.opportunity_employee_monthly,winning_amount_rate:"
+msgid "Winning Amount Rate"
+msgstr "Taux du montant gagné"
+
+msgctxt "field:sale.opportunity_employee_monthly,winning_rate:"
+msgid "Winning Rate"
+msgstr "Taux de réussite"
+
+msgctxt "field:sale.opportunity_employee_monthly,won:"
+msgid "Won"
+msgstr "Gagné"
+
+msgctxt "field:sale.opportunity_employee_monthly,won_amount:"
+msgid "Won Amount"
+msgstr "Montant gagné"
+
+msgctxt "field:sale.opportunity_employee_monthly,year:"
+msgid "Year"
+msgstr "Année"
+
+msgctxt "field:sale.opportunity_monthly,amount:"
+msgid "Amount"
+msgstr "Montant"
+
+msgctxt "field:sale.opportunity_monthly,company:"
+msgid "Company"
+msgstr "Société"
+
+msgctxt "field:sale.opportunity_monthly,conversion_amount_rate:"
+msgid "Conversion Amount Rate"
+msgstr "Taux de conversion des montants"
+
+msgctxt "field:sale.opportunity_monthly,conversion_rate:"
+msgid "Conversion Rate"
+msgstr "Taux de conversion"
+
+msgctxt "field:sale.opportunity_monthly,converted:"
+msgid "Converted"
+msgstr "Convertie"
+
+msgctxt "field:sale.opportunity_monthly,converted_amount:"
+msgid "Converted Amount"
+msgstr "Montant converti"
+
+msgctxt "field:sale.opportunity_monthly,currency:"
+msgid "Currency"
+msgstr "Devise"
+
+msgctxt "field:sale.opportunity_monthly,currency_digits:"
+msgid "Currency Digits"
+msgstr "Décimales de la devise"
+
+msgctxt "field:sale.opportunity_monthly,lost:"
+msgid "Lost"
+msgstr "Perdue"
+
+msgctxt "field:sale.opportunity_monthly,month:"
+msgid "Month"
+msgstr "Mois"
+
+msgctxt "field:sale.opportunity_monthly,number:"
+msgid "Number"
+msgstr "Nombre"
+
+msgctxt "field:sale.opportunity_monthly,winning_amount_rate:"
+msgid "Winning Amount Rate"
+msgstr "Taux du montant gagné"
+
+msgctxt "field:sale.opportunity_monthly,winning_rate:"
+msgid "Winning Rate"
+msgstr "Taux gagnant"
+
+msgctxt "field:sale.opportunity_monthly,won:"
+msgid "Won"
+msgstr "Gagnée"
+
+msgctxt "field:sale.opportunity_monthly,won_amount:"
+msgid "Won Amount"
+msgstr "Montant gagné"
+
+msgctxt "field:sale.opportunity_monthly,year:"
+msgid "Year"
+msgstr "Année"
+
+msgctxt "field:sale.opportunity_monthly,year_month:"
+msgid "Year-Month"
+msgstr "Année-Mois"
+
+msgctxt "help:sale.opportunity,amount:"
+msgid "Estimated revenue amount."
+msgstr "Revenu estimé."
+
+msgctxt "help:sale.opportunity,conversion_probability:"
+msgid "Percentage between 0 and 100."
+msgstr "Pourcentage entre 0 et 100."
+
+msgctxt "model:ir.action,name:act_open_sale_form"
+msgid "Sales"
+msgstr "Ventes"
+
+msgctxt "model:ir.action,name:act_opportunity_employee_form"
+msgid "Opportunities per Employee"
+msgstr "Opportunités par employé"
+
+msgctxt "model:ir.action,name:act_opportunity_employee_monthly_form"
+msgid "Opportunities per Employee per Month"
+msgstr "Opportunités par employé par mois"
+
+msgctxt "model:ir.action,name:act_opportunity_form"
+msgid "Leads and Opportunities"
+msgstr "Prospects et opportunités"
+
+msgctxt "model:ir.action,name:act_opportunity_form2"
+msgid "Sales Leads/Opportunities"
+msgstr "Prospects/Opportunités de ventes"
+
+msgctxt "model:ir.action,name:act_opportunity_monthly_form"
+msgid "Opportunities per Month"
+msgstr "Opportunités par mois"
+
+msgctxt ""
+"model:ir.action.act_window.domain,name:act_opportunity_form_domain_all"
+msgid "All"
+msgstr "Tous"
+
+msgctxt ""
+"model:ir.action.act_window.domain,name:act_opportunity_form_domain_cancelled"
+msgid "Cancelled"
+msgstr "Annulés"
+
+msgctxt ""
+"model:ir.action.act_window.domain,name:act_opportunity_form_domain_converted"
+msgid "Converted"
+msgstr "Convertis"
+
+msgctxt ""
+"model:ir.action.act_window.domain,name:act_opportunity_form_domain_leads"
+msgid "Leads"
+msgstr "Prospects"
+
+msgctxt ""
+"model:ir.action.act_window.domain,name:act_opportunity_form_domain_lost"
+msgid "Lost"
+msgstr "Perdus"
+
+msgctxt ""
+"model:ir.action.act_window.domain,name:act_opportunity_form_domain_opportunities"
+msgid "Opportunities"
+msgstr "Opportunités"
+
+msgctxt ""
+"model:ir.action.act_window.domain,name:act_opportunity_form_domain_won"
+msgid "Won"
+msgstr "Gagnés"
+
+msgctxt "model:ir.message,text:msg_modify_origin_opportunity"
+msgid "You cannot modify the opportunity origin of the sale \"%(sale)s\"."
+msgstr ""
+"Vous ne pouvez pas modifier l'origine d'opportunité de la vente "
+"« %(sale)s »."
+
+msgctxt "model:ir.message,text:msg_opportunity_delete_cancel"
+msgid "To delete opportunity \"%(opportunity)s\", you must cancel it."
+msgstr ""
+"Pour supprimer l’opportunité « %(opportunity)s », vous devez l'annuler."
+
+msgctxt "model:ir.model.button,string:opportunity_cancel_button"
+msgid "Cancel"
+msgstr "Annuler"
+
+msgctxt "model:ir.model.button,string:opportunity_convert_button"
+msgid "Convert to Sale"
+msgstr "Convertir en vente"
+
+msgctxt "model:ir.model.button,string:opportunity_lead_button"
+msgid "Set as Lead"
+msgstr "Reconvertir en contact"
+
+msgctxt "model:ir.model.button,string:opportunity_lost_button"
+msgid "Mark as Lost"
+msgstr "Marquer comme perdue"
+
+msgctxt "model:ir.model.button,string:opportunity_opportunity_button"
+msgid "Convert to Opportunity"
+msgstr "Convertir en opportunité"
+
+msgctxt "model:ir.rule.group,name:rule_group_opportunity_companies"
+msgid "User in companies"
+msgstr "Utilisateur dans les sociétés"
+
+msgctxt "model:ir.rule.group,name:rule_group_opportunity_employee_companies"
+msgid "User in companies"
+msgstr "Utilisateur dans les sociétés"
+
+msgctxt ""
+"model:ir.rule.group,name:rule_group_opportunity_employee_monthly_companies"
+msgid "User in companies"
+msgstr "Utilisateur dans les sociétés"
+
+msgctxt "model:ir.rule.group,name:rule_group_opportunity_monthly_companies"
+msgid "User in companies"
+msgstr "Utilisateur dans les sociétés"
+
+msgctxt "model:ir.sequence,name:sequence_sale_opportunity"
+msgid "Sale Opportunity"
+msgstr "Opportunité de vente"
+
+msgctxt "model:ir.sequence.type,name:sequence_type_sale_opportunity"
+msgid "Sale Opportunity"
+msgstr "Opportunité de vente"
+
+msgctxt "model:ir.ui.menu,name:menu_opportunity_employee_monthly_form"
+msgid "Opportunities per Employee per Month"
+msgstr "Opportunités par employé par mois"
+
+msgctxt "model:ir.ui.menu,name:menu_opportunity_employee_open"
+msgid "Opportunities per Employee"
+msgstr "Opportunités par employé"
+
+msgctxt "model:ir.ui.menu,name:menu_opportunity_form"
+msgid "Leads and Opportunities"
+msgstr "Prospects et opportunités"
+
+msgctxt "model:ir.ui.menu,name:menu_opportunity_monthly_form"
+msgid "Opportunities per Month"
+msgstr "Opportunités par mois"
+
+msgctxt "model:res.group,name:group_opportunity"
+msgid "Sale Opportunity"
+msgstr "Opportunité de vente"
+
+msgctxt "model:sale.opportunity,name:"
+msgid "Sale Opportunity"
+msgstr "Opportunités de vente"
+
+msgctxt "model:sale.opportunity.line,name:"
+msgid "Sale Opportunity Line"
+msgstr "Ligne d'opportunité de vente"
+
+msgctxt "model:sale.opportunity_employee,name:"
+msgid "Sale Opportunity per Employee"
+msgstr "Opportunités de vente par employé"
+
+msgctxt "model:sale.opportunity_employee.context,name:"
+msgid "Sale Opportunity per Employee Context"
+msgstr "Contexte d'opportunités de vente par employé"
+
+msgctxt "model:sale.opportunity_employee_monthly,name:"
+msgid "Sale Opportunity per Employee per Month"
+msgstr "Opportunités de vente par employé par mois"
+
+msgctxt "model:sale.opportunity_monthly,name:"
+msgid "Sale Opportunity per Month"
+msgstr "Opportunités de vente par mois"
+
+msgctxt "selection:sale.opportunity,state:"
+msgid "Cancelled"
+msgstr "Annulée"
+
+msgctxt "selection:sale.opportunity,state:"
+msgid "Converted"
+msgstr "Convertie"
+
+msgctxt "selection:sale.opportunity,state:"
+msgid "Lead"
+msgstr "Contact"
+
+msgctxt "selection:sale.opportunity,state:"
+msgid "Lost"
+msgstr "Perdue"
+
+msgctxt "selection:sale.opportunity,state:"
+msgid "Opportunity"
+msgstr "Opportunité"
+
+msgctxt "selection:sale.opportunity,state:"
+msgid "Won"
+msgstr "Gagnée"
+
+msgctxt "view:sale.opportunity:"
+msgid "%"
+msgstr "%"
+
+msgctxt "view:sale.opportunity:"
+msgid "Lead/Opportunity"
+msgstr "Contact / Opportunité"
+
+msgctxt "view:sale.opportunity_employee:"
+msgid "%"
+msgstr "%"
+
+msgctxt "view:sale.opportunity_employee_monthly:"
+msgid "%"
+msgstr "%"
+
+msgctxt "view:sale.opportunity_monthly:"
+msgid "%"
+msgstr "%"
diff --git a/modules/sale_opportunity/locale/hu.po b/modules/sale_opportunity/locale/hu.po
new file mode 100644
index 0000000000..e079ac8ebe
--- /dev/null
+++ b/modules/sale_opportunity/locale/hu.po
@@ -0,0 +1,590 @@
+#
+msgid ""
+msgstr "Content-Type: text/plain; charset=utf-8\n"
+
+msgctxt "field:sale.configuration,sale_opportunity_sequence:"
+msgid "Opportunity Sequence"
+msgstr ""
+
+msgctxt "field:sale.configuration.sequence,sale_opportunity_sequence:"
+msgid "Opportunity Sequence"
+msgstr ""
+
+#, fuzzy
+msgctxt "field:sale.opportunity,address:"
+msgid "Address"
+msgstr "Cím"
+
+msgctxt "field:sale.opportunity,amount:"
+msgid "Amount"
+msgstr ""
+
+#, fuzzy
+msgctxt "field:sale.opportunity,comment:"
+msgid "Comment"
+msgstr "Megjegyzés"
+
+#, fuzzy
+msgctxt "field:sale.opportunity,company:"
+msgid "Company"
+msgstr "Társaság"
+
+msgctxt "field:sale.opportunity,contact:"
+msgid "Contact"
+msgstr ""
+
+msgctxt "field:sale.opportunity,conversion_probability:"
+msgid "Conversion Probability"
+msgstr ""
+
+#, fuzzy
+msgctxt "field:sale.opportunity,converted_by:"
+msgid "Converted By"
+msgstr "Converted"
+
+#, fuzzy
+msgctxt "field:sale.opportunity,currency:"
+msgid "Currency"
+msgstr "Pénznem"
+
+msgctxt "field:sale.opportunity,currency_digits:"
+msgid "Currency Digits"
+msgstr ""
+
+#, fuzzy
+msgctxt "field:sale.opportunity,description:"
+msgid "Description"
+msgstr "Leírás"
+
+#, fuzzy
+msgctxt "field:sale.opportunity,employee:"
+msgid "Employee"
+msgstr "Alkalmazott"
+
+msgctxt "field:sale.opportunity,end_date:"
+msgid "End Date"
+msgstr ""
+
+#, fuzzy
+msgctxt "field:sale.opportunity,lines:"
+msgid "Lines"
+msgstr "Sor"
+
+msgctxt "field:sale.opportunity,lost_reason:"
+msgid "Reason for loss"
+msgstr ""
+
+#, fuzzy
+msgctxt "field:sale.opportunity,number:"
+msgid "Number"
+msgstr "Szám"
+
+#, fuzzy
+msgctxt "field:sale.opportunity,party:"
+msgid "Party"
+msgstr "Partner"
+
+msgctxt "field:sale.opportunity,payment_term:"
+msgid "Payment Term"
+msgstr ""
+
+msgctxt "field:sale.opportunity,reference:"
+msgid "Reference"
+msgstr ""
+
+#, fuzzy
+msgctxt "field:sale.opportunity,sales:"
+msgid "Sales"
+msgstr "Sales"
+
+msgctxt "field:sale.opportunity,start_date:"
+msgid "Start Date"
+msgstr ""
+
+#, fuzzy
+msgctxt "field:sale.opportunity,state:"
+msgid "State"
+msgstr "Állapot"
+
+#, fuzzy
+msgctxt "field:sale.opportunity.line,opportunity:"
+msgid "Opportunity"
+msgstr "Opportunities"
+
+msgctxt "field:sale.opportunity.line,opportunity_state:"
+msgid "Opportunity State"
+msgstr ""
+
+#, fuzzy
+msgctxt "field:sale.opportunity.line,product:"
+msgid "Product"
+msgstr "Termék"
+
+#, fuzzy
+msgctxt "field:sale.opportunity.line,quantity:"
+msgid "Quantity"
+msgstr "Mennyiség"
+
+#, fuzzy
+msgctxt "field:sale.opportunity.line,unit:"
+msgid "Unit"
+msgstr "Egység"
+
+#, fuzzy
+msgctxt "field:sale.opportunity.line,unit_digits:"
+msgid "Unit Digits"
+msgstr "Tizedes vessző utáni számjegy"
+
+msgctxt "field:sale.opportunity_employee,amount:"
+msgid "Amount"
+msgstr ""
+
+#, fuzzy
+msgctxt "field:sale.opportunity_employee,company:"
+msgid "Company"
+msgstr "Társaság"
+
+msgctxt "field:sale.opportunity_employee,conversion_amount_rate:"
+msgid "Conversion Amount Rate"
+msgstr ""
+
+msgctxt "field:sale.opportunity_employee,conversion_rate:"
+msgid "Conversion Rate"
+msgstr ""
+
+#, fuzzy
+msgctxt "field:sale.opportunity_employee,converted:"
+msgid "Converted"
+msgstr "Converted"
+
+msgctxt "field:sale.opportunity_employee,converted_amount:"
+msgid "Converted Amount"
+msgstr ""
+
+#, fuzzy
+msgctxt "field:sale.opportunity_employee,currency:"
+msgid "Currency"
+msgstr "Pénznem"
+
+msgctxt "field:sale.opportunity_employee,currency_digits:"
+msgid "Currency Digits"
+msgstr ""
+
+#, fuzzy
+msgctxt "field:sale.opportunity_employee,employee:"
+msgid "Employee"
+msgstr "Alkalmazott"
+
+#, fuzzy
+msgctxt "field:sale.opportunity_employee,lost:"
+msgid "Lost"
+msgstr "Lost"
+
+#, fuzzy
+msgctxt "field:sale.opportunity_employee,number:"
+msgid "Number"
+msgstr "Szám"
+
+msgctxt "field:sale.opportunity_employee,winning_amount_rate:"
+msgid "Winning Amount Rate"
+msgstr ""
+
+msgctxt "field:sale.opportunity_employee,winning_rate:"
+msgid "Winning Rate"
+msgstr ""
+
+#, fuzzy
+msgctxt "field:sale.opportunity_employee,won:"
+msgid "Won"
+msgstr "von"
+
+msgctxt "field:sale.opportunity_employee,won_amount:"
+msgid "Won Amount"
+msgstr ""
+
+msgctxt "field:sale.opportunity_employee.context,end_date:"
+msgid "End Date"
+msgstr ""
+
+msgctxt "field:sale.opportunity_employee.context,start_date:"
+msgid "Start Date"
+msgstr ""
+
+msgctxt "field:sale.opportunity_employee_monthly,amount:"
+msgid "Amount"
+msgstr ""
+
+#, fuzzy
+msgctxt "field:sale.opportunity_employee_monthly,company:"
+msgid "Company"
+msgstr "Társaság"
+
+msgctxt "field:sale.opportunity_employee_monthly,conversion_amount_rate:"
+msgid "Conversion Amount Rate"
+msgstr ""
+
+msgctxt "field:sale.opportunity_employee_monthly,conversion_rate:"
+msgid "Conversion Rate"
+msgstr ""
+
+#, fuzzy
+msgctxt "field:sale.opportunity_employee_monthly,converted:"
+msgid "Converted"
+msgstr "Converted"
+
+msgctxt "field:sale.opportunity_employee_monthly,converted_amount:"
+msgid "Converted Amount"
+msgstr ""
+
+#, fuzzy
+msgctxt "field:sale.opportunity_employee_monthly,currency:"
+msgid "Currency"
+msgstr "Pénznem"
+
+msgctxt "field:sale.opportunity_employee_monthly,currency_digits:"
+msgid "Currency Digits"
+msgstr ""
+
+#, fuzzy
+msgctxt "field:sale.opportunity_employee_monthly,employee:"
+msgid "Employee"
+msgstr "Alkalmazott"
+
+#, fuzzy
+msgctxt "field:sale.opportunity_employee_monthly,lost:"
+msgid "Lost"
+msgstr "Lost"
+
+#, fuzzy
+msgctxt "field:sale.opportunity_employee_monthly,month:"
+msgid "Month"
+msgstr "Hónap"
+
+#, fuzzy
+msgctxt "field:sale.opportunity_employee_monthly,number:"
+msgid "Number"
+msgstr "Szám"
+
+msgctxt "field:sale.opportunity_employee_monthly,winning_amount_rate:"
+msgid "Winning Amount Rate"
+msgstr ""
+
+msgctxt "field:sale.opportunity_employee_monthly,winning_rate:"
+msgid "Winning Rate"
+msgstr ""
+
+#, fuzzy
+msgctxt "field:sale.opportunity_employee_monthly,won:"
+msgid "Won"
+msgstr "von"
+
+msgctxt "field:sale.opportunity_employee_monthly,won_amount:"
+msgid "Won Amount"
+msgstr ""
+
+#, fuzzy
+msgctxt "field:sale.opportunity_employee_monthly,year:"
+msgid "Year"
+msgstr "Év"
+
+msgctxt "field:sale.opportunity_monthly,amount:"
+msgid "Amount"
+msgstr ""
+
+#, fuzzy
+msgctxt "field:sale.opportunity_monthly,company:"
+msgid "Company"
+msgstr "Társaság"
+
+msgctxt "field:sale.opportunity_monthly,conversion_amount_rate:"
+msgid "Conversion Amount Rate"
+msgstr ""
+
+msgctxt "field:sale.opportunity_monthly,conversion_rate:"
+msgid "Conversion Rate"
+msgstr ""
+
+#, fuzzy
+msgctxt "field:sale.opportunity_monthly,converted:"
+msgid "Converted"
+msgstr "Converted"
+
+msgctxt "field:sale.opportunity_monthly,converted_amount:"
+msgid "Converted Amount"
+msgstr ""
+
+#, fuzzy
+msgctxt "field:sale.opportunity_monthly,currency:"
+msgid "Currency"
+msgstr "Pénznem"
+
+msgctxt "field:sale.opportunity_monthly,currency_digits:"
+msgid "Currency Digits"
+msgstr ""
+
+#, fuzzy
+msgctxt "field:sale.opportunity_monthly,lost:"
+msgid "Lost"
+msgstr "Lost"
+
+#, fuzzy
+msgctxt "field:sale.opportunity_monthly,month:"
+msgid "Month"
+msgstr "Hónap"
+
+#, fuzzy
+msgctxt "field:sale.opportunity_monthly,number:"
+msgid "Number"
+msgstr "Szám"
+
+msgctxt "field:sale.opportunity_monthly,winning_amount_rate:"
+msgid "Winning Amount Rate"
+msgstr ""
+
+msgctxt "field:sale.opportunity_monthly,winning_rate:"
+msgid "Winning Rate"
+msgstr ""
+
+#, fuzzy
+msgctxt "field:sale.opportunity_monthly,won:"
+msgid "Won"
+msgstr "von"
+
+msgctxt "field:sale.opportunity_monthly,won_amount:"
+msgid "Won Amount"
+msgstr ""
+
+#, fuzzy
+msgctxt "field:sale.opportunity_monthly,year:"
+msgid "Year"
+msgstr "Év"
+
+msgctxt "field:sale.opportunity_monthly,year_month:"
+msgid "Year-Month"
+msgstr ""
+
+msgctxt "help:sale.opportunity,amount:"
+msgid "Estimated revenue amount."
+msgstr ""
+
+msgctxt "help:sale.opportunity,conversion_probability:"
+msgid "Percentage between 0 and 100."
+msgstr ""
+
+msgctxt "model:ir.action,name:act_open_sale_form"
+msgid "Sales"
+msgstr "Sales"
+
+msgctxt "model:ir.action,name:act_opportunity_employee_form"
+msgid "Opportunities per Employee"
+msgstr "Opportunities per Employee"
+
+msgctxt "model:ir.action,name:act_opportunity_employee_monthly_form"
+msgid "Opportunities per Employee per Month"
+msgstr "Opportunities per Employee per Month"
+
+msgctxt "model:ir.action,name:act_opportunity_form"
+msgid "Leads and Opportunities"
+msgstr "Leads and Opportunities"
+
+msgctxt "model:ir.action,name:act_opportunity_form2"
+msgid "Sales Leads/Opportunities"
+msgstr "Sales Leads/Opportunities"
+
+msgctxt "model:ir.action,name:act_opportunity_monthly_form"
+msgid "Opportunities per Month"
+msgstr "Opportunities per Month"
+
+#, fuzzy
+msgctxt ""
+"model:ir.action.act_window.domain,name:act_opportunity_form_domain_all"
+msgid "All"
+msgstr "Összes"
+
+msgctxt ""
+"model:ir.action.act_window.domain,name:act_opportunity_form_domain_cancelled"
+msgid "Cancelled"
+msgstr "Cancelled"
+
+msgctxt ""
+"model:ir.action.act_window.domain,name:act_opportunity_form_domain_converted"
+msgid "Converted"
+msgstr "Converted"
+
+msgctxt ""
+"model:ir.action.act_window.domain,name:act_opportunity_form_domain_leads"
+msgid "Leads"
+msgstr "Leads"
+
+msgctxt ""
+"model:ir.action.act_window.domain,name:act_opportunity_form_domain_lost"
+msgid "Lost"
+msgstr "Lost"
+
+msgctxt ""
+"model:ir.action.act_window.domain,name:act_opportunity_form_domain_opportunities"
+msgid "Opportunities"
+msgstr "Opportunities"
+
+#, fuzzy
+msgctxt ""
+"model:ir.action.act_window.domain,name:act_opportunity_form_domain_won"
+msgid "Won"
+msgstr "von"
+
+msgctxt "model:ir.message,text:msg_modify_origin_opportunity"
+msgid "You cannot modify the opportunity origin of the sale \"%(sale)s\"."
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_opportunity_delete_cancel"
+msgid "To delete opportunity \"%(opportunity)s\", you must cancel it."
+msgstr ""
+
+msgctxt "model:ir.model.button,string:opportunity_cancel_button"
+msgid "Cancel"
+msgstr "Cancel"
+
+msgctxt "model:ir.model.button,string:opportunity_convert_button"
+msgid "Convert to Sale"
+msgstr "Convert to Sale"
+
+msgctxt "model:ir.model.button,string:opportunity_lead_button"
+msgid "Set as Lead"
+msgstr "Set as Lead"
+
+msgctxt "model:ir.model.button,string:opportunity_lost_button"
+msgid "Mark as Lost"
+msgstr "Mark as Lost"
+
+msgctxt "model:ir.model.button,string:opportunity_opportunity_button"
+msgid "Convert to Opportunity"
+msgstr "Convert to Opportunity"
+
+msgctxt "model:ir.rule.group,name:rule_group_opportunity_companies"
+msgid "User in companies"
+msgstr ""
+
+msgctxt "model:ir.rule.group,name:rule_group_opportunity_employee_companies"
+msgid "User in companies"
+msgstr ""
+
+msgctxt ""
+"model:ir.rule.group,name:rule_group_opportunity_employee_monthly_companies"
+msgid "User in companies"
+msgstr ""
+
+msgctxt "model:ir.rule.group,name:rule_group_opportunity_monthly_companies"
+msgid "User in companies"
+msgstr ""
+
+msgctxt "model:ir.sequence,name:sequence_sale_opportunity"
+msgid "Sale Opportunity"
+msgstr "Sale Opportunity"
+
+msgctxt "model:ir.sequence.type,name:sequence_type_sale_opportunity"
+msgid "Sale Opportunity"
+msgstr "Sale Opportunity"
+
+msgctxt "model:ir.ui.menu,name:menu_opportunity_employee_monthly_form"
+msgid "Opportunities per Employee per Month"
+msgstr "Opportunities per Employee per Month"
+
+msgctxt "model:ir.ui.menu,name:menu_opportunity_employee_open"
+msgid "Opportunities per Employee"
+msgstr "Opportunities per Employee"
+
+msgctxt "model:ir.ui.menu,name:menu_opportunity_form"
+msgid "Leads and Opportunities"
+msgstr "Leads and Opportunities"
+
+msgctxt "model:ir.ui.menu,name:menu_opportunity_monthly_form"
+msgid "Opportunities per Month"
+msgstr "Opportunities per Month"
+
+msgctxt "model:res.group,name:group_opportunity"
+msgid "Sale Opportunity"
+msgstr "Sale Opportunity"
+
+#, fuzzy
+msgctxt "model:sale.opportunity,name:"
+msgid "Sale Opportunity"
+msgstr "Sale Opportunity"
+
+#, fuzzy
+msgctxt "model:sale.opportunity.line,name:"
+msgid "Sale Opportunity Line"
+msgstr "Sale Opportunity"
+
+#, fuzzy
+msgctxt "model:sale.opportunity_employee,name:"
+msgid "Sale Opportunity per Employee"
+msgstr "Opportunities per Employee per Month"
+
+#, fuzzy
+msgctxt "model:sale.opportunity_employee.context,name:"
+msgid "Sale Opportunity per Employee Context"
+msgstr "Opportunities per Employee per Month"
+
+#, fuzzy
+msgctxt "model:sale.opportunity_employee_monthly,name:"
+msgid "Sale Opportunity per Employee per Month"
+msgstr "Opportunities per Employee per Month"
+
+#, fuzzy
+msgctxt "model:sale.opportunity_monthly,name:"
+msgid "Sale Opportunity per Month"
+msgstr "Opportunities per Employee per Month"
+
+#, fuzzy
+msgctxt "selection:sale.opportunity,state:"
+msgid "Cancelled"
+msgstr "Cancelled"
+
+#, fuzzy
+msgctxt "selection:sale.opportunity,state:"
+msgid "Converted"
+msgstr "Converted"
+
+#, fuzzy
+msgctxt "selection:sale.opportunity,state:"
+msgid "Lead"
+msgstr "Leads"
+
+#, fuzzy
+msgctxt "selection:sale.opportunity,state:"
+msgid "Lost"
+msgstr "Lost"
+
+#, fuzzy
+msgctxt "selection:sale.opportunity,state:"
+msgid "Opportunity"
+msgstr "Opportunities"
+
+#, fuzzy
+msgctxt "selection:sale.opportunity,state:"
+msgid "Won"
+msgstr "von"
+
+#, fuzzy
+msgctxt "view:sale.opportunity:"
+msgid "%"
+msgstr "%"
+
+msgctxt "view:sale.opportunity:"
+msgid "Lead/Opportunity"
+msgstr ""
+
+#, fuzzy
+msgctxt "view:sale.opportunity_employee:"
+msgid "%"
+msgstr "%"
+
+#, fuzzy
+msgctxt "view:sale.opportunity_employee_monthly:"
+msgid "%"
+msgstr "%"
+
+#, fuzzy
+msgctxt "view:sale.opportunity_monthly:"
+msgid "%"
+msgstr "%"
diff --git a/modules/sale_opportunity/locale/id.po b/modules/sale_opportunity/locale/id.po
new file mode 100644
index 0000000000..02250ccc99
--- /dev/null
+++ b/modules/sale_opportunity/locale/id.po
@@ -0,0 +1,536 @@
+#
+msgid ""
+msgstr "Content-Type: text/plain; charset=utf-8\n"
+
+msgctxt "field:sale.configuration,sale_opportunity_sequence:"
+msgid "Opportunity Sequence"
+msgstr ""
+
+msgctxt "field:sale.configuration.sequence,sale_opportunity_sequence:"
+msgid "Opportunity Sequence"
+msgstr ""
+
+msgctxt "field:sale.opportunity,address:"
+msgid "Address"
+msgstr "Alamat"
+
+msgctxt "field:sale.opportunity,amount:"
+msgid "Amount"
+msgstr "Jumlah"
+
+msgctxt "field:sale.opportunity,comment:"
+msgid "Comment"
+msgstr "Komentar"
+
+msgctxt "field:sale.opportunity,company:"
+msgid "Company"
+msgstr "Perusahaan"
+
+msgctxt "field:sale.opportunity,contact:"
+msgid "Contact"
+msgstr ""
+
+msgctxt "field:sale.opportunity,conversion_probability:"
+msgid "Conversion Probability"
+msgstr ""
+
+#, fuzzy
+msgctxt "field:sale.opportunity,converted_by:"
+msgid "Converted By"
+msgstr "Dibuat oleh"
+
+msgctxt "field:sale.opportunity,currency:"
+msgid "Currency"
+msgstr "Mata uang"
+
+msgctxt "field:sale.opportunity,currency_digits:"
+msgid "Currency Digits"
+msgstr ""
+
+msgctxt "field:sale.opportunity,description:"
+msgid "Description"
+msgstr "Deskripsi"
+
+msgctxt "field:sale.opportunity,employee:"
+msgid "Employee"
+msgstr "Pegawai"
+
+msgctxt "field:sale.opportunity,end_date:"
+msgid "End Date"
+msgstr "Tanggal Akhir"
+
+msgctxt "field:sale.opportunity,lines:"
+msgid "Lines"
+msgstr "Baris"
+
+msgctxt "field:sale.opportunity,lost_reason:"
+msgid "Reason for loss"
+msgstr "Alasan kerugian"
+
+msgctxt "field:sale.opportunity,number:"
+msgid "Number"
+msgstr "Nomor"
+
+msgctxt "field:sale.opportunity,party:"
+msgid "Party"
+msgstr "Pihak"
+
+msgctxt "field:sale.opportunity,payment_term:"
+msgid "Payment Term"
+msgstr "Masa Pembayaran"
+
+msgctxt "field:sale.opportunity,reference:"
+msgid "Reference"
+msgstr "Referensi"
+
+msgctxt "field:sale.opportunity,sales:"
+msgid "Sales"
+msgstr ""
+
+msgctxt "field:sale.opportunity,start_date:"
+msgid "Start Date"
+msgstr "Tanggal Awal"
+
+msgctxt "field:sale.opportunity,state:"
+msgid "State"
+msgstr "Status"
+
+msgctxt "field:sale.opportunity.line,opportunity:"
+msgid "Opportunity"
+msgstr ""
+
+msgctxt "field:sale.opportunity.line,opportunity_state:"
+msgid "Opportunity State"
+msgstr ""
+
+msgctxt "field:sale.opportunity.line,product:"
+msgid "Product"
+msgstr "Produk"
+
+msgctxt "field:sale.opportunity.line,quantity:"
+msgid "Quantity"
+msgstr ""
+
+msgctxt "field:sale.opportunity.line,unit:"
+msgid "Unit"
+msgstr ""
+
+msgctxt "field:sale.opportunity.line,unit_digits:"
+msgid "Unit Digits"
+msgstr ""
+
+msgctxt "field:sale.opportunity_employee,amount:"
+msgid "Amount"
+msgstr "Jumlah"
+
+msgctxt "field:sale.opportunity_employee,company:"
+msgid "Company"
+msgstr "Perusahaan"
+
+msgctxt "field:sale.opportunity_employee,conversion_amount_rate:"
+msgid "Conversion Amount Rate"
+msgstr ""
+
+msgctxt "field:sale.opportunity_employee,conversion_rate:"
+msgid "Conversion Rate"
+msgstr ""
+
+msgctxt "field:sale.opportunity_employee,converted:"
+msgid "Converted"
+msgstr ""
+
+msgctxt "field:sale.opportunity_employee,converted_amount:"
+msgid "Converted Amount"
+msgstr ""
+
+msgctxt "field:sale.opportunity_employee,currency:"
+msgid "Currency"
+msgstr "Mata uang"
+
+msgctxt "field:sale.opportunity_employee,currency_digits:"
+msgid "Currency Digits"
+msgstr ""
+
+msgctxt "field:sale.opportunity_employee,employee:"
+msgid "Employee"
+msgstr "Pegawai"
+
+msgctxt "field:sale.opportunity_employee,lost:"
+msgid "Lost"
+msgstr ""
+
+msgctxt "field:sale.opportunity_employee,number:"
+msgid "Number"
+msgstr "Nomor"
+
+msgctxt "field:sale.opportunity_employee,winning_amount_rate:"
+msgid "Winning Amount Rate"
+msgstr ""
+
+msgctxt "field:sale.opportunity_employee,winning_rate:"
+msgid "Winning Rate"
+msgstr ""
+
+msgctxt "field:sale.opportunity_employee,won:"
+msgid "Won"
+msgstr ""
+
+msgctxt "field:sale.opportunity_employee,won_amount:"
+msgid "Won Amount"
+msgstr ""
+
+msgctxt "field:sale.opportunity_employee.context,end_date:"
+msgid "End Date"
+msgstr "Tanggal Akhir"
+
+msgctxt "field:sale.opportunity_employee.context,start_date:"
+msgid "Start Date"
+msgstr "Tanggal Awal"
+
+msgctxt "field:sale.opportunity_employee_monthly,amount:"
+msgid "Amount"
+msgstr "Jumlah"
+
+msgctxt "field:sale.opportunity_employee_monthly,company:"
+msgid "Company"
+msgstr "Perusahaan"
+
+msgctxt "field:sale.opportunity_employee_monthly,conversion_amount_rate:"
+msgid "Conversion Amount Rate"
+msgstr ""
+
+msgctxt "field:sale.opportunity_employee_monthly,conversion_rate:"
+msgid "Conversion Rate"
+msgstr ""
+
+msgctxt "field:sale.opportunity_employee_monthly,converted:"
+msgid "Converted"
+msgstr ""
+
+msgctxt "field:sale.opportunity_employee_monthly,converted_amount:"
+msgid "Converted Amount"
+msgstr ""
+
+msgctxt "field:sale.opportunity_employee_monthly,currency:"
+msgid "Currency"
+msgstr "Mata uang"
+
+msgctxt "field:sale.opportunity_employee_monthly,currency_digits:"
+msgid "Currency Digits"
+msgstr ""
+
+msgctxt "field:sale.opportunity_employee_monthly,employee:"
+msgid "Employee"
+msgstr "Pegawai"
+
+msgctxt "field:sale.opportunity_employee_monthly,lost:"
+msgid "Lost"
+msgstr ""
+
+msgctxt "field:sale.opportunity_employee_monthly,month:"
+msgid "Month"
+msgstr "Bulan"
+
+msgctxt "field:sale.opportunity_employee_monthly,number:"
+msgid "Number"
+msgstr "Nomor"
+
+msgctxt "field:sale.opportunity_employee_monthly,winning_amount_rate:"
+msgid "Winning Amount Rate"
+msgstr ""
+
+msgctxt "field:sale.opportunity_employee_monthly,winning_rate:"
+msgid "Winning Rate"
+msgstr ""
+
+msgctxt "field:sale.opportunity_employee_monthly,won:"
+msgid "Won"
+msgstr ""
+
+msgctxt "field:sale.opportunity_employee_monthly,won_amount:"
+msgid "Won Amount"
+msgstr ""
+
+msgctxt "field:sale.opportunity_employee_monthly,year:"
+msgid "Year"
+msgstr "Tahun"
+
+msgctxt "field:sale.opportunity_monthly,amount:"
+msgid "Amount"
+msgstr "Jumlah"
+
+msgctxt "field:sale.opportunity_monthly,company:"
+msgid "Company"
+msgstr "Perusahaan"
+
+msgctxt "field:sale.opportunity_monthly,conversion_amount_rate:"
+msgid "Conversion Amount Rate"
+msgstr ""
+
+msgctxt "field:sale.opportunity_monthly,conversion_rate:"
+msgid "Conversion Rate"
+msgstr ""
+
+msgctxt "field:sale.opportunity_monthly,converted:"
+msgid "Converted"
+msgstr ""
+
+msgctxt "field:sale.opportunity_monthly,converted_amount:"
+msgid "Converted Amount"
+msgstr ""
+
+msgctxt "field:sale.opportunity_monthly,currency:"
+msgid "Currency"
+msgstr "Mata uang"
+
+msgctxt "field:sale.opportunity_monthly,currency_digits:"
+msgid "Currency Digits"
+msgstr ""
+
+msgctxt "field:sale.opportunity_monthly,lost:"
+msgid "Lost"
+msgstr ""
+
+msgctxt "field:sale.opportunity_monthly,month:"
+msgid "Month"
+msgstr "Bulan"
+
+msgctxt "field:sale.opportunity_monthly,number:"
+msgid "Number"
+msgstr "Nomor"
+
+msgctxt "field:sale.opportunity_monthly,winning_amount_rate:"
+msgid "Winning Amount Rate"
+msgstr ""
+
+msgctxt "field:sale.opportunity_monthly,winning_rate:"
+msgid "Winning Rate"
+msgstr ""
+
+msgctxt "field:sale.opportunity_monthly,won:"
+msgid "Won"
+msgstr ""
+
+msgctxt "field:sale.opportunity_monthly,won_amount:"
+msgid "Won Amount"
+msgstr ""
+
+msgctxt "field:sale.opportunity_monthly,year:"
+msgid "Year"
+msgstr "Tahun"
+
+msgctxt "field:sale.opportunity_monthly,year_month:"
+msgid "Year-Month"
+msgstr ""
+
+msgctxt "help:sale.opportunity,amount:"
+msgid "Estimated revenue amount."
+msgstr ""
+
+msgctxt "help:sale.opportunity,conversion_probability:"
+msgid "Percentage between 0 and 100."
+msgstr ""
+
+msgctxt "model:ir.action,name:act_open_sale_form"
+msgid "Sales"
+msgstr ""
+
+msgctxt "model:ir.action,name:act_opportunity_employee_form"
+msgid "Opportunities per Employee"
+msgstr ""
+
+msgctxt "model:ir.action,name:act_opportunity_employee_monthly_form"
+msgid "Opportunities per Employee per Month"
+msgstr ""
+
+msgctxt "model:ir.action,name:act_opportunity_form"
+msgid "Leads and Opportunities"
+msgstr ""
+
+msgctxt "model:ir.action,name:act_opportunity_form2"
+msgid "Sales Leads/Opportunities"
+msgstr ""
+
+msgctxt "model:ir.action,name:act_opportunity_monthly_form"
+msgid "Opportunities per Month"
+msgstr ""
+
+msgctxt ""
+"model:ir.action.act_window.domain,name:act_opportunity_form_domain_all"
+msgid "All"
+msgstr ""
+
+msgctxt ""
+"model:ir.action.act_window.domain,name:act_opportunity_form_domain_cancelled"
+msgid "Cancelled"
+msgstr ""
+
+msgctxt ""
+"model:ir.action.act_window.domain,name:act_opportunity_form_domain_converted"
+msgid "Converted"
+msgstr ""
+
+msgctxt ""
+"model:ir.action.act_window.domain,name:act_opportunity_form_domain_leads"
+msgid "Leads"
+msgstr ""
+
+msgctxt ""
+"model:ir.action.act_window.domain,name:act_opportunity_form_domain_lost"
+msgid "Lost"
+msgstr ""
+
+msgctxt ""
+"model:ir.action.act_window.domain,name:act_opportunity_form_domain_opportunities"
+msgid "Opportunities"
+msgstr ""
+
+msgctxt ""
+"model:ir.action.act_window.domain,name:act_opportunity_form_domain_won"
+msgid "Won"
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_modify_origin_opportunity"
+msgid "You cannot modify the opportunity origin of the sale \"%(sale)s\"."
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_opportunity_delete_cancel"
+msgid "To delete opportunity \"%(opportunity)s\", you must cancel it."
+msgstr ""
+
+msgctxt "model:ir.model.button,string:opportunity_cancel_button"
+msgid "Cancel"
+msgstr "Batal"
+
+msgctxt "model:ir.model.button,string:opportunity_convert_button"
+msgid "Convert to Sale"
+msgstr ""
+
+msgctxt "model:ir.model.button,string:opportunity_lead_button"
+msgid "Set as Lead"
+msgstr ""
+
+msgctxt "model:ir.model.button,string:opportunity_lost_button"
+msgid "Mark as Lost"
+msgstr ""
+
+msgctxt "model:ir.model.button,string:opportunity_opportunity_button"
+msgid "Convert to Opportunity"
+msgstr ""
+
+#, fuzzy
+msgctxt "model:ir.rule.group,name:rule_group_opportunity_companies"
+msgid "User in companies"
+msgstr "Pengguna di dalam perusahaan"
+
+#, fuzzy
+msgctxt "model:ir.rule.group,name:rule_group_opportunity_employee_companies"
+msgid "User in companies"
+msgstr "Pengguna di dalam perusahaan"
+
+#, fuzzy
+msgctxt ""
+"model:ir.rule.group,name:rule_group_opportunity_employee_monthly_companies"
+msgid "User in companies"
+msgstr "Pengguna di dalam perusahaan"
+
+#, fuzzy
+msgctxt "model:ir.rule.group,name:rule_group_opportunity_monthly_companies"
+msgid "User in companies"
+msgstr "Pengguna di dalam perusahaan"
+
+msgctxt "model:ir.sequence,name:sequence_sale_opportunity"
+msgid "Sale Opportunity"
+msgstr ""
+
+msgctxt "model:ir.sequence.type,name:sequence_type_sale_opportunity"
+msgid "Sale Opportunity"
+msgstr ""
+
+msgctxt "model:ir.ui.menu,name:menu_opportunity_employee_monthly_form"
+msgid "Opportunities per Employee per Month"
+msgstr ""
+
+msgctxt "model:ir.ui.menu,name:menu_opportunity_employee_open"
+msgid "Opportunities per Employee"
+msgstr ""
+
+msgctxt "model:ir.ui.menu,name:menu_opportunity_form"
+msgid "Leads and Opportunities"
+msgstr ""
+
+msgctxt "model:ir.ui.menu,name:menu_opportunity_monthly_form"
+msgid "Opportunities per Month"
+msgstr ""
+
+msgctxt "model:res.group,name:group_opportunity"
+msgid "Sale Opportunity"
+msgstr ""
+
+msgctxt "model:sale.opportunity,name:"
+msgid "Sale Opportunity"
+msgstr ""
+
+msgctxt "model:sale.opportunity.line,name:"
+msgid "Sale Opportunity Line"
+msgstr ""
+
+msgctxt "model:sale.opportunity_employee,name:"
+msgid "Sale Opportunity per Employee"
+msgstr ""
+
+msgctxt "model:sale.opportunity_employee.context,name:"
+msgid "Sale Opportunity per Employee Context"
+msgstr ""
+
+msgctxt "model:sale.opportunity_employee_monthly,name:"
+msgid "Sale Opportunity per Employee per Month"
+msgstr ""
+
+msgctxt "model:sale.opportunity_monthly,name:"
+msgid "Sale Opportunity per Month"
+msgstr ""
+
+msgctxt "selection:sale.opportunity,state:"
+msgid "Cancelled"
+msgstr ""
+
+msgctxt "selection:sale.opportunity,state:"
+msgid "Converted"
+msgstr ""
+
+msgctxt "selection:sale.opportunity,state:"
+msgid "Lead"
+msgstr ""
+
+msgctxt "selection:sale.opportunity,state:"
+msgid "Lost"
+msgstr ""
+
+msgctxt "selection:sale.opportunity,state:"
+msgid "Opportunity"
+msgstr ""
+
+msgctxt "selection:sale.opportunity,state:"
+msgid "Won"
+msgstr ""
+
+msgctxt "view:sale.opportunity:"
+msgid "%"
+msgstr "%"
+
+msgctxt "view:sale.opportunity:"
+msgid "Lead/Opportunity"
+msgstr ""
+
+msgctxt "view:sale.opportunity_employee:"
+msgid "%"
+msgstr "%"
+
+msgctxt "view:sale.opportunity_employee_monthly:"
+msgid "%"
+msgstr "%"
+
+msgctxt "view:sale.opportunity_monthly:"
+msgid "%"
+msgstr "%"
diff --git a/modules/sale_opportunity/locale/it.po b/modules/sale_opportunity/locale/it.po
new file mode 100644
index 0000000000..47893df454
--- /dev/null
+++ b/modules/sale_opportunity/locale/it.po
@@ -0,0 +1,558 @@
+#
+msgid ""
+msgstr "Content-Type: text/plain; charset=utf-8\n"
+
+msgctxt "field:sale.configuration,sale_opportunity_sequence:"
+msgid "Opportunity Sequence"
+msgstr "sequenza opportunity"
+
+#, fuzzy
+msgctxt "field:sale.configuration.sequence,sale_opportunity_sequence:"
+msgid "Opportunity Sequence"
+msgstr "sequenza opportunity"
+
+msgctxt "field:sale.opportunity,address:"
+msgid "Address"
+msgstr "Indirizzo"
+
+msgctxt "field:sale.opportunity,amount:"
+msgid "Amount"
+msgstr "Importo"
+
+msgctxt "field:sale.opportunity,comment:"
+msgid "Comment"
+msgstr "Commento"
+
+msgctxt "field:sale.opportunity,company:"
+msgid "Company"
+msgstr "Azienda"
+
+msgctxt "field:sale.opportunity,contact:"
+msgid "Contact"
+msgstr ""
+
+msgctxt "field:sale.opportunity,conversion_probability:"
+msgid "Conversion Probability"
+msgstr "Probabilita di conversion"
+
+#, fuzzy
+msgctxt "field:sale.opportunity,converted_by:"
+msgid "Converted By"
+msgstr "convertito"
+
+msgctxt "field:sale.opportunity,currency:"
+msgid "Currency"
+msgstr "Valuta"
+
+msgctxt "field:sale.opportunity,currency_digits:"
+msgid "Currency Digits"
+msgstr "posizioni valuta"
+
+msgctxt "field:sale.opportunity,description:"
+msgid "Description"
+msgstr "Descrizione"
+
+msgctxt "field:sale.opportunity,employee:"
+msgid "Employee"
+msgstr "Dipendente"
+
+msgctxt "field:sale.opportunity,end_date:"
+msgid "End Date"
+msgstr "Data finale"
+
+msgctxt "field:sale.opportunity,lines:"
+msgid "Lines"
+msgstr "Righe"
+
+msgctxt "field:sale.opportunity,lost_reason:"
+msgid "Reason for loss"
+msgstr "motivo della perdita"
+
+msgctxt "field:sale.opportunity,number:"
+msgid "Number"
+msgstr "Numero"
+
+msgctxt "field:sale.opportunity,party:"
+msgid "Party"
+msgstr "Controparte"
+
+msgctxt "field:sale.opportunity,payment_term:"
+msgid "Payment Term"
+msgstr "Termine di pagamento"
+
+msgctxt "field:sale.opportunity,reference:"
+msgid "Reference"
+msgstr "Riferimento"
+
+msgctxt "field:sale.opportunity,sales:"
+msgid "Sales"
+msgstr "Vendite"
+
+msgctxt "field:sale.opportunity,start_date:"
+msgid "Start Date"
+msgstr "Data iniziale"
+
+msgctxt "field:sale.opportunity,state:"
+msgid "State"
+msgstr "Stato"
+
+msgctxt "field:sale.opportunity.line,opportunity:"
+msgid "Opportunity"
+msgstr "opportunity"
+
+msgctxt "field:sale.opportunity.line,opportunity_state:"
+msgid "Opportunity State"
+msgstr "stato opportunity"
+
+msgctxt "field:sale.opportunity.line,product:"
+msgid "Product"
+msgstr "Prodotto"
+
+msgctxt "field:sale.opportunity.line,quantity:"
+msgid "Quantity"
+msgstr "Quantità"
+
+msgctxt "field:sale.opportunity.line,unit:"
+msgid "Unit"
+msgstr "Unità"
+
+msgctxt "field:sale.opportunity.line,unit_digits:"
+msgid "Unit Digits"
+msgstr "Posizioni Unità"
+
+msgctxt "field:sale.opportunity_employee,amount:"
+msgid "Amount"
+msgstr "Importo"
+
+msgctxt "field:sale.opportunity_employee,company:"
+msgid "Company"
+msgstr "Azienda"
+
+msgctxt "field:sale.opportunity_employee,conversion_amount_rate:"
+msgid "Conversion Amount Rate"
+msgstr "tasso di conversione importo"
+
+msgctxt "field:sale.opportunity_employee,conversion_rate:"
+msgid "Conversion Rate"
+msgstr "tasso di conversione"
+
+msgctxt "field:sale.opportunity_employee,converted:"
+msgid "Converted"
+msgstr "convertito"
+
+msgctxt "field:sale.opportunity_employee,converted_amount:"
+msgid "Converted Amount"
+msgstr "importo convertito"
+
+msgctxt "field:sale.opportunity_employee,currency:"
+msgid "Currency"
+msgstr "Valuta"
+
+msgctxt "field:sale.opportunity_employee,currency_digits:"
+msgid "Currency Digits"
+msgstr "posizioni valuta"
+
+msgctxt "field:sale.opportunity_employee,employee:"
+msgid "Employee"
+msgstr "Dipendente"
+
+msgctxt "field:sale.opportunity_employee,lost:"
+msgid "Lost"
+msgstr "Perso"
+
+msgctxt "field:sale.opportunity_employee,number:"
+msgid "Number"
+msgstr "Numero"
+
+msgctxt "field:sale.opportunity_employee,winning_amount_rate:"
+msgid "Winning Amount Rate"
+msgstr "probabilità di conseguimento importo"
+
+msgctxt "field:sale.opportunity_employee,winning_rate:"
+msgid "Winning Rate"
+msgstr "tasso di aggiudicazione"
+
+msgctxt "field:sale.opportunity_employee,won:"
+msgid "Won"
+msgstr "conseguito"
+
+msgctxt "field:sale.opportunity_employee,won_amount:"
+msgid "Won Amount"
+msgstr "importo conseguito"
+
+msgctxt "field:sale.opportunity_employee.context,end_date:"
+msgid "End Date"
+msgstr "Data finale"
+
+msgctxt "field:sale.opportunity_employee.context,start_date:"
+msgid "Start Date"
+msgstr "Data iniziale"
+
+msgctxt "field:sale.opportunity_employee_monthly,amount:"
+msgid "Amount"
+msgstr "Importo"
+
+msgctxt "field:sale.opportunity_employee_monthly,company:"
+msgid "Company"
+msgstr "Azienda"
+
+msgctxt "field:sale.opportunity_employee_monthly,conversion_amount_rate:"
+msgid "Conversion Amount Rate"
+msgstr "tasso di conversione importo"
+
+msgctxt "field:sale.opportunity_employee_monthly,conversion_rate:"
+msgid "Conversion Rate"
+msgstr "tasso di conversione"
+
+msgctxt "field:sale.opportunity_employee_monthly,converted:"
+msgid "Converted"
+msgstr "convertito"
+
+msgctxt "field:sale.opportunity_employee_monthly,converted_amount:"
+msgid "Converted Amount"
+msgstr "importo convertito"
+
+msgctxt "field:sale.opportunity_employee_monthly,currency:"
+msgid "Currency"
+msgstr "Valuta"
+
+msgctxt "field:sale.opportunity_employee_monthly,currency_digits:"
+msgid "Currency Digits"
+msgstr "posizioni valuta"
+
+msgctxt "field:sale.opportunity_employee_monthly,employee:"
+msgid "Employee"
+msgstr "Dipendente"
+
+msgctxt "field:sale.opportunity_employee_monthly,lost:"
+msgid "Lost"
+msgstr "Perse"
+
+msgctxt "field:sale.opportunity_employee_monthly,month:"
+msgid "Month"
+msgstr "Mese"
+
+msgctxt "field:sale.opportunity_employee_monthly,number:"
+msgid "Number"
+msgstr "Numero"
+
+msgctxt "field:sale.opportunity_employee_monthly,winning_amount_rate:"
+msgid "Winning Amount Rate"
+msgstr "tasso di conseguimento importo"
+
+msgctxt "field:sale.opportunity_employee_monthly,winning_rate:"
+msgid "Winning Rate"
+msgstr "tasso di conseguimento"
+
+msgctxt "field:sale.opportunity_employee_monthly,won:"
+msgid "Won"
+msgstr "conseguito"
+
+msgctxt "field:sale.opportunity_employee_monthly,won_amount:"
+msgid "Won Amount"
+msgstr "importo conseguito"
+
+msgctxt "field:sale.opportunity_employee_monthly,year:"
+msgid "Year"
+msgstr "Anno"
+
+msgctxt "field:sale.opportunity_monthly,amount:"
+msgid "Amount"
+msgstr "Importo"
+
+msgctxt "field:sale.opportunity_monthly,company:"
+msgid "Company"
+msgstr "Azienda"
+
+msgctxt "field:sale.opportunity_monthly,conversion_amount_rate:"
+msgid "Conversion Amount Rate"
+msgstr "tasso di conversione importo"
+
+msgctxt "field:sale.opportunity_monthly,conversion_rate:"
+msgid "Conversion Rate"
+msgstr "tasso di conversione"
+
+msgctxt "field:sale.opportunity_monthly,converted:"
+msgid "Converted"
+msgstr "convertito"
+
+msgctxt "field:sale.opportunity_monthly,converted_amount:"
+msgid "Converted Amount"
+msgstr "importo convertito"
+
+msgctxt "field:sale.opportunity_monthly,currency:"
+msgid "Currency"
+msgstr "Valuta"
+
+msgctxt "field:sale.opportunity_monthly,currency_digits:"
+msgid "Currency Digits"
+msgstr "posizioni valuta"
+
+msgctxt "field:sale.opportunity_monthly,lost:"
+msgid "Lost"
+msgstr "Perso"
+
+msgctxt "field:sale.opportunity_monthly,month:"
+msgid "Month"
+msgstr "Mese"
+
+msgctxt "field:sale.opportunity_monthly,number:"
+msgid "Number"
+msgstr "Numero"
+
+msgctxt "field:sale.opportunity_monthly,winning_amount_rate:"
+msgid "Winning Amount Rate"
+msgstr "tasso di conseguimento importo"
+
+msgctxt "field:sale.opportunity_monthly,winning_rate:"
+msgid "Winning Rate"
+msgstr "tasso di conseguimento"
+
+msgctxt "field:sale.opportunity_monthly,won:"
+msgid "Won"
+msgstr "conseguito"
+
+msgctxt "field:sale.opportunity_monthly,won_amount:"
+msgid "Won Amount"
+msgstr "importo conseguito"
+
+msgctxt "field:sale.opportunity_monthly,year:"
+msgid "Year"
+msgstr "Anno"
+
+msgctxt "field:sale.opportunity_monthly,year_month:"
+msgid "Year-Month"
+msgstr "anno - mese"
+
+#, fuzzy
+msgctxt "help:sale.opportunity,amount:"
+msgid "Estimated revenue amount."
+msgstr "Importo reddito stimato"
+
+#, fuzzy
+msgctxt "help:sale.opportunity,conversion_probability:"
+msgid "Percentage between 0 and 100."
+msgstr "percentuale fra 0 e 100"
+
+#, fuzzy
+msgctxt "model:ir.action,name:act_open_sale_form"
+msgid "Sales"
+msgstr "Sales"
+
+#, fuzzy
+msgctxt "model:ir.action,name:act_opportunity_employee_form"
+msgid "Opportunities per Employee"
+msgstr "Opportunities per Employee"
+
+#, fuzzy
+msgctxt "model:ir.action,name:act_opportunity_employee_monthly_form"
+msgid "Opportunities per Employee per Month"
+msgstr "Opportunities per Employee per Month"
+
+#, fuzzy
+msgctxt "model:ir.action,name:act_opportunity_form"
+msgid "Leads and Opportunities"
+msgstr "Leads and Opportunities"
+
+#, fuzzy
+msgctxt "model:ir.action,name:act_opportunity_form2"
+msgid "Sales Leads/Opportunities"
+msgstr "Sales Leads/Opportunities"
+
+#, fuzzy
+msgctxt "model:ir.action,name:act_opportunity_monthly_form"
+msgid "Opportunities per Month"
+msgstr "Opportunities per Month"
+
+#, fuzzy
+msgctxt ""
+"model:ir.action.act_window.domain,name:act_opportunity_form_domain_all"
+msgid "All"
+msgstr "All"
+
+#, fuzzy
+msgctxt ""
+"model:ir.action.act_window.domain,name:act_opportunity_form_domain_cancelled"
+msgid "Cancelled"
+msgstr "Cancelled"
+
+#, fuzzy
+msgctxt ""
+"model:ir.action.act_window.domain,name:act_opportunity_form_domain_converted"
+msgid "Converted"
+msgstr "Converted"
+
+#, fuzzy
+msgctxt ""
+"model:ir.action.act_window.domain,name:act_opportunity_form_domain_leads"
+msgid "Leads"
+msgstr "Leads"
+
+#, fuzzy
+msgctxt ""
+"model:ir.action.act_window.domain,name:act_opportunity_form_domain_lost"
+msgid "Lost"
+msgstr "Lost"
+
+#, fuzzy
+msgctxt ""
+"model:ir.action.act_window.domain,name:act_opportunity_form_domain_opportunities"
+msgid "Opportunities"
+msgstr "Opportunities"
+
+#, fuzzy
+msgctxt ""
+"model:ir.action.act_window.domain,name:act_opportunity_form_domain_won"
+msgid "Won"
+msgstr "Won"
+
+msgctxt "model:ir.message,text:msg_modify_origin_opportunity"
+msgid "You cannot modify the opportunity origin of the sale \"%(sale)s\"."
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_opportunity_delete_cancel"
+msgid "To delete opportunity \"%(opportunity)s\", you must cancel it."
+msgstr ""
+
+msgctxt "model:ir.model.button,string:opportunity_cancel_button"
+msgid "Cancel"
+msgstr "Annulla"
+
+msgctxt "model:ir.model.button,string:opportunity_convert_button"
+msgid "Convert to Sale"
+msgstr "Convert to Sale"
+
+msgctxt "model:ir.model.button,string:opportunity_lead_button"
+msgid "Set as Lead"
+msgstr "Set as Lead"
+
+msgctxt "model:ir.model.button,string:opportunity_lost_button"
+msgid "Mark as Lost"
+msgstr "Mark as Lost"
+
+msgctxt "model:ir.model.button,string:opportunity_opportunity_button"
+msgid "Convert to Opportunity"
+msgstr "Convert to Opportunity"
+
+msgctxt "model:ir.rule.group,name:rule_group_opportunity_companies"
+msgid "User in companies"
+msgstr ""
+
+msgctxt "model:ir.rule.group,name:rule_group_opportunity_employee_companies"
+msgid "User in companies"
+msgstr ""
+
+msgctxt ""
+"model:ir.rule.group,name:rule_group_opportunity_employee_monthly_companies"
+msgid "User in companies"
+msgstr ""
+
+msgctxt "model:ir.rule.group,name:rule_group_opportunity_monthly_companies"
+msgid "User in companies"
+msgstr ""
+
+#, fuzzy
+msgctxt "model:ir.sequence,name:sequence_sale_opportunity"
+msgid "Sale Opportunity"
+msgstr "Sale Opportunity"
+
+#, fuzzy
+msgctxt "model:ir.sequence.type,name:sequence_type_sale_opportunity"
+msgid "Sale Opportunity"
+msgstr "Sale Opportunity"
+
+#, fuzzy
+msgctxt "model:ir.ui.menu,name:menu_opportunity_employee_monthly_form"
+msgid "Opportunities per Employee per Month"
+msgstr "Opportunities per Employee per Month"
+
+#, fuzzy
+msgctxt "model:ir.ui.menu,name:menu_opportunity_employee_open"
+msgid "Opportunities per Employee"
+msgstr "Opportunities per Employee"
+
+#, fuzzy
+msgctxt "model:ir.ui.menu,name:menu_opportunity_form"
+msgid "Leads and Opportunities"
+msgstr "Leads and Opportunities"
+
+#, fuzzy
+msgctxt "model:ir.ui.menu,name:menu_opportunity_monthly_form"
+msgid "Opportunities per Month"
+msgstr "Opportunities per Month"
+
+#, fuzzy
+msgctxt "model:res.group,name:group_opportunity"
+msgid "Sale Opportunity"
+msgstr "Sale Opportunity"
+
+msgctxt "model:sale.opportunity,name:"
+msgid "Sale Opportunity"
+msgstr "opportunity di vendita"
+
+msgctxt "model:sale.opportunity.line,name:"
+msgid "Sale Opportunity Line"
+msgstr "riga opportunity di vendita"
+
+msgctxt "model:sale.opportunity_employee,name:"
+msgid "Sale Opportunity per Employee"
+msgstr "opportunity di vendita per dipendente"
+
+msgctxt "model:sale.opportunity_employee.context,name:"
+msgid "Sale Opportunity per Employee Context"
+msgstr "context opportunity di vendita per dipendente"
+
+msgctxt "model:sale.opportunity_employee_monthly,name:"
+msgid "Sale Opportunity per Employee per Month"
+msgstr "opportunity di vendita per dipendente per mese"
+
+msgctxt "model:sale.opportunity_monthly,name:"
+msgid "Sale Opportunity per Month"
+msgstr "opportunity di vendita per mese"
+
+msgctxt "selection:sale.opportunity,state:"
+msgid "Cancelled"
+msgstr "Annullato"
+
+msgctxt "selection:sale.opportunity,state:"
+msgid "Converted"
+msgstr "convertito"
+
+msgctxt "selection:sale.opportunity,state:"
+msgid "Lead"
+msgstr "lead"
+
+msgctxt "selection:sale.opportunity,state:"
+msgid "Lost"
+msgstr "Perso"
+
+msgctxt "selection:sale.opportunity,state:"
+msgid "Opportunity"
+msgstr "opportunity"
+
+msgctxt "selection:sale.opportunity,state:"
+msgid "Won"
+msgstr "conseguito"
+
+msgctxt "view:sale.opportunity:"
+msgid "%"
+msgstr "%"
+
+msgctxt "view:sale.opportunity:"
+msgid "Lead/Opportunity"
+msgstr "lead / opportunity"
+
+#, fuzzy
+msgctxt "view:sale.opportunity_employee:"
+msgid "%"
+msgstr "%"
+
+#, fuzzy
+msgctxt "view:sale.opportunity_employee_monthly:"
+msgid "%"
+msgstr "%"
+
+#, fuzzy
+msgctxt "view:sale.opportunity_monthly:"
+msgid "%"
+msgstr "%"
diff --git a/modules/sale_opportunity/locale/lo.po b/modules/sale_opportunity/locale/lo.po
new file mode 100644
index 0000000000..fa1d5daf03
--- /dev/null
+++ b/modules/sale_opportunity/locale/lo.po
@@ -0,0 +1,604 @@
+#
+msgid ""
+msgstr "Content-Type: text/plain; charset=utf-8\n"
+
+msgctxt "field:sale.configuration,sale_opportunity_sequence:"
+msgid "Opportunity Sequence"
+msgstr ""
+
+msgctxt "field:sale.configuration.sequence,sale_opportunity_sequence:"
+msgid "Opportunity Sequence"
+msgstr ""
+
+#, fuzzy
+msgctxt "field:sale.opportunity,address:"
+msgid "Address"
+msgstr "ທີ່ຢູ່"
+
+#, fuzzy
+msgctxt "field:sale.opportunity,amount:"
+msgid "Amount"
+msgstr "ມູນຄ່າ"
+
+#, fuzzy
+msgctxt "field:sale.opportunity,comment:"
+msgid "Comment"
+msgstr "ຄໍາເຫັນ"
+
+#, fuzzy
+msgctxt "field:sale.opportunity,company:"
+msgid "Company"
+msgstr "ຫ້ອງການ/ສຳນັກງານ"
+
+msgctxt "field:sale.opportunity,contact:"
+msgid "Contact"
+msgstr ""
+
+msgctxt "field:sale.opportunity,conversion_probability:"
+msgid "Conversion Probability"
+msgstr ""
+
+#, fuzzy
+msgctxt "field:sale.opportunity,converted_by:"
+msgid "Converted By"
+msgstr "Converted"
+
+#, fuzzy
+msgctxt "field:sale.opportunity,currency:"
+msgid "Currency"
+msgstr "ສະກຸນເງິນ"
+
+#, fuzzy
+msgctxt "field:sale.opportunity,currency_digits:"
+msgid "Currency Digits"
+msgstr "ໂຕເລກສະກຸນເງິນ"
+
+#, fuzzy
+msgctxt "field:sale.opportunity,description:"
+msgid "Description"
+msgstr "ເນື້ອໃນລາຍການ"
+
+#, fuzzy
+msgctxt "field:sale.opportunity,employee:"
+msgid "Employee"
+msgstr "ພະນັກງານ"
+
+#, fuzzy
+msgctxt "field:sale.opportunity,end_date:"
+msgid "End Date"
+msgstr "ວັນທີສິ້ນສຸດ"
+
+#, fuzzy
+msgctxt "field:sale.opportunity,lines:"
+msgid "Lines"
+msgstr "ຮ່ວງ"
+
+msgctxt "field:sale.opportunity,lost_reason:"
+msgid "Reason for loss"
+msgstr ""
+
+#, fuzzy
+msgctxt "field:sale.opportunity,number:"
+msgid "Number"
+msgstr "ເລກທີ"
+
+#, fuzzy
+msgctxt "field:sale.opportunity,party:"
+msgid "Party"
+msgstr "ພາກສ່ວນ"
+
+#, fuzzy
+msgctxt "field:sale.opportunity,payment_term:"
+msgid "Payment Term"
+msgstr "ໄລຍະຊໍາລະ"
+
+#, fuzzy
+msgctxt "field:sale.opportunity,reference:"
+msgid "Reference"
+msgstr "ເອກະສານອ້າງອີງ"
+
+#, fuzzy
+msgctxt "field:sale.opportunity,sales:"
+msgid "Sales"
+msgstr "Sales"
+
+#, fuzzy
+msgctxt "field:sale.opportunity,start_date:"
+msgid "Start Date"
+msgstr "ວັນທີເລີ່ມ"
+
+#, fuzzy
+msgctxt "field:sale.opportunity,state:"
+msgid "State"
+msgstr "ສະຖານະ"
+
+#, fuzzy
+msgctxt "field:sale.opportunity.line,opportunity:"
+msgid "Opportunity"
+msgstr "Opportunities"
+
+msgctxt "field:sale.opportunity.line,opportunity_state:"
+msgid "Opportunity State"
+msgstr ""
+
+#, fuzzy
+msgctxt "field:sale.opportunity.line,product:"
+msgid "Product"
+msgstr "ຜະລິດຕະພັນ"
+
+#, fuzzy
+msgctxt "field:sale.opportunity.line,quantity:"
+msgid "Quantity"
+msgstr "ຈຳນວນ"
+
+#, fuzzy
+msgctxt "field:sale.opportunity.line,unit:"
+msgid "Unit"
+msgstr "ໜ່ວຍ"
+
+#, fuzzy
+msgctxt "field:sale.opportunity.line,unit_digits:"
+msgid "Unit Digits"
+msgstr "ຫົວໜ່ວຍເສດ"
+
+#, fuzzy
+msgctxt "field:sale.opportunity_employee,amount:"
+msgid "Amount"
+msgstr "ມູນຄ່າ"
+
+#, fuzzy
+msgctxt "field:sale.opportunity_employee,company:"
+msgid "Company"
+msgstr "ຫ້ອງການ/ສຳນັກງານ"
+
+msgctxt "field:sale.opportunity_employee,conversion_amount_rate:"
+msgid "Conversion Amount Rate"
+msgstr ""
+
+msgctxt "field:sale.opportunity_employee,conversion_rate:"
+msgid "Conversion Rate"
+msgstr ""
+
+#, fuzzy
+msgctxt "field:sale.opportunity_employee,converted:"
+msgid "Converted"
+msgstr "Converted"
+
+msgctxt "field:sale.opportunity_employee,converted_amount:"
+msgid "Converted Amount"
+msgstr ""
+
+#, fuzzy
+msgctxt "field:sale.opportunity_employee,currency:"
+msgid "Currency"
+msgstr "ສະກຸນເງິນ"
+
+#, fuzzy
+msgctxt "field:sale.opportunity_employee,currency_digits:"
+msgid "Currency Digits"
+msgstr "ໂຕເລກສະກຸນເງິນ"
+
+#, fuzzy
+msgctxt "field:sale.opportunity_employee,employee:"
+msgid "Employee"
+msgstr "ພະນັກງານ"
+
+#, fuzzy
+msgctxt "field:sale.opportunity_employee,lost:"
+msgid "Lost"
+msgstr "Lost"
+
+#, fuzzy
+msgctxt "field:sale.opportunity_employee,number:"
+msgid "Number"
+msgstr "ເລກທີ"
+
+msgctxt "field:sale.opportunity_employee,winning_amount_rate:"
+msgid "Winning Amount Rate"
+msgstr ""
+
+msgctxt "field:sale.opportunity_employee,winning_rate:"
+msgid "Winning Rate"
+msgstr ""
+
+#, fuzzy
+msgctxt "field:sale.opportunity_employee,won:"
+msgid "Won"
+msgstr "ວອນ ເກົາຫຼີໃຕ້"
+
+msgctxt "field:sale.opportunity_employee,won_amount:"
+msgid "Won Amount"
+msgstr ""
+
+#, fuzzy
+msgctxt "field:sale.opportunity_employee.context,end_date:"
+msgid "End Date"
+msgstr "ວັນທີສິ້ນສຸດ"
+
+#, fuzzy
+msgctxt "field:sale.opportunity_employee.context,start_date:"
+msgid "Start Date"
+msgstr "ວັນທີເລີ່ມ"
+
+#, fuzzy
+msgctxt "field:sale.opportunity_employee_monthly,amount:"
+msgid "Amount"
+msgstr "ມູນຄ່າ"
+
+#, fuzzy
+msgctxt "field:sale.opportunity_employee_monthly,company:"
+msgid "Company"
+msgstr "ຫ້ອງການ/ສຳນັກງານ"
+
+msgctxt "field:sale.opportunity_employee_monthly,conversion_amount_rate:"
+msgid "Conversion Amount Rate"
+msgstr ""
+
+msgctxt "field:sale.opportunity_employee_monthly,conversion_rate:"
+msgid "Conversion Rate"
+msgstr ""
+
+#, fuzzy
+msgctxt "field:sale.opportunity_employee_monthly,converted:"
+msgid "Converted"
+msgstr "Converted"
+
+msgctxt "field:sale.opportunity_employee_monthly,converted_amount:"
+msgid "Converted Amount"
+msgstr ""
+
+#, fuzzy
+msgctxt "field:sale.opportunity_employee_monthly,currency:"
+msgid "Currency"
+msgstr "ສະກຸນເງິນ"
+
+#, fuzzy
+msgctxt "field:sale.opportunity_employee_monthly,currency_digits:"
+msgid "Currency Digits"
+msgstr "ໂຕເລກສະກຸນເງິນ"
+
+#, fuzzy
+msgctxt "field:sale.opportunity_employee_monthly,employee:"
+msgid "Employee"
+msgstr "ພະນັກງານ"
+
+#, fuzzy
+msgctxt "field:sale.opportunity_employee_monthly,lost:"
+msgid "Lost"
+msgstr "Lost"
+
+#, fuzzy
+msgctxt "field:sale.opportunity_employee_monthly,month:"
+msgid "Month"
+msgstr "ເດືອນ"
+
+#, fuzzy
+msgctxt "field:sale.opportunity_employee_monthly,number:"
+msgid "Number"
+msgstr "ເລກທີ"
+
+msgctxt "field:sale.opportunity_employee_monthly,winning_amount_rate:"
+msgid "Winning Amount Rate"
+msgstr ""
+
+msgctxt "field:sale.opportunity_employee_monthly,winning_rate:"
+msgid "Winning Rate"
+msgstr ""
+
+#, fuzzy
+msgctxt "field:sale.opportunity_employee_monthly,won:"
+msgid "Won"
+msgstr "ວອນ ເກົາຫຼີໃຕ້"
+
+msgctxt "field:sale.opportunity_employee_monthly,won_amount:"
+msgid "Won Amount"
+msgstr ""
+
+#, fuzzy
+msgctxt "field:sale.opportunity_employee_monthly,year:"
+msgid "Year"
+msgstr "ປີ"
+
+#, fuzzy
+msgctxt "field:sale.opportunity_monthly,amount:"
+msgid "Amount"
+msgstr "ມູນຄ່າ"
+
+#, fuzzy
+msgctxt "field:sale.opportunity_monthly,company:"
+msgid "Company"
+msgstr "ຫ້ອງການ/ສຳນັກງານ"
+
+msgctxt "field:sale.opportunity_monthly,conversion_amount_rate:"
+msgid "Conversion Amount Rate"
+msgstr ""
+
+msgctxt "field:sale.opportunity_monthly,conversion_rate:"
+msgid "Conversion Rate"
+msgstr ""
+
+#, fuzzy
+msgctxt "field:sale.opportunity_monthly,converted:"
+msgid "Converted"
+msgstr "Converted"
+
+msgctxt "field:sale.opportunity_monthly,converted_amount:"
+msgid "Converted Amount"
+msgstr ""
+
+#, fuzzy
+msgctxt "field:sale.opportunity_monthly,currency:"
+msgid "Currency"
+msgstr "ສະກຸນເງິນ"
+
+#, fuzzy
+msgctxt "field:sale.opportunity_monthly,currency_digits:"
+msgid "Currency Digits"
+msgstr "ໂຕເລກສະກຸນເງິນ"
+
+#, fuzzy
+msgctxt "field:sale.opportunity_monthly,lost:"
+msgid "Lost"
+msgstr "Lost"
+
+#, fuzzy
+msgctxt "field:sale.opportunity_monthly,month:"
+msgid "Month"
+msgstr "ເດືອນ"
+
+#, fuzzy
+msgctxt "field:sale.opportunity_monthly,number:"
+msgid "Number"
+msgstr "ເລກທີ"
+
+msgctxt "field:sale.opportunity_monthly,winning_amount_rate:"
+msgid "Winning Amount Rate"
+msgstr ""
+
+msgctxt "field:sale.opportunity_monthly,winning_rate:"
+msgid "Winning Rate"
+msgstr ""
+
+#, fuzzy
+msgctxt "field:sale.opportunity_monthly,won:"
+msgid "Won"
+msgstr "ວອນ ເກົາຫຼີໃຕ້"
+
+msgctxt "field:sale.opportunity_monthly,won_amount:"
+msgid "Won Amount"
+msgstr ""
+
+#, fuzzy
+msgctxt "field:sale.opportunity_monthly,year:"
+msgid "Year"
+msgstr "ປີ"
+
+msgctxt "field:sale.opportunity_monthly,year_month:"
+msgid "Year-Month"
+msgstr ""
+
+msgctxt "help:sale.opportunity,amount:"
+msgid "Estimated revenue amount."
+msgstr ""
+
+msgctxt "help:sale.opportunity,conversion_probability:"
+msgid "Percentage between 0 and 100."
+msgstr ""
+
+msgctxt "model:ir.action,name:act_open_sale_form"
+msgid "Sales"
+msgstr "Sales"
+
+msgctxt "model:ir.action,name:act_opportunity_employee_form"
+msgid "Opportunities per Employee"
+msgstr "Opportunities per Employee"
+
+msgctxt "model:ir.action,name:act_opportunity_employee_monthly_form"
+msgid "Opportunities per Employee per Month"
+msgstr "Opportunities per Employee per Month"
+
+msgctxt "model:ir.action,name:act_opportunity_form"
+msgid "Leads and Opportunities"
+msgstr "Leads and Opportunities"
+
+msgctxt "model:ir.action,name:act_opportunity_form2"
+msgid "Sales Leads/Opportunities"
+msgstr "Sales Leads/Opportunities"
+
+msgctxt "model:ir.action,name:act_opportunity_monthly_form"
+msgid "Opportunities per Month"
+msgstr "Opportunities per Month"
+
+#, fuzzy
+msgctxt ""
+"model:ir.action.act_window.domain,name:act_opportunity_form_domain_all"
+msgid "All"
+msgstr "ທັງໝົດ"
+
+msgctxt ""
+"model:ir.action.act_window.domain,name:act_opportunity_form_domain_cancelled"
+msgid "Cancelled"
+msgstr "Cancelled"
+
+msgctxt ""
+"model:ir.action.act_window.domain,name:act_opportunity_form_domain_converted"
+msgid "Converted"
+msgstr "Converted"
+
+msgctxt ""
+"model:ir.action.act_window.domain,name:act_opportunity_form_domain_leads"
+msgid "Leads"
+msgstr "Leads"
+
+msgctxt ""
+"model:ir.action.act_window.domain,name:act_opportunity_form_domain_lost"
+msgid "Lost"
+msgstr "Lost"
+
+msgctxt ""
+"model:ir.action.act_window.domain,name:act_opportunity_form_domain_opportunities"
+msgid "Opportunities"
+msgstr "Opportunities"
+
+#, fuzzy
+msgctxt ""
+"model:ir.action.act_window.domain,name:act_opportunity_form_domain_won"
+msgid "Won"
+msgstr "ວອນ ເກົາຫຼີໃຕ້"
+
+msgctxt "model:ir.message,text:msg_modify_origin_opportunity"
+msgid "You cannot modify the opportunity origin of the sale \"%(sale)s\"."
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_opportunity_delete_cancel"
+msgid "To delete opportunity \"%(opportunity)s\", you must cancel it."
+msgstr ""
+
+msgctxt "model:ir.model.button,string:opportunity_cancel_button"
+msgid "Cancel"
+msgstr "Cancel"
+
+msgctxt "model:ir.model.button,string:opportunity_convert_button"
+msgid "Convert to Sale"
+msgstr "Convert to Sale"
+
+msgctxt "model:ir.model.button,string:opportunity_lead_button"
+msgid "Set as Lead"
+msgstr "Set as Lead"
+
+msgctxt "model:ir.model.button,string:opportunity_lost_button"
+msgid "Mark as Lost"
+msgstr "Mark as Lost"
+
+msgctxt "model:ir.model.button,string:opportunity_opportunity_button"
+msgid "Convert to Opportunity"
+msgstr "Convert to Opportunity"
+
+msgctxt "model:ir.rule.group,name:rule_group_opportunity_companies"
+msgid "User in companies"
+msgstr ""
+
+msgctxt "model:ir.rule.group,name:rule_group_opportunity_employee_companies"
+msgid "User in companies"
+msgstr ""
+
+msgctxt ""
+"model:ir.rule.group,name:rule_group_opportunity_employee_monthly_companies"
+msgid "User in companies"
+msgstr ""
+
+msgctxt "model:ir.rule.group,name:rule_group_opportunity_monthly_companies"
+msgid "User in companies"
+msgstr ""
+
+msgctxt "model:ir.sequence,name:sequence_sale_opportunity"
+msgid "Sale Opportunity"
+msgstr "Sale Opportunity"
+
+msgctxt "model:ir.sequence.type,name:sequence_type_sale_opportunity"
+msgid "Sale Opportunity"
+msgstr "Sale Opportunity"
+
+msgctxt "model:ir.ui.menu,name:menu_opportunity_employee_monthly_form"
+msgid "Opportunities per Employee per Month"
+msgstr "Opportunities per Employee per Month"
+
+msgctxt "model:ir.ui.menu,name:menu_opportunity_employee_open"
+msgid "Opportunities per Employee"
+msgstr "Opportunities per Employee"
+
+msgctxt "model:ir.ui.menu,name:menu_opportunity_form"
+msgid "Leads and Opportunities"
+msgstr "Leads and Opportunities"
+
+msgctxt "model:ir.ui.menu,name:menu_opportunity_monthly_form"
+msgid "Opportunities per Month"
+msgstr "Opportunities per Month"
+
+msgctxt "model:res.group,name:group_opportunity"
+msgid "Sale Opportunity"
+msgstr "Sale Opportunity"
+
+#, fuzzy
+msgctxt "model:sale.opportunity,name:"
+msgid "Sale Opportunity"
+msgstr "Sale Opportunity"
+
+#, fuzzy
+msgctxt "model:sale.opportunity.line,name:"
+msgid "Sale Opportunity Line"
+msgstr "Sale Opportunity"
+
+#, fuzzy
+msgctxt "model:sale.opportunity_employee,name:"
+msgid "Sale Opportunity per Employee"
+msgstr "Opportunities per Employee per Month"
+
+#, fuzzy
+msgctxt "model:sale.opportunity_employee.context,name:"
+msgid "Sale Opportunity per Employee Context"
+msgstr "Opportunities per Employee per Month"
+
+#, fuzzy
+msgctxt "model:sale.opportunity_employee_monthly,name:"
+msgid "Sale Opportunity per Employee per Month"
+msgstr "Opportunities per Employee per Month"
+
+#, fuzzy
+msgctxt "model:sale.opportunity_monthly,name:"
+msgid "Sale Opportunity per Month"
+msgstr "Opportunities per Employee per Month"
+
+#, fuzzy
+msgctxt "selection:sale.opportunity,state:"
+msgid "Cancelled"
+msgstr "Cancelled"
+
+#, fuzzy
+msgctxt "selection:sale.opportunity,state:"
+msgid "Converted"
+msgstr "Converted"
+
+#, fuzzy
+msgctxt "selection:sale.opportunity,state:"
+msgid "Lead"
+msgstr "Leads"
+
+#, fuzzy
+msgctxt "selection:sale.opportunity,state:"
+msgid "Lost"
+msgstr "Lost"
+
+#, fuzzy
+msgctxt "selection:sale.opportunity,state:"
+msgid "Opportunity"
+msgstr "Opportunities"
+
+#, fuzzy
+msgctxt "selection:sale.opportunity,state:"
+msgid "Won"
+msgstr "ວອນ ເກົາຫຼີໃຕ້"
+
+#, fuzzy
+msgctxt "view:sale.opportunity:"
+msgid "%"
+msgstr "%"
+
+msgctxt "view:sale.opportunity:"
+msgid "Lead/Opportunity"
+msgstr ""
+
+#, fuzzy
+msgctxt "view:sale.opportunity_employee:"
+msgid "%"
+msgstr "%"
+
+#, fuzzy
+msgctxt "view:sale.opportunity_employee_monthly:"
+msgid "%"
+msgstr "%"
+
+#, fuzzy
+msgctxt "view:sale.opportunity_monthly:"
+msgid "%"
+msgstr "%"
diff --git a/modules/sale_opportunity/locale/lt.po b/modules/sale_opportunity/locale/lt.po
new file mode 100644
index 0000000000..28193c4962
--- /dev/null
+++ b/modules/sale_opportunity/locale/lt.po
@@ -0,0 +1,560 @@
+#
+msgid ""
+msgstr "Content-Type: text/plain; charset=utf-8\n"
+
+msgctxt "field:sale.configuration,sale_opportunity_sequence:"
+msgid "Opportunity Sequence"
+msgstr ""
+
+msgctxt "field:sale.configuration.sequence,sale_opportunity_sequence:"
+msgid "Opportunity Sequence"
+msgstr ""
+
+msgctxt "field:sale.opportunity,address:"
+msgid "Address"
+msgstr "Adresas"
+
+msgctxt "field:sale.opportunity,amount:"
+msgid "Amount"
+msgstr ""
+
+msgctxt "field:sale.opportunity,comment:"
+msgid "Comment"
+msgstr "Komentaras"
+
+msgctxt "field:sale.opportunity,company:"
+msgid "Company"
+msgstr "Organizacija"
+
+msgctxt "field:sale.opportunity,contact:"
+msgid "Contact"
+msgstr ""
+
+msgctxt "field:sale.opportunity,conversion_probability:"
+msgid "Conversion Probability"
+msgstr ""
+
+#, fuzzy
+msgctxt "field:sale.opportunity,converted_by:"
+msgid "Converted By"
+msgstr "Converted"
+
+msgctxt "field:sale.opportunity,currency:"
+msgid "Currency"
+msgstr "Valiuta"
+
+msgctxt "field:sale.opportunity,currency_digits:"
+msgid "Currency Digits"
+msgstr "Valiutos skaitmenų skaičius"
+
+msgctxt "field:sale.opportunity,description:"
+msgid "Description"
+msgstr ""
+
+msgctxt "field:sale.opportunity,employee:"
+msgid "Employee"
+msgstr ""
+
+msgctxt "field:sale.opportunity,end_date:"
+msgid "End Date"
+msgstr "Pabaigos data"
+
+msgctxt "field:sale.opportunity,lines:"
+msgid "Lines"
+msgstr ""
+
+msgctxt "field:sale.opportunity,lost_reason:"
+msgid "Reason for loss"
+msgstr ""
+
+msgctxt "field:sale.opportunity,number:"
+msgid "Number"
+msgstr ""
+
+msgctxt "field:sale.opportunity,party:"
+msgid "Party"
+msgstr "Kontrahentas"
+
+msgctxt "field:sale.opportunity,payment_term:"
+msgid "Payment Term"
+msgstr ""
+
+msgctxt "field:sale.opportunity,reference:"
+msgid "Reference"
+msgstr ""
+
+#, fuzzy
+msgctxt "field:sale.opportunity,sales:"
+msgid "Sales"
+msgstr "Sales"
+
+msgctxt "field:sale.opportunity,start_date:"
+msgid "Start Date"
+msgstr "Pradžios data"
+
+msgctxt "field:sale.opportunity,state:"
+msgid "State"
+msgstr ""
+
+#, fuzzy
+msgctxt "field:sale.opportunity.line,opportunity:"
+msgid "Opportunity"
+msgstr "Opportunities"
+
+msgctxt "field:sale.opportunity.line,opportunity_state:"
+msgid "Opportunity State"
+msgstr ""
+
+msgctxt "field:sale.opportunity.line,product:"
+msgid "Product"
+msgstr ""
+
+msgctxt "field:sale.opportunity.line,quantity:"
+msgid "Quantity"
+msgstr ""
+
+msgctxt "field:sale.opportunity.line,unit:"
+msgid "Unit"
+msgstr ""
+
+msgctxt "field:sale.opportunity.line,unit_digits:"
+msgid "Unit Digits"
+msgstr ""
+
+msgctxt "field:sale.opportunity_employee,amount:"
+msgid "Amount"
+msgstr ""
+
+msgctxt "field:sale.opportunity_employee,company:"
+msgid "Company"
+msgstr "Organizacija"
+
+msgctxt "field:sale.opportunity_employee,conversion_amount_rate:"
+msgid "Conversion Amount Rate"
+msgstr ""
+
+msgctxt "field:sale.opportunity_employee,conversion_rate:"
+msgid "Conversion Rate"
+msgstr ""
+
+#, fuzzy
+msgctxt "field:sale.opportunity_employee,converted:"
+msgid "Converted"
+msgstr "Converted"
+
+msgctxt "field:sale.opportunity_employee,converted_amount:"
+msgid "Converted Amount"
+msgstr ""
+
+msgctxt "field:sale.opportunity_employee,currency:"
+msgid "Currency"
+msgstr "Valiuta"
+
+msgctxt "field:sale.opportunity_employee,currency_digits:"
+msgid "Currency Digits"
+msgstr "Valiutos skaitmenų skaičius"
+
+msgctxt "field:sale.opportunity_employee,employee:"
+msgid "Employee"
+msgstr ""
+
+#, fuzzy
+msgctxt "field:sale.opportunity_employee,lost:"
+msgid "Lost"
+msgstr "Lost"
+
+msgctxt "field:sale.opportunity_employee,number:"
+msgid "Number"
+msgstr ""
+
+msgctxt "field:sale.opportunity_employee,winning_amount_rate:"
+msgid "Winning Amount Rate"
+msgstr ""
+
+msgctxt "field:sale.opportunity_employee,winning_rate:"
+msgid "Winning Rate"
+msgstr ""
+
+#, fuzzy
+msgctxt "field:sale.opportunity_employee,won:"
+msgid "Won"
+msgstr "Vonas"
+
+msgctxt "field:sale.opportunity_employee,won_amount:"
+msgid "Won Amount"
+msgstr ""
+
+msgctxt "field:sale.opportunity_employee.context,end_date:"
+msgid "End Date"
+msgstr "Pabaigos data"
+
+msgctxt "field:sale.opportunity_employee.context,start_date:"
+msgid "Start Date"
+msgstr "Pradžios data"
+
+msgctxt "field:sale.opportunity_employee_monthly,amount:"
+msgid "Amount"
+msgstr ""
+
+msgctxt "field:sale.opportunity_employee_monthly,company:"
+msgid "Company"
+msgstr "Organizacija"
+
+msgctxt "field:sale.opportunity_employee_monthly,conversion_amount_rate:"
+msgid "Conversion Amount Rate"
+msgstr ""
+
+msgctxt "field:sale.opportunity_employee_monthly,conversion_rate:"
+msgid "Conversion Rate"
+msgstr ""
+
+#, fuzzy
+msgctxt "field:sale.opportunity_employee_monthly,converted:"
+msgid "Converted"
+msgstr "Converted"
+
+msgctxt "field:sale.opportunity_employee_monthly,converted_amount:"
+msgid "Converted Amount"
+msgstr ""
+
+msgctxt "field:sale.opportunity_employee_monthly,currency:"
+msgid "Currency"
+msgstr "Valiuta"
+
+msgctxt "field:sale.opportunity_employee_monthly,currency_digits:"
+msgid "Currency Digits"
+msgstr "Valiutos skaitmenų skaičius"
+
+msgctxt "field:sale.opportunity_employee_monthly,employee:"
+msgid "Employee"
+msgstr ""
+
+#, fuzzy
+msgctxt "field:sale.opportunity_employee_monthly,lost:"
+msgid "Lost"
+msgstr "Lost"
+
+msgctxt "field:sale.opportunity_employee_monthly,month:"
+msgid "Month"
+msgstr ""
+
+msgctxt "field:sale.opportunity_employee_monthly,number:"
+msgid "Number"
+msgstr ""
+
+msgctxt "field:sale.opportunity_employee_monthly,winning_amount_rate:"
+msgid "Winning Amount Rate"
+msgstr ""
+
+msgctxt "field:sale.opportunity_employee_monthly,winning_rate:"
+msgid "Winning Rate"
+msgstr ""
+
+#, fuzzy
+msgctxt "field:sale.opportunity_employee_monthly,won:"
+msgid "Won"
+msgstr "Vonas"
+
+msgctxt "field:sale.opportunity_employee_monthly,won_amount:"
+msgid "Won Amount"
+msgstr ""
+
+msgctxt "field:sale.opportunity_employee_monthly,year:"
+msgid "Year"
+msgstr ""
+
+msgctxt "field:sale.opportunity_monthly,amount:"
+msgid "Amount"
+msgstr ""
+
+msgctxt "field:sale.opportunity_monthly,company:"
+msgid "Company"
+msgstr "Organizacija"
+
+msgctxt "field:sale.opportunity_monthly,conversion_amount_rate:"
+msgid "Conversion Amount Rate"
+msgstr ""
+
+msgctxt "field:sale.opportunity_monthly,conversion_rate:"
+msgid "Conversion Rate"
+msgstr ""
+
+#, fuzzy
+msgctxt "field:sale.opportunity_monthly,converted:"
+msgid "Converted"
+msgstr "Converted"
+
+msgctxt "field:sale.opportunity_monthly,converted_amount:"
+msgid "Converted Amount"
+msgstr ""
+
+msgctxt "field:sale.opportunity_monthly,currency:"
+msgid "Currency"
+msgstr "Valiuta"
+
+msgctxt "field:sale.opportunity_monthly,currency_digits:"
+msgid "Currency Digits"
+msgstr "Valiutos skaitmenų skaičius"
+
+#, fuzzy
+msgctxt "field:sale.opportunity_monthly,lost:"
+msgid "Lost"
+msgstr "Lost"
+
+msgctxt "field:sale.opportunity_monthly,month:"
+msgid "Month"
+msgstr ""
+
+msgctxt "field:sale.opportunity_monthly,number:"
+msgid "Number"
+msgstr ""
+
+msgctxt "field:sale.opportunity_monthly,winning_amount_rate:"
+msgid "Winning Amount Rate"
+msgstr ""
+
+msgctxt "field:sale.opportunity_monthly,winning_rate:"
+msgid "Winning Rate"
+msgstr ""
+
+#, fuzzy
+msgctxt "field:sale.opportunity_monthly,won:"
+msgid "Won"
+msgstr "Vonas"
+
+msgctxt "field:sale.opportunity_monthly,won_amount:"
+msgid "Won Amount"
+msgstr ""
+
+msgctxt "field:sale.opportunity_monthly,year:"
+msgid "Year"
+msgstr ""
+
+msgctxt "field:sale.opportunity_monthly,year_month:"
+msgid "Year-Month"
+msgstr ""
+
+msgctxt "help:sale.opportunity,amount:"
+msgid "Estimated revenue amount."
+msgstr ""
+
+msgctxt "help:sale.opportunity,conversion_probability:"
+msgid "Percentage between 0 and 100."
+msgstr ""
+
+msgctxt "model:ir.action,name:act_open_sale_form"
+msgid "Sales"
+msgstr "Sales"
+
+msgctxt "model:ir.action,name:act_opportunity_employee_form"
+msgid "Opportunities per Employee"
+msgstr "Opportunities per Employee"
+
+msgctxt "model:ir.action,name:act_opportunity_employee_monthly_form"
+msgid "Opportunities per Employee per Month"
+msgstr "Opportunities per Employee per Month"
+
+msgctxt "model:ir.action,name:act_opportunity_form"
+msgid "Leads and Opportunities"
+msgstr "Leads and Opportunities"
+
+msgctxt "model:ir.action,name:act_opportunity_form2"
+msgid "Sales Leads/Opportunities"
+msgstr "Sales Leads/Opportunities"
+
+msgctxt "model:ir.action,name:act_opportunity_monthly_form"
+msgid "Opportunities per Month"
+msgstr "Opportunities per Month"
+
+msgctxt ""
+"model:ir.action.act_window.domain,name:act_opportunity_form_domain_all"
+msgid "All"
+msgstr "All"
+
+msgctxt ""
+"model:ir.action.act_window.domain,name:act_opportunity_form_domain_cancelled"
+msgid "Cancelled"
+msgstr "Cancelled"
+
+msgctxt ""
+"model:ir.action.act_window.domain,name:act_opportunity_form_domain_converted"
+msgid "Converted"
+msgstr "Converted"
+
+msgctxt ""
+"model:ir.action.act_window.domain,name:act_opportunity_form_domain_leads"
+msgid "Leads"
+msgstr "Leads"
+
+msgctxt ""
+"model:ir.action.act_window.domain,name:act_opportunity_form_domain_lost"
+msgid "Lost"
+msgstr "Lost"
+
+msgctxt ""
+"model:ir.action.act_window.domain,name:act_opportunity_form_domain_opportunities"
+msgid "Opportunities"
+msgstr "Opportunities"
+
+#, fuzzy
+msgctxt ""
+"model:ir.action.act_window.domain,name:act_opportunity_form_domain_won"
+msgid "Won"
+msgstr "Vonas"
+
+msgctxt "model:ir.message,text:msg_modify_origin_opportunity"
+msgid "You cannot modify the opportunity origin of the sale \"%(sale)s\"."
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_opportunity_delete_cancel"
+msgid "To delete opportunity \"%(opportunity)s\", you must cancel it."
+msgstr ""
+
+msgctxt "model:ir.model.button,string:opportunity_cancel_button"
+msgid "Cancel"
+msgstr "Cancel"
+
+msgctxt "model:ir.model.button,string:opportunity_convert_button"
+msgid "Convert to Sale"
+msgstr "Convert to Sale"
+
+msgctxt "model:ir.model.button,string:opportunity_lead_button"
+msgid "Set as Lead"
+msgstr "Set as Lead"
+
+msgctxt "model:ir.model.button,string:opportunity_lost_button"
+msgid "Mark as Lost"
+msgstr "Mark as Lost"
+
+msgctxt "model:ir.model.button,string:opportunity_opportunity_button"
+msgid "Convert to Opportunity"
+msgstr "Convert to Opportunity"
+
+msgctxt "model:ir.rule.group,name:rule_group_opportunity_companies"
+msgid "User in companies"
+msgstr ""
+
+msgctxt "model:ir.rule.group,name:rule_group_opportunity_employee_companies"
+msgid "User in companies"
+msgstr ""
+
+msgctxt ""
+"model:ir.rule.group,name:rule_group_opportunity_employee_monthly_companies"
+msgid "User in companies"
+msgstr ""
+
+msgctxt "model:ir.rule.group,name:rule_group_opportunity_monthly_companies"
+msgid "User in companies"
+msgstr ""
+
+msgctxt "model:ir.sequence,name:sequence_sale_opportunity"
+msgid "Sale Opportunity"
+msgstr "Sale Opportunity"
+
+msgctxt "model:ir.sequence.type,name:sequence_type_sale_opportunity"
+msgid "Sale Opportunity"
+msgstr "Sale Opportunity"
+
+msgctxt "model:ir.ui.menu,name:menu_opportunity_employee_monthly_form"
+msgid "Opportunities per Employee per Month"
+msgstr "Opportunities per Employee per Month"
+
+msgctxt "model:ir.ui.menu,name:menu_opportunity_employee_open"
+msgid "Opportunities per Employee"
+msgstr "Opportunities per Employee"
+
+msgctxt "model:ir.ui.menu,name:menu_opportunity_form"
+msgid "Leads and Opportunities"
+msgstr "Leads and Opportunities"
+
+msgctxt "model:ir.ui.menu,name:menu_opportunity_monthly_form"
+msgid "Opportunities per Month"
+msgstr "Opportunities per Month"
+
+msgctxt "model:res.group,name:group_opportunity"
+msgid "Sale Opportunity"
+msgstr "Sale Opportunity"
+
+#, fuzzy
+msgctxt "model:sale.opportunity,name:"
+msgid "Sale Opportunity"
+msgstr "Sale Opportunity"
+
+#, fuzzy
+msgctxt "model:sale.opportunity.line,name:"
+msgid "Sale Opportunity Line"
+msgstr "Sale Opportunity"
+
+#, fuzzy
+msgctxt "model:sale.opportunity_employee,name:"
+msgid "Sale Opportunity per Employee"
+msgstr "Opportunities per Employee per Month"
+
+#, fuzzy
+msgctxt "model:sale.opportunity_employee.context,name:"
+msgid "Sale Opportunity per Employee Context"
+msgstr "Opportunities per Employee per Month"
+
+#, fuzzy
+msgctxt "model:sale.opportunity_employee_monthly,name:"
+msgid "Sale Opportunity per Employee per Month"
+msgstr "Opportunities per Employee per Month"
+
+#, fuzzy
+msgctxt "model:sale.opportunity_monthly,name:"
+msgid "Sale Opportunity per Month"
+msgstr "Opportunities per Employee per Month"
+
+#, fuzzy
+msgctxt "selection:sale.opportunity,state:"
+msgid "Cancelled"
+msgstr "Cancelled"
+
+#, fuzzy
+msgctxt "selection:sale.opportunity,state:"
+msgid "Converted"
+msgstr "Converted"
+
+#, fuzzy
+msgctxt "selection:sale.opportunity,state:"
+msgid "Lead"
+msgstr "Leads"
+
+#, fuzzy
+msgctxt "selection:sale.opportunity,state:"
+msgid "Lost"
+msgstr "Lost"
+
+#, fuzzy
+msgctxt "selection:sale.opportunity,state:"
+msgid "Opportunity"
+msgstr "Opportunities"
+
+#, fuzzy
+msgctxt "selection:sale.opportunity,state:"
+msgid "Won"
+msgstr "Vonas"
+
+#, fuzzy
+msgctxt "view:sale.opportunity:"
+msgid "%"
+msgstr "%"
+
+msgctxt "view:sale.opportunity:"
+msgid "Lead/Opportunity"
+msgstr ""
+
+#, fuzzy
+msgctxt "view:sale.opportunity_employee:"
+msgid "%"
+msgstr "%"
+
+#, fuzzy
+msgctxt "view:sale.opportunity_employee_monthly:"
+msgid "%"
+msgstr "%"
+
+#, fuzzy
+msgctxt "view:sale.opportunity_monthly:"
+msgid "%"
+msgstr "%"
diff --git a/modules/sale_opportunity/locale/nl.po b/modules/sale_opportunity/locale/nl.po
new file mode 100644
index 0000000000..d5198ad51a
--- /dev/null
+++ b/modules/sale_opportunity/locale/nl.po
@@ -0,0 +1,537 @@
+#
+msgid ""
+msgstr "Content-Type: text/plain; charset=utf-8\n"
+
+msgctxt "field:sale.configuration,sale_opportunity_sequence:"
+msgid "Opportunity Sequence"
+msgstr "Volgorde kansen (opportynity)"
+
+msgctxt "field:sale.configuration.sequence,sale_opportunity_sequence:"
+msgid "Opportunity Sequence"
+msgstr "Volgorde kansen (opportynity)"
+
+msgctxt "field:sale.opportunity,address:"
+msgid "Address"
+msgstr "Adres"
+
+msgctxt "field:sale.opportunity,amount:"
+msgid "Amount"
+msgstr "Bedrag"
+
+msgctxt "field:sale.opportunity,comment:"
+msgid "Comment"
+msgstr "Opmerking"
+
+msgctxt "field:sale.opportunity,company:"
+msgid "Company"
+msgstr "Bedrijf"
+
+msgctxt "field:sale.opportunity,contact:"
+msgid "Contact"
+msgstr "Contact"
+
+msgctxt "field:sale.opportunity,conversion_probability:"
+msgid "Conversion Probability"
+msgstr "Conversie waarschijnlijkheid"
+
+msgctxt "field:sale.opportunity,converted_by:"
+msgid "Converted By"
+msgstr "Geconverteerd door"
+
+msgctxt "field:sale.opportunity,currency:"
+msgid "Currency"
+msgstr "Valuta"
+
+msgctxt "field:sale.opportunity,currency_digits:"
+msgid "Currency Digits"
+msgstr "Valuta decimalen"
+
+msgctxt "field:sale.opportunity,description:"
+msgid "Description"
+msgstr "Omschrijving"
+
+msgctxt "field:sale.opportunity,employee:"
+msgid "Employee"
+msgstr "Werknemer"
+
+msgctxt "field:sale.opportunity,end_date:"
+msgid "End Date"
+msgstr "Eind datum"
+
+msgctxt "field:sale.opportunity,lines:"
+msgid "Lines"
+msgstr "Regels"
+
+msgctxt "field:sale.opportunity,lost_reason:"
+msgid "Reason for loss"
+msgstr "Reden voor verlies"
+
+msgctxt "field:sale.opportunity,number:"
+msgid "Number"
+msgstr "Nummer"
+
+msgctxt "field:sale.opportunity,party:"
+msgid "Party"
+msgstr "Relatie"
+
+msgctxt "field:sale.opportunity,payment_term:"
+msgid "Payment Term"
+msgstr "Betalingstermijn"
+
+msgctxt "field:sale.opportunity,reference:"
+msgid "Reference"
+msgstr "Referentie"
+
+msgctxt "field:sale.opportunity,sales:"
+msgid "Sales"
+msgstr "Verkoop"
+
+msgctxt "field:sale.opportunity,start_date:"
+msgid "Start Date"
+msgstr "Start datum"
+
+msgctxt "field:sale.opportunity,state:"
+msgid "State"
+msgstr "Status"
+
+msgctxt "field:sale.opportunity.line,opportunity:"
+msgid "Opportunity"
+msgstr "Opportunitieiten"
+
+msgctxt "field:sale.opportunity.line,opportunity_state:"
+msgid "Opportunity State"
+msgstr "Status opportuniteit"
+
+msgctxt "field:sale.opportunity.line,product:"
+msgid "Product"
+msgstr "Product"
+
+msgctxt "field:sale.opportunity.line,quantity:"
+msgid "Quantity"
+msgstr "Hoeveelheid"
+
+msgctxt "field:sale.opportunity.line,unit:"
+msgid "Unit"
+msgstr "Eenheid"
+
+msgctxt "field:sale.opportunity.line,unit_digits:"
+msgid "Unit Digits"
+msgstr "Decimalen eenheid"
+
+msgctxt "field:sale.opportunity_employee,amount:"
+msgid "Amount"
+msgstr "Bedrag"
+
+msgctxt "field:sale.opportunity_employee,company:"
+msgid "Company"
+msgstr "Bedrijf"
+
+msgctxt "field:sale.opportunity_employee,conversion_amount_rate:"
+msgid "Conversion Amount Rate"
+msgstr "Conversie Bedrag"
+
+msgctxt "field:sale.opportunity_employee,conversion_rate:"
+msgid "Conversion Rate"
+msgstr "Conversieratio"
+
+msgctxt "field:sale.opportunity_employee,converted:"
+msgid "Converted"
+msgstr "geconverteerd"
+
+msgctxt "field:sale.opportunity_employee,converted_amount:"
+msgid "Converted Amount"
+msgstr "geconverteerd bedrag"
+
+msgctxt "field:sale.opportunity_employee,currency:"
+msgid "Currency"
+msgstr "Valuta"
+
+msgctxt "field:sale.opportunity_employee,currency_digits:"
+msgid "Currency Digits"
+msgstr "Valuta decimalen"
+
+msgctxt "field:sale.opportunity_employee,employee:"
+msgid "Employee"
+msgstr "Werknemer"
+
+msgctxt "field:sale.opportunity_employee,lost:"
+msgid "Lost"
+msgstr "Verloren"
+
+msgctxt "field:sale.opportunity_employee,number:"
+msgid "Number"
+msgstr "Nummer"
+
+msgctxt "field:sale.opportunity_employee,winning_amount_rate:"
+msgid "Winning Amount Rate"
+msgstr "Gewonnen bedrag"
+
+msgctxt "field:sale.opportunity_employee,winning_rate:"
+msgid "Winning Rate"
+msgstr "procent gewonnen"
+
+msgctxt "field:sale.opportunity_employee,won:"
+msgid "Won"
+msgstr "Gewonnen"
+
+msgctxt "field:sale.opportunity_employee,won_amount:"
+msgid "Won Amount"
+msgstr "Gewonnen bedrag"
+
+msgctxt "field:sale.opportunity_employee.context,end_date:"
+msgid "End Date"
+msgstr "Eind datum"
+
+msgctxt "field:sale.opportunity_employee.context,start_date:"
+msgid "Start Date"
+msgstr "Start datum"
+
+msgctxt "field:sale.opportunity_employee_monthly,amount:"
+msgid "Amount"
+msgstr "Bedrag"
+
+msgctxt "field:sale.opportunity_employee_monthly,company:"
+msgid "Company"
+msgstr "Bedrijf"
+
+msgctxt "field:sale.opportunity_employee_monthly,conversion_amount_rate:"
+msgid "Conversion Amount Rate"
+msgstr "Conversie Bedrag"
+
+msgctxt "field:sale.opportunity_employee_monthly,conversion_rate:"
+msgid "Conversion Rate"
+msgstr "succes percentage"
+
+msgctxt "field:sale.opportunity_employee_monthly,converted:"
+msgid "Converted"
+msgstr "geconverteerd"
+
+msgctxt "field:sale.opportunity_employee_monthly,converted_amount:"
+msgid "Converted Amount"
+msgstr "geconverteerd bedrag"
+
+msgctxt "field:sale.opportunity_employee_monthly,currency:"
+msgid "Currency"
+msgstr "Valuta"
+
+msgctxt "field:sale.opportunity_employee_monthly,currency_digits:"
+msgid "Currency Digits"
+msgstr "Valuta decimalen"
+
+msgctxt "field:sale.opportunity_employee_monthly,employee:"
+msgid "Employee"
+msgstr "Werknemer"
+
+msgctxt "field:sale.opportunity_employee_monthly,lost:"
+msgid "Lost"
+msgstr "Verloren"
+
+msgctxt "field:sale.opportunity_employee_monthly,month:"
+msgid "Month"
+msgstr "Maand"
+
+msgctxt "field:sale.opportunity_employee_monthly,number:"
+msgid "Number"
+msgstr "Nummer"
+
+msgctxt "field:sale.opportunity_employee_monthly,winning_amount_rate:"
+msgid "Winning Amount Rate"
+msgstr "Gewonnen bedrag"
+
+msgctxt "field:sale.opportunity_employee_monthly,winning_rate:"
+msgid "Winning Rate"
+msgstr "procent gewonnen"
+
+msgctxt "field:sale.opportunity_employee_monthly,won:"
+msgid "Won"
+msgstr "Gewonnen"
+
+msgctxt "field:sale.opportunity_employee_monthly,won_amount:"
+msgid "Won Amount"
+msgstr "Gewonnen bedrag"
+
+msgctxt "field:sale.opportunity_employee_monthly,year:"
+msgid "Year"
+msgstr "Jaar"
+
+msgctxt "field:sale.opportunity_monthly,amount:"
+msgid "Amount"
+msgstr "Bedrag"
+
+msgctxt "field:sale.opportunity_monthly,company:"
+msgid "Company"
+msgstr "Bedrijf"
+
+msgctxt "field:sale.opportunity_monthly,conversion_amount_rate:"
+msgid "Conversion Amount Rate"
+msgstr "Conversie Bedrag"
+
+msgctxt "field:sale.opportunity_monthly,conversion_rate:"
+msgid "Conversion Rate"
+msgstr "Conversieratio"
+
+msgctxt "field:sale.opportunity_monthly,converted:"
+msgid "Converted"
+msgstr "geconverteerd"
+
+msgctxt "field:sale.opportunity_monthly,converted_amount:"
+msgid "Converted Amount"
+msgstr "geconverteerd bedrag"
+
+msgctxt "field:sale.opportunity_monthly,currency:"
+msgid "Currency"
+msgstr "Valuta"
+
+msgctxt "field:sale.opportunity_monthly,currency_digits:"
+msgid "Currency Digits"
+msgstr "Valuta decimalen"
+
+msgctxt "field:sale.opportunity_monthly,lost:"
+msgid "Lost"
+msgstr "Verloren"
+
+msgctxt "field:sale.opportunity_monthly,month:"
+msgid "Month"
+msgstr "Maand"
+
+msgctxt "field:sale.opportunity_monthly,number:"
+msgid "Number"
+msgstr "Nummer"
+
+msgctxt "field:sale.opportunity_monthly,winning_amount_rate:"
+msgid "Winning Amount Rate"
+msgstr "Gewonnen bedrag"
+
+msgctxt "field:sale.opportunity_monthly,winning_rate:"
+msgid "Winning Rate"
+msgstr "procent gewonnen"
+
+msgctxt "field:sale.opportunity_monthly,won:"
+msgid "Won"
+msgstr "Gewonnen"
+
+msgctxt "field:sale.opportunity_monthly,won_amount:"
+msgid "Won Amount"
+msgstr "Gewonnen bedrag"
+
+msgctxt "field:sale.opportunity_monthly,year:"
+msgid "Year"
+msgstr "Jaar"
+
+msgctxt "field:sale.opportunity_monthly,year_month:"
+msgid "Year-Month"
+msgstr "jaar-maand"
+
+msgctxt "help:sale.opportunity,amount:"
+msgid "Estimated revenue amount."
+msgstr "Geschat omzetbedrag."
+
+msgctxt "help:sale.opportunity,conversion_probability:"
+msgid "Percentage between 0 and 100."
+msgstr "Percentage tussen 0 en 100."
+
+msgctxt "model:ir.action,name:act_open_sale_form"
+msgid "Sales"
+msgstr "Verkoop"
+
+msgctxt "model:ir.action,name:act_opportunity_employee_form"
+msgid "Opportunities per Employee"
+msgstr "Oppportuniteiten per werkneemer"
+
+msgctxt "model:ir.action,name:act_opportunity_employee_monthly_form"
+msgid "Opportunities per Employee per Month"
+msgstr "opportuniteit per werknemer per maand"
+
+msgctxt "model:ir.action,name:act_opportunity_form"
+msgid "Leads and Opportunities"
+msgstr "Geinteresseerden en opportuniteiten"
+
+msgctxt "model:ir.action,name:act_opportunity_form2"
+msgid "Sales Leads/Opportunities"
+msgstr "geinteresseerden / opportuniteiten"
+
+msgctxt "model:ir.action,name:act_opportunity_monthly_form"
+msgid "Opportunities per Month"
+msgstr "Opportuniteiten per maand"
+
+msgctxt ""
+"model:ir.action.act_window.domain,name:act_opportunity_form_domain_all"
+msgid "All"
+msgstr "Alle"
+
+msgctxt ""
+"model:ir.action.act_window.domain,name:act_opportunity_form_domain_cancelled"
+msgid "Cancelled"
+msgstr "Geannuleerd"
+
+msgctxt ""
+"model:ir.action.act_window.domain,name:act_opportunity_form_domain_converted"
+msgid "Converted"
+msgstr "geconverteerd"
+
+msgctxt ""
+"model:ir.action.act_window.domain,name:act_opportunity_form_domain_leads"
+msgid "Leads"
+msgstr "Leads"
+
+msgctxt ""
+"model:ir.action.act_window.domain,name:act_opportunity_form_domain_lost"
+msgid "Lost"
+msgstr "Verloren"
+
+msgctxt ""
+"model:ir.action.act_window.domain,name:act_opportunity_form_domain_opportunities"
+msgid "Opportunities"
+msgstr "Opportuniteiten"
+
+msgctxt ""
+"model:ir.action.act_window.domain,name:act_opportunity_form_domain_won"
+msgid "Won"
+msgstr "Gewonnen"
+
+msgctxt "model:ir.message,text:msg_modify_origin_opportunity"
+msgid "You cannot modify the opportunity origin of the sale \"%(sale)s\"."
+msgstr ""
+"U kunt de oorsprong van de verkoopkans van de verkoop \"%(sale)s\" niet "
+"wijzigen."
+
+msgctxt "model:ir.message,text:msg_opportunity_delete_cancel"
+msgid "To delete opportunity \"%(opportunity)s\", you must cancel it."
+msgstr "Om opportunity \"%(opportunity)s\" te verwijderen, moet u deze annuleren."
+
+msgctxt "model:ir.model.button,string:opportunity_cancel_button"
+msgid "Cancel"
+msgstr "Annuleer"
+
+msgctxt "model:ir.model.button,string:opportunity_convert_button"
+msgid "Convert to Sale"
+msgstr "Converteren naar verkoop"
+
+msgctxt "model:ir.model.button,string:opportunity_lead_button"
+msgid "Set as Lead"
+msgstr "instellen als geinteresseerd"
+
+msgctxt "model:ir.model.button,string:opportunity_lost_button"
+msgid "Mark as Lost"
+msgstr "Markeren als verloren"
+
+msgctxt "model:ir.model.button,string:opportunity_opportunity_button"
+msgid "Convert to Opportunity"
+msgstr "Omzeten naar opportuniteit"
+
+#, fuzzy
+msgctxt "model:ir.rule.group,name:rule_group_opportunity_companies"
+msgid "User in companies"
+msgstr "Gebruiker in het bedrijf"
+
+#, fuzzy
+msgctxt "model:ir.rule.group,name:rule_group_opportunity_employee_companies"
+msgid "User in companies"
+msgstr "Gebruiker in het bedrijf"
+
+#, fuzzy
+msgctxt ""
+"model:ir.rule.group,name:rule_group_opportunity_employee_monthly_companies"
+msgid "User in companies"
+msgstr "Gebruiker in het bedrijf"
+
+#, fuzzy
+msgctxt "model:ir.rule.group,name:rule_group_opportunity_monthly_companies"
+msgid "User in companies"
+msgstr "Gebruiker in het bedrijf"
+
+msgctxt "model:ir.sequence,name:sequence_sale_opportunity"
+msgid "Sale Opportunity"
+msgstr "verkoops opportuniteit"
+
+msgctxt "model:ir.sequence.type,name:sequence_type_sale_opportunity"
+msgid "Sale Opportunity"
+msgstr "verkoops opportuniteit"
+
+msgctxt "model:ir.ui.menu,name:menu_opportunity_employee_monthly_form"
+msgid "Opportunities per Employee per Month"
+msgstr "opportuniteit per werknemer per maand"
+
+msgctxt "model:ir.ui.menu,name:menu_opportunity_employee_open"
+msgid "Opportunities per Employee"
+msgstr "Oppportuniteiten per werkneemer"
+
+msgctxt "model:ir.ui.menu,name:menu_opportunity_form"
+msgid "Leads and Opportunities"
+msgstr "Geinteresseerden en opportuniteiten"
+
+msgctxt "model:ir.ui.menu,name:menu_opportunity_monthly_form"
+msgid "Opportunities per Month"
+msgstr "Opportuniteiten per maand"
+
+msgctxt "model:res.group,name:group_opportunity"
+msgid "Sale Opportunity"
+msgstr "verkoops opportuniteit"
+
+msgctxt "model:sale.opportunity,name:"
+msgid "Sale Opportunity"
+msgstr "Verkoops opportuniteit"
+
+msgctxt "model:sale.opportunity.line,name:"
+msgid "Sale Opportunity Line"
+msgstr "Verkoops opportuniteit"
+
+msgctxt "model:sale.opportunity_employee,name:"
+msgid "Sale Opportunity per Employee"
+msgstr "Verkoopksopportuniteit per werknemer"
+
+msgctxt "model:sale.opportunity_employee.context,name:"
+msgid "Sale Opportunity per Employee Context"
+msgstr "Verkoopksopportuniteit per werknemer context"
+
+msgctxt "model:sale.opportunity_employee_monthly,name:"
+msgid "Sale Opportunity per Employee per Month"
+msgstr "Verkoopopportuniteit per werknemer per maand"
+
+msgctxt "model:sale.opportunity_monthly,name:"
+msgid "Sale Opportunity per Month"
+msgstr "Verkoops opportuniteit per maand"
+
+msgctxt "selection:sale.opportunity,state:"
+msgid "Cancelled"
+msgstr "Geannuleerd"
+
+msgctxt "selection:sale.opportunity,state:"
+msgid "Converted"
+msgstr "geconverteerd"
+
+msgctxt "selection:sale.opportunity,state:"
+msgid "Lead"
+msgstr "Geinteresseerden"
+
+msgctxt "selection:sale.opportunity,state:"
+msgid "Lost"
+msgstr "Verloren"
+
+msgctxt "selection:sale.opportunity,state:"
+msgid "Opportunity"
+msgstr "Opportunitieiten"
+
+msgctxt "selection:sale.opportunity,state:"
+msgid "Won"
+msgstr "Gewonnen"
+
+msgctxt "view:sale.opportunity:"
+msgid "%"
+msgstr "%"
+
+msgctxt "view:sale.opportunity:"
+msgid "Lead/Opportunity"
+msgstr "geinteresseerden / opportuniteiten"
+
+msgctxt "view:sale.opportunity_employee:"
+msgid "%"
+msgstr "%"
+
+msgctxt "view:sale.opportunity_employee_monthly:"
+msgid "%"
+msgstr "%"
+
+msgctxt "view:sale.opportunity_monthly:"
+msgid "%"
+msgstr "%"
diff --git a/modules/sale_opportunity/locale/pl.po b/modules/sale_opportunity/locale/pl.po
new file mode 100644
index 0000000000..da3f4161b7
--- /dev/null
+++ b/modules/sale_opportunity/locale/pl.po
@@ -0,0 +1,566 @@
+#
+msgid ""
+msgstr "Content-Type: text/plain; charset=utf-8\n"
+
+msgctxt "field:sale.configuration,sale_opportunity_sequence:"
+msgid "Opportunity Sequence"
+msgstr ""
+
+msgctxt "field:sale.configuration.sequence,sale_opportunity_sequence:"
+msgid "Opportunity Sequence"
+msgstr ""
+
+msgctxt "field:sale.opportunity,address:"
+msgid "Address"
+msgstr "Adres"
+
+msgctxt "field:sale.opportunity,amount:"
+msgid "Amount"
+msgstr ""
+
+msgctxt "field:sale.opportunity,comment:"
+msgid "Comment"
+msgstr "Komentarz"
+
+msgctxt "field:sale.opportunity,company:"
+msgid "Company"
+msgstr "Firma"
+
+msgctxt "field:sale.opportunity,contact:"
+msgid "Contact"
+msgstr ""
+
+msgctxt "field:sale.opportunity,conversion_probability:"
+msgid "Conversion Probability"
+msgstr ""
+
+#, fuzzy
+msgctxt "field:sale.opportunity,converted_by:"
+msgid "Converted By"
+msgstr "Converted"
+
+msgctxt "field:sale.opportunity,currency:"
+msgid "Currency"
+msgstr "Waluta"
+
+msgctxt "field:sale.opportunity,currency_digits:"
+msgid "Currency Digits"
+msgstr "Cyfry waluty"
+
+msgctxt "field:sale.opportunity,description:"
+msgid "Description"
+msgstr "Opis"
+
+msgctxt "field:sale.opportunity,employee:"
+msgid "Employee"
+msgstr "Pracownik"
+
+msgctxt "field:sale.opportunity,end_date:"
+msgid "End Date"
+msgstr "Data ukończenia"
+
+msgctxt "field:sale.opportunity,lines:"
+msgid "Lines"
+msgstr "Wiersze"
+
+msgctxt "field:sale.opportunity,lost_reason:"
+msgid "Reason for loss"
+msgstr ""
+
+msgctxt "field:sale.opportunity,number:"
+msgid "Number"
+msgstr "Numer"
+
+msgctxt "field:sale.opportunity,party:"
+msgid "Party"
+msgstr "Strona"
+
+msgctxt "field:sale.opportunity,payment_term:"
+msgid "Payment Term"
+msgstr "Termin płatności"
+
+msgctxt "field:sale.opportunity,reference:"
+msgid "Reference"
+msgstr "Referencja"
+
+msgctxt "field:sale.opportunity,sales:"
+msgid "Sales"
+msgstr "Sprzedaż"
+
+msgctxt "field:sale.opportunity,start_date:"
+msgid "Start Date"
+msgstr "Data rozpoczęcia"
+
+msgctxt "field:sale.opportunity,state:"
+msgid "State"
+msgstr "Stan"
+
+#, fuzzy
+msgctxt "field:sale.opportunity.line,opportunity:"
+msgid "Opportunity"
+msgstr "Opportunities"
+
+msgctxt "field:sale.opportunity.line,opportunity_state:"
+msgid "Opportunity State"
+msgstr ""
+
+msgctxt "field:sale.opportunity.line,product:"
+msgid "Product"
+msgstr "Produkt"
+
+msgctxt "field:sale.opportunity.line,quantity:"
+msgid "Quantity"
+msgstr "Ilość"
+
+msgctxt "field:sale.opportunity.line,unit:"
+msgid "Unit"
+msgstr "Jednostka"
+
+msgctxt "field:sale.opportunity.line,unit_digits:"
+msgid "Unit Digits"
+msgstr "Cyfry jednostki"
+
+msgctxt "field:sale.opportunity_employee,amount:"
+msgid "Amount"
+msgstr ""
+
+msgctxt "field:sale.opportunity_employee,company:"
+msgid "Company"
+msgstr "Firma"
+
+msgctxt "field:sale.opportunity_employee,conversion_amount_rate:"
+msgid "Conversion Amount Rate"
+msgstr ""
+
+msgctxt "field:sale.opportunity_employee,conversion_rate:"
+msgid "Conversion Rate"
+msgstr ""
+
+#, fuzzy
+msgctxt "field:sale.opportunity_employee,converted:"
+msgid "Converted"
+msgstr "Converted"
+
+msgctxt "field:sale.opportunity_employee,converted_amount:"
+msgid "Converted Amount"
+msgstr ""
+
+msgctxt "field:sale.opportunity_employee,currency:"
+msgid "Currency"
+msgstr "Waluta"
+
+msgctxt "field:sale.opportunity_employee,currency_digits:"
+msgid "Currency Digits"
+msgstr "Cyfry waluty"
+
+msgctxt "field:sale.opportunity_employee,employee:"
+msgid "Employee"
+msgstr "Pracownik"
+
+#, fuzzy
+msgctxt "field:sale.opportunity_employee,lost:"
+msgid "Lost"
+msgstr "Lost"
+
+msgctxt "field:sale.opportunity_employee,number:"
+msgid "Number"
+msgstr "Numer"
+
+msgctxt "field:sale.opportunity_employee,winning_amount_rate:"
+msgid "Winning Amount Rate"
+msgstr ""
+
+msgctxt "field:sale.opportunity_employee,winning_rate:"
+msgid "Winning Rate"
+msgstr ""
+
+#, fuzzy
+msgctxt "field:sale.opportunity_employee,won:"
+msgid "Won"
+msgstr "Won"
+
+msgctxt "field:sale.opportunity_employee,won_amount:"
+msgid "Won Amount"
+msgstr ""
+
+msgctxt "field:sale.opportunity_employee.context,end_date:"
+msgid "End Date"
+msgstr "Data ukończenia"
+
+msgctxt "field:sale.opportunity_employee.context,start_date:"
+msgid "Start Date"
+msgstr "Data rozpoczęcia"
+
+msgctxt "field:sale.opportunity_employee_monthly,amount:"
+msgid "Amount"
+msgstr ""
+
+msgctxt "field:sale.opportunity_employee_monthly,company:"
+msgid "Company"
+msgstr "Firma"
+
+msgctxt "field:sale.opportunity_employee_monthly,conversion_amount_rate:"
+msgid "Conversion Amount Rate"
+msgstr ""
+
+msgctxt "field:sale.opportunity_employee_monthly,conversion_rate:"
+msgid "Conversion Rate"
+msgstr ""
+
+#, fuzzy
+msgctxt "field:sale.opportunity_employee_monthly,converted:"
+msgid "Converted"
+msgstr "Converted"
+
+msgctxt "field:sale.opportunity_employee_monthly,converted_amount:"
+msgid "Converted Amount"
+msgstr ""
+
+msgctxt "field:sale.opportunity_employee_monthly,currency:"
+msgid "Currency"
+msgstr "Waluta"
+
+msgctxt "field:sale.opportunity_employee_monthly,currency_digits:"
+msgid "Currency Digits"
+msgstr "Cyfry waluty"
+
+msgctxt "field:sale.opportunity_employee_monthly,employee:"
+msgid "Employee"
+msgstr "Pracownik"
+
+#, fuzzy
+msgctxt "field:sale.opportunity_employee_monthly,lost:"
+msgid "Lost"
+msgstr "Lost"
+
+msgctxt "field:sale.opportunity_employee_monthly,month:"
+msgid "Month"
+msgstr "Miesiąc"
+
+msgctxt "field:sale.opportunity_employee_monthly,number:"
+msgid "Number"
+msgstr "Numer"
+
+msgctxt "field:sale.opportunity_employee_monthly,winning_amount_rate:"
+msgid "Winning Amount Rate"
+msgstr ""
+
+msgctxt "field:sale.opportunity_employee_monthly,winning_rate:"
+msgid "Winning Rate"
+msgstr ""
+
+#, fuzzy
+msgctxt "field:sale.opportunity_employee_monthly,won:"
+msgid "Won"
+msgstr "Won"
+
+msgctxt "field:sale.opportunity_employee_monthly,won_amount:"
+msgid "Won Amount"
+msgstr ""
+
+msgctxt "field:sale.opportunity_employee_monthly,year:"
+msgid "Year"
+msgstr "Rok"
+
+msgctxt "field:sale.opportunity_monthly,amount:"
+msgid "Amount"
+msgstr ""
+
+msgctxt "field:sale.opportunity_monthly,company:"
+msgid "Company"
+msgstr "Firma"
+
+msgctxt "field:sale.opportunity_monthly,conversion_amount_rate:"
+msgid "Conversion Amount Rate"
+msgstr ""
+
+msgctxt "field:sale.opportunity_monthly,conversion_rate:"
+msgid "Conversion Rate"
+msgstr ""
+
+#, fuzzy
+msgctxt "field:sale.opportunity_monthly,converted:"
+msgid "Converted"
+msgstr "Converted"
+
+msgctxt "field:sale.opportunity_monthly,converted_amount:"
+msgid "Converted Amount"
+msgstr ""
+
+msgctxt "field:sale.opportunity_monthly,currency:"
+msgid "Currency"
+msgstr "Waluta"
+
+msgctxt "field:sale.opportunity_monthly,currency_digits:"
+msgid "Currency Digits"
+msgstr "Cyfry waluty"
+
+#, fuzzy
+msgctxt "field:sale.opportunity_monthly,lost:"
+msgid "Lost"
+msgstr "Lost"
+
+msgctxt "field:sale.opportunity_monthly,month:"
+msgid "Month"
+msgstr "Miesiąc"
+
+msgctxt "field:sale.opportunity_monthly,number:"
+msgid "Number"
+msgstr "Numer"
+
+msgctxt "field:sale.opportunity_monthly,winning_amount_rate:"
+msgid "Winning Amount Rate"
+msgstr ""
+
+msgctxt "field:sale.opportunity_monthly,winning_rate:"
+msgid "Winning Rate"
+msgstr ""
+
+#, fuzzy
+msgctxt "field:sale.opportunity_monthly,won:"
+msgid "Won"
+msgstr "Won"
+
+msgctxt "field:sale.opportunity_monthly,won_amount:"
+msgid "Won Amount"
+msgstr ""
+
+msgctxt "field:sale.opportunity_monthly,year:"
+msgid "Year"
+msgstr "Rok"
+
+msgctxt "field:sale.opportunity_monthly,year_month:"
+msgid "Year-Month"
+msgstr "Rok-Miesiąc"
+
+msgctxt "help:sale.opportunity,amount:"
+msgid "Estimated revenue amount."
+msgstr ""
+
+msgctxt "help:sale.opportunity,conversion_probability:"
+msgid "Percentage between 0 and 100."
+msgstr ""
+
+#, fuzzy
+msgctxt "model:ir.action,name:act_open_sale_form"
+msgid "Sales"
+msgstr "Sales"
+
+msgctxt "model:ir.action,name:act_opportunity_employee_form"
+msgid "Opportunities per Employee"
+msgstr "Opportunities per Employee"
+
+#, fuzzy
+msgctxt "model:ir.action,name:act_opportunity_employee_monthly_form"
+msgid "Opportunities per Employee per Month"
+msgstr "Opportunities per Employee per Month"
+
+msgctxt "model:ir.action,name:act_opportunity_form"
+msgid "Leads and Opportunities"
+msgstr "Leads and Opportunities"
+
+msgctxt "model:ir.action,name:act_opportunity_form2"
+msgid "Sales Leads/Opportunities"
+msgstr "Sales Leads/Opportunities"
+
+msgctxt "model:ir.action,name:act_opportunity_monthly_form"
+msgid "Opportunities per Month"
+msgstr "Opportunities per Month"
+
+#, fuzzy
+msgctxt ""
+"model:ir.action.act_window.domain,name:act_opportunity_form_domain_all"
+msgid "All"
+msgstr "All"
+
+#, fuzzy
+msgctxt ""
+"model:ir.action.act_window.domain,name:act_opportunity_form_domain_cancelled"
+msgid "Cancelled"
+msgstr "Cancelled"
+
+#, fuzzy
+msgctxt ""
+"model:ir.action.act_window.domain,name:act_opportunity_form_domain_converted"
+msgid "Converted"
+msgstr "Converted"
+
+#, fuzzy
+msgctxt ""
+"model:ir.action.act_window.domain,name:act_opportunity_form_domain_leads"
+msgid "Leads"
+msgstr "Leads"
+
+#, fuzzy
+msgctxt ""
+"model:ir.action.act_window.domain,name:act_opportunity_form_domain_lost"
+msgid "Lost"
+msgstr "Lost"
+
+#, fuzzy
+msgctxt ""
+"model:ir.action.act_window.domain,name:act_opportunity_form_domain_opportunities"
+msgid "Opportunities"
+msgstr "Opportunities"
+
+#, fuzzy
+msgctxt ""
+"model:ir.action.act_window.domain,name:act_opportunity_form_domain_won"
+msgid "Won"
+msgstr "Won"
+
+msgctxt "model:ir.message,text:msg_modify_origin_opportunity"
+msgid "You cannot modify the opportunity origin of the sale \"%(sale)s\"."
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_opportunity_delete_cancel"
+msgid "To delete opportunity \"%(opportunity)s\", you must cancel it."
+msgstr ""
+
+msgctxt "model:ir.model.button,string:opportunity_cancel_button"
+msgid "Cancel"
+msgstr "Cancel"
+
+msgctxt "model:ir.model.button,string:opportunity_convert_button"
+msgid "Convert to Sale"
+msgstr "Convert to Sale"
+
+msgctxt "model:ir.model.button,string:opportunity_lead_button"
+msgid "Set as Lead"
+msgstr "Set as Lead"
+
+msgctxt "model:ir.model.button,string:opportunity_lost_button"
+msgid "Mark as Lost"
+msgstr "Mark as Lost"
+
+msgctxt "model:ir.model.button,string:opportunity_opportunity_button"
+msgid "Convert to Opportunity"
+msgstr "Convert to Opportunity"
+
+msgctxt "model:ir.rule.group,name:rule_group_opportunity_companies"
+msgid "User in companies"
+msgstr ""
+
+msgctxt "model:ir.rule.group,name:rule_group_opportunity_employee_companies"
+msgid "User in companies"
+msgstr ""
+
+msgctxt ""
+"model:ir.rule.group,name:rule_group_opportunity_employee_monthly_companies"
+msgid "User in companies"
+msgstr ""
+
+msgctxt "model:ir.rule.group,name:rule_group_opportunity_monthly_companies"
+msgid "User in companies"
+msgstr ""
+
+#, fuzzy
+msgctxt "model:ir.sequence,name:sequence_sale_opportunity"
+msgid "Sale Opportunity"
+msgstr "Sale Opportunity"
+
+#, fuzzy
+msgctxt "model:ir.sequence.type,name:sequence_type_sale_opportunity"
+msgid "Sale Opportunity"
+msgstr "Sale Opportunity"
+
+#, fuzzy
+msgctxt "model:ir.ui.menu,name:menu_opportunity_employee_monthly_form"
+msgid "Opportunities per Employee per Month"
+msgstr "Opportunities per Employee per Month"
+
+msgctxt "model:ir.ui.menu,name:menu_opportunity_employee_open"
+msgid "Opportunities per Employee"
+msgstr "Opportunities per Employee"
+
+msgctxt "model:ir.ui.menu,name:menu_opportunity_form"
+msgid "Leads and Opportunities"
+msgstr "Leads and Opportunities"
+
+msgctxt "model:ir.ui.menu,name:menu_opportunity_monthly_form"
+msgid "Opportunities per Month"
+msgstr "Opportunities per Month"
+
+#, fuzzy
+msgctxt "model:res.group,name:group_opportunity"
+msgid "Sale Opportunity"
+msgstr "Sale Opportunity"
+
+#, fuzzy
+msgctxt "model:sale.opportunity,name:"
+msgid "Sale Opportunity"
+msgstr "Sale Opportunity"
+
+#, fuzzy
+msgctxt "model:sale.opportunity.line,name:"
+msgid "Sale Opportunity Line"
+msgstr "Sale Opportunity"
+
+#, fuzzy
+msgctxt "model:sale.opportunity_employee,name:"
+msgid "Sale Opportunity per Employee"
+msgstr "Opportunities per Employee per Month"
+
+#, fuzzy
+msgctxt "model:sale.opportunity_employee.context,name:"
+msgid "Sale Opportunity per Employee Context"
+msgstr "Opportunities per Employee per Month"
+
+#, fuzzy
+msgctxt "model:sale.opportunity_employee_monthly,name:"
+msgid "Sale Opportunity per Employee per Month"
+msgstr "Opportunities per Employee per Month"
+
+#, fuzzy
+msgctxt "model:sale.opportunity_monthly,name:"
+msgid "Sale Opportunity per Month"
+msgstr "Opportunities per Employee per Month"
+
+msgctxt "selection:sale.opportunity,state:"
+msgid "Cancelled"
+msgstr "Anulowano"
+
+#, fuzzy
+msgctxt "selection:sale.opportunity,state:"
+msgid "Converted"
+msgstr "Converted"
+
+#, fuzzy
+msgctxt "selection:sale.opportunity,state:"
+msgid "Lead"
+msgstr "Leads"
+
+#, fuzzy
+msgctxt "selection:sale.opportunity,state:"
+msgid "Lost"
+msgstr "Lost"
+
+#, fuzzy
+msgctxt "selection:sale.opportunity,state:"
+msgid "Opportunity"
+msgstr "Opportunities"
+
+#, fuzzy
+msgctxt "selection:sale.opportunity,state:"
+msgid "Won"
+msgstr "Won"
+
+msgctxt "view:sale.opportunity:"
+msgid "%"
+msgstr "%"
+
+msgctxt "view:sale.opportunity:"
+msgid "Lead/Opportunity"
+msgstr ""
+
+msgctxt "view:sale.opportunity_employee:"
+msgid "%"
+msgstr "%"
+
+msgctxt "view:sale.opportunity_employee_monthly:"
+msgid "%"
+msgstr "%"
+
+msgctxt "view:sale.opportunity_monthly:"
+msgid "%"
+msgstr "%"
diff --git a/modules/sale_opportunity/locale/pt.po b/modules/sale_opportunity/locale/pt.po
new file mode 100644
index 0000000000..4cc709a2cf
--- /dev/null
+++ b/modules/sale_opportunity/locale/pt.po
@@ -0,0 +1,553 @@
+#
+msgid ""
+msgstr "Content-Type: text/plain; charset=utf-8\n"
+
+msgctxt "field:sale.configuration,sale_opportunity_sequence:"
+msgid "Opportunity Sequence"
+msgstr "Sequência de Oportunidade"
+
+msgctxt "field:sale.configuration.sequence,sale_opportunity_sequence:"
+msgid "Opportunity Sequence"
+msgstr "Sequência de Oportunidade"
+
+msgctxt "field:sale.opportunity,address:"
+msgid "Address"
+msgstr "Endereço"
+
+msgctxt "field:sale.opportunity,amount:"
+msgid "Amount"
+msgstr "Quantidade"
+
+msgctxt "field:sale.opportunity,comment:"
+msgid "Comment"
+msgstr "Comentário"
+
+msgctxt "field:sale.opportunity,company:"
+msgid "Company"
+msgstr "Empresa"
+
+msgctxt "field:sale.opportunity,contact:"
+msgid "Contact"
+msgstr ""
+
+msgctxt "field:sale.opportunity,conversion_probability:"
+msgid "Conversion Probability"
+msgstr "Probabilidade de Conversão"
+
+#, fuzzy
+msgctxt "field:sale.opportunity,converted_by:"
+msgid "Converted By"
+msgstr "Convertido"
+
+msgctxt "field:sale.opportunity,currency:"
+msgid "Currency"
+msgstr "Moeda"
+
+msgctxt "field:sale.opportunity,currency_digits:"
+msgid "Currency Digits"
+msgstr "Dígitos da moeda"
+
+msgctxt "field:sale.opportunity,description:"
+msgid "Description"
+msgstr "Descrição"
+
+msgctxt "field:sale.opportunity,employee:"
+msgid "Employee"
+msgstr "Empregado"
+
+msgctxt "field:sale.opportunity,end_date:"
+msgid "End Date"
+msgstr "Data de extremidade"
+
+msgctxt "field:sale.opportunity,lines:"
+msgid "Lines"
+msgstr "Linhas"
+
+msgctxt "field:sale.opportunity,lost_reason:"
+msgid "Reason for loss"
+msgstr "Razão da perda"
+
+msgctxt "field:sale.opportunity,number:"
+msgid "Number"
+msgstr "Número"
+
+msgctxt "field:sale.opportunity,party:"
+msgid "Party"
+msgstr "Parceiro"
+
+msgctxt "field:sale.opportunity,payment_term:"
+msgid "Payment Term"
+msgstr "Prazo de Pagamento"
+
+msgctxt "field:sale.opportunity,reference:"
+msgid "Reference"
+msgstr "Referência"
+
+msgctxt "field:sale.opportunity,sales:"
+msgid "Sales"
+msgstr "Vendas"
+
+msgctxt "field:sale.opportunity,start_date:"
+msgid "Start Date"
+msgstr "Data de início"
+
+msgctxt "field:sale.opportunity,state:"
+msgid "State"
+msgstr "Estado"
+
+msgctxt "field:sale.opportunity.line,opportunity:"
+msgid "Opportunity"
+msgstr "Oportunidade"
+
+msgctxt "field:sale.opportunity.line,opportunity_state:"
+msgid "Opportunity State"
+msgstr "Estado da Oportunidade"
+
+msgctxt "field:sale.opportunity.line,product:"
+msgid "Product"
+msgstr "Produto"
+
+msgctxt "field:sale.opportunity.line,quantity:"
+msgid "Quantity"
+msgstr "Quantidade"
+
+msgctxt "field:sale.opportunity.line,unit:"
+msgid "Unit"
+msgstr "Unidade"
+
+msgctxt "field:sale.opportunity.line,unit_digits:"
+msgid "Unit Digits"
+msgstr "Dígitos da unidade"
+
+msgctxt "field:sale.opportunity_employee,amount:"
+msgid "Amount"
+msgstr "Quantidade"
+
+msgctxt "field:sale.opportunity_employee,company:"
+msgid "Company"
+msgstr "Empresa"
+
+msgctxt "field:sale.opportunity_employee,conversion_amount_rate:"
+msgid "Conversion Amount Rate"
+msgstr "Taxa de Conversão (sobre o montante)"
+
+msgctxt "field:sale.opportunity_employee,conversion_rate:"
+msgid "Conversion Rate"
+msgstr "Taxa de Conversão"
+
+msgctxt "field:sale.opportunity_employee,converted:"
+msgid "Converted"
+msgstr "Convertido"
+
+msgctxt "field:sale.opportunity_employee,converted_amount:"
+msgid "Converted Amount"
+msgstr "Montante Convertido"
+
+msgctxt "field:sale.opportunity_employee,currency:"
+msgid "Currency"
+msgstr "Moeda"
+
+msgctxt "field:sale.opportunity_employee,currency_digits:"
+msgid "Currency Digits"
+msgstr "Dígitos da moeda"
+
+msgctxt "field:sale.opportunity_employee,employee:"
+msgid "Employee"
+msgstr "Empregado"
+
+msgctxt "field:sale.opportunity_employee,lost:"
+msgid "Lost"
+msgstr "Perdida"
+
+msgctxt "field:sale.opportunity_employee,number:"
+msgid "Number"
+msgstr "Numero"
+
+msgctxt "field:sale.opportunity_employee,winning_amount_rate:"
+msgid "Winning Amount Rate"
+msgstr "Porcentagem de Ganhos (sobre o montante)"
+
+msgctxt "field:sale.opportunity_employee,winning_rate:"
+msgid "Winning Rate"
+msgstr "Taxa de Ganho"
+
+msgctxt "field:sale.opportunity_employee,won:"
+msgid "Won"
+msgstr "Ganhou"
+
+msgctxt "field:sale.opportunity_employee,won_amount:"
+msgid "Won Amount"
+msgstr "Montante Ganho"
+
+msgctxt "field:sale.opportunity_employee.context,end_date:"
+msgid "End Date"
+msgstr "Data de Término"
+
+msgctxt "field:sale.opportunity_employee.context,start_date:"
+msgid "Start Date"
+msgstr "Data de Início"
+
+msgctxt "field:sale.opportunity_employee_monthly,amount:"
+msgid "Amount"
+msgstr "Quantidade"
+
+msgctxt "field:sale.opportunity_employee_monthly,company:"
+msgid "Company"
+msgstr "Empresa"
+
+msgctxt "field:sale.opportunity_employee_monthly,conversion_amount_rate:"
+msgid "Conversion Amount Rate"
+msgstr "Taxa de Conversão (sobre o montate)"
+
+msgctxt "field:sale.opportunity_employee_monthly,conversion_rate:"
+msgid "Conversion Rate"
+msgstr "Taxa de Conversão"
+
+msgctxt "field:sale.opportunity_employee_monthly,converted:"
+msgid "Converted"
+msgstr "Convertidas"
+
+msgctxt "field:sale.opportunity_employee_monthly,converted_amount:"
+msgid "Converted Amount"
+msgstr "Montante Convertido"
+
+msgctxt "field:sale.opportunity_employee_monthly,currency:"
+msgid "Currency"
+msgstr "Moeda"
+
+msgctxt "field:sale.opportunity_employee_monthly,currency_digits:"
+msgid "Currency Digits"
+msgstr "Dígitos da moeda"
+
+msgctxt "field:sale.opportunity_employee_monthly,employee:"
+msgid "Employee"
+msgstr "Empregado"
+
+msgctxt "field:sale.opportunity_employee_monthly,lost:"
+msgid "Lost"
+msgstr "Perdida"
+
+msgctxt "field:sale.opportunity_employee_monthly,month:"
+msgid "Month"
+msgstr "Mês"
+
+msgctxt "field:sale.opportunity_employee_monthly,number:"
+msgid "Number"
+msgstr "Numero"
+
+msgctxt "field:sale.opportunity_employee_monthly,winning_amount_rate:"
+msgid "Winning Amount Rate"
+msgstr "Porcentagem de Ganhos (sobre o montante)"
+
+msgctxt "field:sale.opportunity_employee_monthly,winning_rate:"
+msgid "Winning Rate"
+msgstr "Taxa de Ganho"
+
+msgctxt "field:sale.opportunity_employee_monthly,won:"
+msgid "Won"
+msgstr "Ganhou"
+
+msgctxt "field:sale.opportunity_employee_monthly,won_amount:"
+msgid "Won Amount"
+msgstr "Montante Ganho"
+
+msgctxt "field:sale.opportunity_employee_monthly,year:"
+msgid "Year"
+msgstr "Ano"
+
+msgctxt "field:sale.opportunity_monthly,amount:"
+msgid "Amount"
+msgstr "Quantidade"
+
+msgctxt "field:sale.opportunity_monthly,company:"
+msgid "Company"
+msgstr "Empresa"
+
+msgctxt "field:sale.opportunity_monthly,conversion_amount_rate:"
+msgid "Conversion Amount Rate"
+msgstr "Taxa de Conversão (sobre o montante)"
+
+msgctxt "field:sale.opportunity_monthly,conversion_rate:"
+msgid "Conversion Rate"
+msgstr "Taxa de Conversão"
+
+msgctxt "field:sale.opportunity_monthly,converted:"
+msgid "Converted"
+msgstr "Convertidas"
+
+msgctxt "field:sale.opportunity_monthly,converted_amount:"
+msgid "Converted Amount"
+msgstr "Montante Convertido"
+
+msgctxt "field:sale.opportunity_monthly,currency:"
+msgid "Currency"
+msgstr "Moeda"
+
+msgctxt "field:sale.opportunity_monthly,currency_digits:"
+msgid "Currency Digits"
+msgstr "Dígitos da moeda"
+
+msgctxt "field:sale.opportunity_monthly,lost:"
+msgid "Lost"
+msgstr "Perdida"
+
+msgctxt "field:sale.opportunity_monthly,month:"
+msgid "Month"
+msgstr "Mês"
+
+msgctxt "field:sale.opportunity_monthly,number:"
+msgid "Number"
+msgstr "Numero"
+
+msgctxt "field:sale.opportunity_monthly,winning_amount_rate:"
+msgid "Winning Amount Rate"
+msgstr "Taxa de Ganho (sobre o montante)"
+
+msgctxt "field:sale.opportunity_monthly,winning_rate:"
+msgid "Winning Rate"
+msgstr "Taxa de Ganho"
+
+msgctxt "field:sale.opportunity_monthly,won:"
+msgid "Won"
+msgstr "Ganhou"
+
+msgctxt "field:sale.opportunity_monthly,won_amount:"
+msgid "Won Amount"
+msgstr "Montante Ganho"
+
+msgctxt "field:sale.opportunity_monthly,year:"
+msgid "Year"
+msgstr "Ano"
+
+msgctxt "field:sale.opportunity_monthly,year_month:"
+msgid "Year-Month"
+msgstr "Ano-Mês"
+
+#, fuzzy
+msgctxt "help:sale.opportunity,amount:"
+msgid "Estimated revenue amount."
+msgstr "Monante estimado de receitas"
+
+#, fuzzy
+msgctxt "help:sale.opportunity,conversion_probability:"
+msgid "Percentage between 0 and 100."
+msgstr "Porcentagem entre 0 e 100"
+
+#, fuzzy
+msgctxt "model:ir.action,name:act_open_sale_form"
+msgid "Sales"
+msgstr "Sales"
+
+#, fuzzy
+msgctxt "model:ir.action,name:act_opportunity_employee_form"
+msgid "Opportunities per Employee"
+msgstr "Opportunities per Employee"
+
+#, fuzzy
+msgctxt "model:ir.action,name:act_opportunity_employee_monthly_form"
+msgid "Opportunities per Employee per Month"
+msgstr "Opportunities per Employee per Month"
+
+#, fuzzy
+msgctxt "model:ir.action,name:act_opportunity_form"
+msgid "Leads and Opportunities"
+msgstr "Leads and Opportunities"
+
+#, fuzzy
+msgctxt "model:ir.action,name:act_opportunity_form2"
+msgid "Sales Leads/Opportunities"
+msgstr "Sales Leads/Opportunities"
+
+#, fuzzy
+msgctxt "model:ir.action,name:act_opportunity_monthly_form"
+msgid "Opportunities per Month"
+msgstr "Opportunities per Month"
+
+#, fuzzy
+msgctxt ""
+"model:ir.action.act_window.domain,name:act_opportunity_form_domain_all"
+msgid "All"
+msgstr "All"
+
+#, fuzzy
+msgctxt ""
+"model:ir.action.act_window.domain,name:act_opportunity_form_domain_cancelled"
+msgid "Cancelled"
+msgstr "Cancelled"
+
+#, fuzzy
+msgctxt ""
+"model:ir.action.act_window.domain,name:act_opportunity_form_domain_converted"
+msgid "Converted"
+msgstr "Converted"
+
+msgctxt ""
+"model:ir.action.act_window.domain,name:act_opportunity_form_domain_leads"
+msgid "Leads"
+msgstr "Leads"
+
+#, fuzzy
+msgctxt ""
+"model:ir.action.act_window.domain,name:act_opportunity_form_domain_lost"
+msgid "Lost"
+msgstr "Lost"
+
+#, fuzzy
+msgctxt ""
+"model:ir.action.act_window.domain,name:act_opportunity_form_domain_opportunities"
+msgid "Opportunities"
+msgstr "Opportunities"
+
+#, fuzzy
+msgctxt ""
+"model:ir.action.act_window.domain,name:act_opportunity_form_domain_won"
+msgid "Won"
+msgstr "Won"
+
+msgctxt "model:ir.message,text:msg_modify_origin_opportunity"
+msgid "You cannot modify the opportunity origin of the sale \"%(sale)s\"."
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_opportunity_delete_cancel"
+msgid "To delete opportunity \"%(opportunity)s\", you must cancel it."
+msgstr ""
+
+msgctxt "model:ir.model.button,string:opportunity_cancel_button"
+msgid "Cancel"
+msgstr "Cancel"
+
+msgctxt "model:ir.model.button,string:opportunity_convert_button"
+msgid "Convert to Sale"
+msgstr "Convert to Sale"
+
+msgctxt "model:ir.model.button,string:opportunity_lead_button"
+msgid "Set as Lead"
+msgstr "Set as Lead"
+
+msgctxt "model:ir.model.button,string:opportunity_lost_button"
+msgid "Mark as Lost"
+msgstr "Mark as Lost"
+
+msgctxt "model:ir.model.button,string:opportunity_opportunity_button"
+msgid "Convert to Opportunity"
+msgstr "Convert to Opportunity"
+
+msgctxt "model:ir.rule.group,name:rule_group_opportunity_companies"
+msgid "User in companies"
+msgstr ""
+
+msgctxt "model:ir.rule.group,name:rule_group_opportunity_employee_companies"
+msgid "User in companies"
+msgstr ""
+
+msgctxt ""
+"model:ir.rule.group,name:rule_group_opportunity_employee_monthly_companies"
+msgid "User in companies"
+msgstr ""
+
+msgctxt "model:ir.rule.group,name:rule_group_opportunity_monthly_companies"
+msgid "User in companies"
+msgstr ""
+
+#, fuzzy
+msgctxt "model:ir.sequence,name:sequence_sale_opportunity"
+msgid "Sale Opportunity"
+msgstr "Sale Opportunity"
+
+#, fuzzy
+msgctxt "model:ir.sequence.type,name:sequence_type_sale_opportunity"
+msgid "Sale Opportunity"
+msgstr "Sale Opportunity"
+
+#, fuzzy
+msgctxt "model:ir.ui.menu,name:menu_opportunity_employee_monthly_form"
+msgid "Opportunities per Employee per Month"
+msgstr "Opportunities per Employee per Month"
+
+#, fuzzy
+msgctxt "model:ir.ui.menu,name:menu_opportunity_employee_open"
+msgid "Opportunities per Employee"
+msgstr "Opportunities per Employee"
+
+#, fuzzy
+msgctxt "model:ir.ui.menu,name:menu_opportunity_form"
+msgid "Leads and Opportunities"
+msgstr "Leads and Opportunities"
+
+#, fuzzy
+msgctxt "model:ir.ui.menu,name:menu_opportunity_monthly_form"
+msgid "Opportunities per Month"
+msgstr "Opportunities per Month"
+
+#, fuzzy
+msgctxt "model:res.group,name:group_opportunity"
+msgid "Sale Opportunity"
+msgstr "Sale Opportunity"
+
+msgctxt "model:sale.opportunity,name:"
+msgid "Sale Opportunity"
+msgstr "Oportunidade de Venda"
+
+msgctxt "model:sale.opportunity.line,name:"
+msgid "Sale Opportunity Line"
+msgstr "Linha da Oportunidade de Venda"
+
+msgctxt "model:sale.opportunity_employee,name:"
+msgid "Sale Opportunity per Employee"
+msgstr "Oportunidade de Venda por Empregado"
+
+msgctxt "model:sale.opportunity_employee.context,name:"
+msgid "Sale Opportunity per Employee Context"
+msgstr "Contexto da Oportunidade de Venda por Empregado"
+
+msgctxt "model:sale.opportunity_employee_monthly,name:"
+msgid "Sale Opportunity per Employee per Month"
+msgstr "Oportunidade de Venda por Empregado por Mês"
+
+msgctxt "model:sale.opportunity_monthly,name:"
+msgid "Sale Opportunity per Month"
+msgstr "Oportunidade de Venda por Mês"
+
+msgctxt "selection:sale.opportunity,state:"
+msgid "Cancelled"
+msgstr "Cancelado"
+
+msgctxt "selection:sale.opportunity,state:"
+msgid "Converted"
+msgstr "Convertida"
+
+msgctxt "selection:sale.opportunity,state:"
+msgid "Lead"
+msgstr "Chumbo"
+
+msgctxt "selection:sale.opportunity,state:"
+msgid "Lost"
+msgstr "Perdida"
+
+msgctxt "selection:sale.opportunity,state:"
+msgid "Opportunity"
+msgstr "Oportunidade"
+
+msgctxt "selection:sale.opportunity,state:"
+msgid "Won"
+msgstr "Ganhou"
+
+msgctxt "view:sale.opportunity:"
+msgid "%"
+msgstr "%"
+
+msgctxt "view:sale.opportunity:"
+msgid "Lead/Opportunity"
+msgstr "Lead/Oportunidade"
+
+msgctxt "view:sale.opportunity_employee:"
+msgid "%"
+msgstr "%"
+
+msgctxt "view:sale.opportunity_employee_monthly:"
+msgid "%"
+msgstr "%"
+
+msgctxt "view:sale.opportunity_monthly:"
+msgid "%"
+msgstr "%"
diff --git a/modules/sale_opportunity/locale/ro.po b/modules/sale_opportunity/locale/ro.po
new file mode 100644
index 0000000000..6c54588cd2
--- /dev/null
+++ b/modules/sale_opportunity/locale/ro.po
@@ -0,0 +1,531 @@
+#
+msgid ""
+msgstr "Content-Type: text/plain; charset=utf-8\n"
+
+msgctxt "field:sale.configuration,sale_opportunity_sequence:"
+msgid "Opportunity Sequence"
+msgstr ""
+
+msgctxt "field:sale.configuration.sequence,sale_opportunity_sequence:"
+msgid "Opportunity Sequence"
+msgstr ""
+
+msgctxt "field:sale.opportunity,address:"
+msgid "Address"
+msgstr "Adresa"
+
+msgctxt "field:sale.opportunity,amount:"
+msgid "Amount"
+msgstr "Suma"
+
+msgctxt "field:sale.opportunity,comment:"
+msgid "Comment"
+msgstr "Cometariu"
+
+msgctxt "field:sale.opportunity,company:"
+msgid "Company"
+msgstr "Companie"
+
+msgctxt "field:sale.opportunity,contact:"
+msgid "Contact"
+msgstr ""
+
+msgctxt "field:sale.opportunity,conversion_probability:"
+msgid "Conversion Probability"
+msgstr ""
+
+msgctxt "field:sale.opportunity,converted_by:"
+msgid "Converted By"
+msgstr ""
+
+msgctxt "field:sale.opportunity,currency:"
+msgid "Currency"
+msgstr "Moneda"
+
+msgctxt "field:sale.opportunity,currency_digits:"
+msgid "Currency Digits"
+msgstr "Zecimale valută"
+
+msgctxt "field:sale.opportunity,description:"
+msgid "Description"
+msgstr "Descriere"
+
+msgctxt "field:sale.opportunity,employee:"
+msgid "Employee"
+msgstr ""
+
+msgctxt "field:sale.opportunity,end_date:"
+msgid "End Date"
+msgstr ""
+
+msgctxt "field:sale.opportunity,lines:"
+msgid "Lines"
+msgstr "Rânduri"
+
+msgctxt "field:sale.opportunity,lost_reason:"
+msgid "Reason for loss"
+msgstr ""
+
+msgctxt "field:sale.opportunity,number:"
+msgid "Number"
+msgstr ""
+
+msgctxt "field:sale.opportunity,party:"
+msgid "Party"
+msgstr "Parte"
+
+msgctxt "field:sale.opportunity,payment_term:"
+msgid "Payment Term"
+msgstr "Termen de plata"
+
+msgctxt "field:sale.opportunity,reference:"
+msgid "Reference"
+msgstr "Referinţă"
+
+msgctxt "field:sale.opportunity,sales:"
+msgid "Sales"
+msgstr "Vânzări"
+
+msgctxt "field:sale.opportunity,start_date:"
+msgid "Start Date"
+msgstr ""
+
+msgctxt "field:sale.opportunity,state:"
+msgid "State"
+msgstr ""
+
+msgctxt "field:sale.opportunity.line,opportunity:"
+msgid "Opportunity"
+msgstr ""
+
+msgctxt "field:sale.opportunity.line,opportunity_state:"
+msgid "Opportunity State"
+msgstr ""
+
+msgctxt "field:sale.opportunity.line,product:"
+msgid "Product"
+msgstr "Produs"
+
+msgctxt "field:sale.opportunity.line,quantity:"
+msgid "Quantity"
+msgstr ""
+
+msgctxt "field:sale.opportunity.line,unit:"
+msgid "Unit"
+msgstr ""
+
+msgctxt "field:sale.opportunity.line,unit_digits:"
+msgid "Unit Digits"
+msgstr ""
+
+msgctxt "field:sale.opportunity_employee,amount:"
+msgid "Amount"
+msgstr "Suma"
+
+msgctxt "field:sale.opportunity_employee,company:"
+msgid "Company"
+msgstr "Companie"
+
+msgctxt "field:sale.opportunity_employee,conversion_amount_rate:"
+msgid "Conversion Amount Rate"
+msgstr ""
+
+msgctxt "field:sale.opportunity_employee,conversion_rate:"
+msgid "Conversion Rate"
+msgstr ""
+
+msgctxt "field:sale.opportunity_employee,converted:"
+msgid "Converted"
+msgstr ""
+
+msgctxt "field:sale.opportunity_employee,converted_amount:"
+msgid "Converted Amount"
+msgstr ""
+
+msgctxt "field:sale.opportunity_employee,currency:"
+msgid "Currency"
+msgstr "Moneda"
+
+msgctxt "field:sale.opportunity_employee,currency_digits:"
+msgid "Currency Digits"
+msgstr "Zecimale valută"
+
+msgctxt "field:sale.opportunity_employee,employee:"
+msgid "Employee"
+msgstr "Angajat"
+
+msgctxt "field:sale.opportunity_employee,lost:"
+msgid "Lost"
+msgstr "Pierdut"
+
+msgctxt "field:sale.opportunity_employee,number:"
+msgid "Number"
+msgstr "Număr"
+
+msgctxt "field:sale.opportunity_employee,winning_amount_rate:"
+msgid "Winning Amount Rate"
+msgstr ""
+
+msgctxt "field:sale.opportunity_employee,winning_rate:"
+msgid "Winning Rate"
+msgstr ""
+
+msgctxt "field:sale.opportunity_employee,won:"
+msgid "Won"
+msgstr ""
+
+msgctxt "field:sale.opportunity_employee,won_amount:"
+msgid "Won Amount"
+msgstr ""
+
+msgctxt "field:sale.opportunity_employee.context,end_date:"
+msgid "End Date"
+msgstr ""
+
+msgctxt "field:sale.opportunity_employee.context,start_date:"
+msgid "Start Date"
+msgstr ""
+
+msgctxt "field:sale.opportunity_employee_monthly,amount:"
+msgid "Amount"
+msgstr "Suma"
+
+msgctxt "field:sale.opportunity_employee_monthly,company:"
+msgid "Company"
+msgstr "Companie"
+
+msgctxt "field:sale.opportunity_employee_monthly,conversion_amount_rate:"
+msgid "Conversion Amount Rate"
+msgstr ""
+
+msgctxt "field:sale.opportunity_employee_monthly,conversion_rate:"
+msgid "Conversion Rate"
+msgstr ""
+
+msgctxt "field:sale.opportunity_employee_monthly,converted:"
+msgid "Converted"
+msgstr ""
+
+msgctxt "field:sale.opportunity_employee_monthly,converted_amount:"
+msgid "Converted Amount"
+msgstr ""
+
+msgctxt "field:sale.opportunity_employee_monthly,currency:"
+msgid "Currency"
+msgstr "Moneda"
+
+msgctxt "field:sale.opportunity_employee_monthly,currency_digits:"
+msgid "Currency Digits"
+msgstr "Zecimale valută"
+
+msgctxt "field:sale.opportunity_employee_monthly,employee:"
+msgid "Employee"
+msgstr "Angajat"
+
+msgctxt "field:sale.opportunity_employee_monthly,lost:"
+msgid "Lost"
+msgstr "Pierdut"
+
+msgctxt "field:sale.opportunity_employee_monthly,month:"
+msgid "Month"
+msgstr "Lună"
+
+msgctxt "field:sale.opportunity_employee_monthly,number:"
+msgid "Number"
+msgstr "Număr"
+
+msgctxt "field:sale.opportunity_employee_monthly,winning_amount_rate:"
+msgid "Winning Amount Rate"
+msgstr ""
+
+msgctxt "field:sale.opportunity_employee_monthly,winning_rate:"
+msgid "Winning Rate"
+msgstr ""
+
+msgctxt "field:sale.opportunity_employee_monthly,won:"
+msgid "Won"
+msgstr ""
+
+msgctxt "field:sale.opportunity_employee_monthly,won_amount:"
+msgid "Won Amount"
+msgstr ""
+
+msgctxt "field:sale.opportunity_employee_monthly,year:"
+msgid "Year"
+msgstr ""
+
+msgctxt "field:sale.opportunity_monthly,amount:"
+msgid "Amount"
+msgstr "Suma"
+
+msgctxt "field:sale.opportunity_monthly,company:"
+msgid "Company"
+msgstr "Companie"
+
+msgctxt "field:sale.opportunity_monthly,conversion_amount_rate:"
+msgid "Conversion Amount Rate"
+msgstr ""
+
+msgctxt "field:sale.opportunity_monthly,conversion_rate:"
+msgid "Conversion Rate"
+msgstr ""
+
+msgctxt "field:sale.opportunity_monthly,converted:"
+msgid "Converted"
+msgstr ""
+
+msgctxt "field:sale.opportunity_monthly,converted_amount:"
+msgid "Converted Amount"
+msgstr ""
+
+msgctxt "field:sale.opportunity_monthly,currency:"
+msgid "Currency"
+msgstr "Moneda"
+
+msgctxt "field:sale.opportunity_monthly,currency_digits:"
+msgid "Currency Digits"
+msgstr "Zecimale valută"
+
+msgctxt "field:sale.opportunity_monthly,lost:"
+msgid "Lost"
+msgstr "Pierdut"
+
+msgctxt "field:sale.opportunity_monthly,month:"
+msgid "Month"
+msgstr "Lună"
+
+msgctxt "field:sale.opportunity_monthly,number:"
+msgid "Number"
+msgstr "Număr"
+
+msgctxt "field:sale.opportunity_monthly,winning_amount_rate:"
+msgid "Winning Amount Rate"
+msgstr ""
+
+msgctxt "field:sale.opportunity_monthly,winning_rate:"
+msgid "Winning Rate"
+msgstr ""
+
+msgctxt "field:sale.opportunity_monthly,won:"
+msgid "Won"
+msgstr ""
+
+msgctxt "field:sale.opportunity_monthly,won_amount:"
+msgid "Won Amount"
+msgstr ""
+
+msgctxt "field:sale.opportunity_monthly,year:"
+msgid "Year"
+msgstr ""
+
+msgctxt "field:sale.opportunity_monthly,year_month:"
+msgid "Year-Month"
+msgstr ""
+
+msgctxt "help:sale.opportunity,amount:"
+msgid "Estimated revenue amount."
+msgstr ""
+
+msgctxt "help:sale.opportunity,conversion_probability:"
+msgid "Percentage between 0 and 100."
+msgstr ""
+
+msgctxt "model:ir.action,name:act_open_sale_form"
+msgid "Sales"
+msgstr ""
+
+msgctxt "model:ir.action,name:act_opportunity_employee_form"
+msgid "Opportunities per Employee"
+msgstr ""
+
+msgctxt "model:ir.action,name:act_opportunity_employee_monthly_form"
+msgid "Opportunities per Employee per Month"
+msgstr ""
+
+msgctxt "model:ir.action,name:act_opportunity_form"
+msgid "Leads and Opportunities"
+msgstr ""
+
+msgctxt "model:ir.action,name:act_opportunity_form2"
+msgid "Sales Leads/Opportunities"
+msgstr ""
+
+msgctxt "model:ir.action,name:act_opportunity_monthly_form"
+msgid "Opportunities per Month"
+msgstr ""
+
+msgctxt ""
+"model:ir.action.act_window.domain,name:act_opportunity_form_domain_all"
+msgid "All"
+msgstr ""
+
+msgctxt ""
+"model:ir.action.act_window.domain,name:act_opportunity_form_domain_cancelled"
+msgid "Cancelled"
+msgstr ""
+
+msgctxt ""
+"model:ir.action.act_window.domain,name:act_opportunity_form_domain_converted"
+msgid "Converted"
+msgstr ""
+
+msgctxt ""
+"model:ir.action.act_window.domain,name:act_opportunity_form_domain_leads"
+msgid "Leads"
+msgstr ""
+
+msgctxt ""
+"model:ir.action.act_window.domain,name:act_opportunity_form_domain_lost"
+msgid "Lost"
+msgstr ""
+
+msgctxt ""
+"model:ir.action.act_window.domain,name:act_opportunity_form_domain_opportunities"
+msgid "Opportunities"
+msgstr ""
+
+msgctxt ""
+"model:ir.action.act_window.domain,name:act_opportunity_form_domain_won"
+msgid "Won"
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_modify_origin_opportunity"
+msgid "You cannot modify the opportunity origin of the sale \"%(sale)s\"."
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_opportunity_delete_cancel"
+msgid "To delete opportunity \"%(opportunity)s\", you must cancel it."
+msgstr ""
+
+msgctxt "model:ir.model.button,string:opportunity_cancel_button"
+msgid "Cancel"
+msgstr ""
+
+msgctxt "model:ir.model.button,string:opportunity_convert_button"
+msgid "Convert to Sale"
+msgstr ""
+
+msgctxt "model:ir.model.button,string:opportunity_lead_button"
+msgid "Set as Lead"
+msgstr ""
+
+msgctxt "model:ir.model.button,string:opportunity_lost_button"
+msgid "Mark as Lost"
+msgstr ""
+
+msgctxt "model:ir.model.button,string:opportunity_opportunity_button"
+msgid "Convert to Opportunity"
+msgstr ""
+
+msgctxt "model:ir.rule.group,name:rule_group_opportunity_companies"
+msgid "User in companies"
+msgstr ""
+
+msgctxt "model:ir.rule.group,name:rule_group_opportunity_employee_companies"
+msgid "User in companies"
+msgstr ""
+
+msgctxt ""
+"model:ir.rule.group,name:rule_group_opportunity_employee_monthly_companies"
+msgid "User in companies"
+msgstr ""
+
+msgctxt "model:ir.rule.group,name:rule_group_opportunity_monthly_companies"
+msgid "User in companies"
+msgstr ""
+
+msgctxt "model:ir.sequence,name:sequence_sale_opportunity"
+msgid "Sale Opportunity"
+msgstr ""
+
+msgctxt "model:ir.sequence.type,name:sequence_type_sale_opportunity"
+msgid "Sale Opportunity"
+msgstr ""
+
+msgctxt "model:ir.ui.menu,name:menu_opportunity_employee_monthly_form"
+msgid "Opportunities per Employee per Month"
+msgstr ""
+
+msgctxt "model:ir.ui.menu,name:menu_opportunity_employee_open"
+msgid "Opportunities per Employee"
+msgstr ""
+
+msgctxt "model:ir.ui.menu,name:menu_opportunity_form"
+msgid "Leads and Opportunities"
+msgstr ""
+
+msgctxt "model:ir.ui.menu,name:menu_opportunity_monthly_form"
+msgid "Opportunities per Month"
+msgstr ""
+
+msgctxt "model:res.group,name:group_opportunity"
+msgid "Sale Opportunity"
+msgstr ""
+
+msgctxt "model:sale.opportunity,name:"
+msgid "Sale Opportunity"
+msgstr ""
+
+msgctxt "model:sale.opportunity.line,name:"
+msgid "Sale Opportunity Line"
+msgstr ""
+
+msgctxt "model:sale.opportunity_employee,name:"
+msgid "Sale Opportunity per Employee"
+msgstr ""
+
+msgctxt "model:sale.opportunity_employee.context,name:"
+msgid "Sale Opportunity per Employee Context"
+msgstr ""
+
+msgctxt "model:sale.opportunity_employee_monthly,name:"
+msgid "Sale Opportunity per Employee per Month"
+msgstr ""
+
+msgctxt "model:sale.opportunity_monthly,name:"
+msgid "Sale Opportunity per Month"
+msgstr ""
+
+msgctxt "selection:sale.opportunity,state:"
+msgid "Cancelled"
+msgstr ""
+
+msgctxt "selection:sale.opportunity,state:"
+msgid "Converted"
+msgstr ""
+
+msgctxt "selection:sale.opportunity,state:"
+msgid "Lead"
+msgstr ""
+
+msgctxt "selection:sale.opportunity,state:"
+msgid "Lost"
+msgstr ""
+
+msgctxt "selection:sale.opportunity,state:"
+msgid "Opportunity"
+msgstr ""
+
+msgctxt "selection:sale.opportunity,state:"
+msgid "Won"
+msgstr ""
+
+msgctxt "view:sale.opportunity:"
+msgid "%"
+msgstr ""
+
+msgctxt "view:sale.opportunity:"
+msgid "Lead/Opportunity"
+msgstr ""
+
+msgctxt "view:sale.opportunity_employee:"
+msgid "%"
+msgstr ""
+
+msgctxt "view:sale.opportunity_employee_monthly:"
+msgid "%"
+msgstr ""
+
+msgctxt "view:sale.opportunity_monthly:"
+msgid "%"
+msgstr ""
diff --git a/modules/sale_opportunity/locale/ru.po b/modules/sale_opportunity/locale/ru.po
new file mode 100644
index 0000000000..42878559a9
--- /dev/null
+++ b/modules/sale_opportunity/locale/ru.po
@@ -0,0 +1,567 @@
+#
+msgid ""
+msgstr "Content-Type: text/plain; charset=utf-8\n"
+
+msgctxt "field:sale.configuration,sale_opportunity_sequence:"
+msgid "Opportunity Sequence"
+msgstr ""
+
+msgctxt "field:sale.configuration.sequence,sale_opportunity_sequence:"
+msgid "Opportunity Sequence"
+msgstr ""
+
+msgctxt "field:sale.opportunity,address:"
+msgid "Address"
+msgstr "Адрес"
+
+msgctxt "field:sale.opportunity,amount:"
+msgid "Amount"
+msgstr "Сумма"
+
+msgctxt "field:sale.opportunity,comment:"
+msgid "Comment"
+msgstr "Комментарии"
+
+msgctxt "field:sale.opportunity,company:"
+msgid "Company"
+msgstr "Организация"
+
+msgctxt "field:sale.opportunity,contact:"
+msgid "Contact"
+msgstr ""
+
+msgctxt "field:sale.opportunity,conversion_probability:"
+msgid "Conversion Probability"
+msgstr ""
+
+#, fuzzy
+msgctxt "field:sale.opportunity,converted_by:"
+msgid "Converted By"
+msgstr "Обращенные"
+
+msgctxt "field:sale.opportunity,currency:"
+msgid "Currency"
+msgstr "Валюта"
+
+msgctxt "field:sale.opportunity,currency_digits:"
+msgid "Currency Digits"
+msgstr "Кол-во цифр валюты"
+
+msgctxt "field:sale.opportunity,description:"
+msgid "Description"
+msgstr "Описание"
+
+msgctxt "field:sale.opportunity,employee:"
+msgid "Employee"
+msgstr "Сотрудник"
+
+msgctxt "field:sale.opportunity,end_date:"
+msgid "End Date"
+msgstr "Дата окончания"
+
+msgctxt "field:sale.opportunity,lines:"
+msgid "Lines"
+msgstr "Строки"
+
+msgctxt "field:sale.opportunity,lost_reason:"
+msgid "Reason for loss"
+msgstr "Причина потери"
+
+#, fuzzy
+msgctxt "field:sale.opportunity,number:"
+msgid "Number"
+msgstr "Номер"
+
+msgctxt "field:sale.opportunity,party:"
+msgid "Party"
+msgstr "Контрагент"
+
+msgctxt "field:sale.opportunity,payment_term:"
+msgid "Payment Term"
+msgstr "Правило оплаты"
+
+#, fuzzy
+msgctxt "field:sale.opportunity,reference:"
+msgid "Reference"
+msgstr "Ссылка"
+
+#, fuzzy
+msgctxt "field:sale.opportunity,sales:"
+msgid "Sales"
+msgstr "Продажи"
+
+msgctxt "field:sale.opportunity,start_date:"
+msgid "Start Date"
+msgstr "Дата начала"
+
+msgctxt "field:sale.opportunity,state:"
+msgid "State"
+msgstr "Состояние"
+
+msgctxt "field:sale.opportunity.line,opportunity:"
+msgid "Opportunity"
+msgstr "Возможная продажа"
+
+msgctxt "field:sale.opportunity.line,opportunity_state:"
+msgid "Opportunity State"
+msgstr ""
+
+msgctxt "field:sale.opportunity.line,product:"
+msgid "Product"
+msgstr "Продукт"
+
+msgctxt "field:sale.opportunity.line,quantity:"
+msgid "Quantity"
+msgstr "Кол-во"
+
+msgctxt "field:sale.opportunity.line,unit:"
+msgid "Unit"
+msgstr "Единица измерения"
+
+msgctxt "field:sale.opportunity.line,unit_digits:"
+msgid "Unit Digits"
+msgstr "Кол-во цифр после запятой"
+
+msgctxt "field:sale.opportunity_employee,amount:"
+msgid "Amount"
+msgstr "Сумма"
+
+msgctxt "field:sale.opportunity_employee,company:"
+msgid "Company"
+msgstr "Организация"
+
+msgctxt "field:sale.opportunity_employee,conversion_amount_rate:"
+msgid "Conversion Amount Rate"
+msgstr "Общая частота обращения"
+
+msgctxt "field:sale.opportunity_employee,conversion_rate:"
+msgid "Conversion Rate"
+msgstr "Частота обращения"
+
+msgctxt "field:sale.opportunity_employee,converted:"
+msgid "Converted"
+msgstr "Обращенные"
+
+msgctxt "field:sale.opportunity_employee,converted_amount:"
+msgid "Converted Amount"
+msgstr "Кол-во обращенных"
+
+msgctxt "field:sale.opportunity_employee,currency:"
+msgid "Currency"
+msgstr "Валюта"
+
+msgctxt "field:sale.opportunity_employee,currency_digits:"
+msgid "Currency Digits"
+msgstr "Кол-во цифр валюты"
+
+msgctxt "field:sale.opportunity_employee,employee:"
+msgid "Employee"
+msgstr "Сотрудник"
+
+msgctxt "field:sale.opportunity_employee,lost:"
+msgid "Lost"
+msgstr "Утраченная"
+
+msgctxt "field:sale.opportunity_employee,number:"
+msgid "Number"
+msgstr "Номер"
+
+msgctxt "field:sale.opportunity_employee,winning_amount_rate:"
+msgid "Winning Amount Rate"
+msgstr ""
+
+msgctxt "field:sale.opportunity_employee,winning_rate:"
+msgid "Winning Rate"
+msgstr ""
+
+#, fuzzy
+msgctxt "field:sale.opportunity_employee,won:"
+msgid "Won"
+msgstr "Вона"
+
+msgctxt "field:sale.opportunity_employee,won_amount:"
+msgid "Won Amount"
+msgstr ""
+
+#, fuzzy
+msgctxt "field:sale.opportunity_employee.context,end_date:"
+msgid "End Date"
+msgstr "Дата окончания"
+
+#, fuzzy
+msgctxt "field:sale.opportunity_employee.context,start_date:"
+msgid "Start Date"
+msgstr "Дата начала"
+
+msgctxt "field:sale.opportunity_employee_monthly,amount:"
+msgid "Amount"
+msgstr "Сумма"
+
+msgctxt "field:sale.opportunity_employee_monthly,company:"
+msgid "Company"
+msgstr "Организация"
+
+msgctxt "field:sale.opportunity_employee_monthly,conversion_amount_rate:"
+msgid "Conversion Amount Rate"
+msgstr "Общая частота обращения"
+
+msgctxt "field:sale.opportunity_employee_monthly,conversion_rate:"
+msgid "Conversion Rate"
+msgstr "Частота обращения"
+
+msgctxt "field:sale.opportunity_employee_monthly,converted:"
+msgid "Converted"
+msgstr "Обращенные"
+
+msgctxt "field:sale.opportunity_employee_monthly,converted_amount:"
+msgid "Converted Amount"
+msgstr "Кол-во обращенных"
+
+msgctxt "field:sale.opportunity_employee_monthly,currency:"
+msgid "Currency"
+msgstr "Валюта"
+
+msgctxt "field:sale.opportunity_employee_monthly,currency_digits:"
+msgid "Currency Digits"
+msgstr "Кол-во цифр валюты"
+
+msgctxt "field:sale.opportunity_employee_monthly,employee:"
+msgid "Employee"
+msgstr "Сотрудник"
+
+msgctxt "field:sale.opportunity_employee_monthly,lost:"
+msgid "Lost"
+msgstr "Утраченная"
+
+msgctxt "field:sale.opportunity_employee_monthly,month:"
+msgid "Month"
+msgstr "Месяц"
+
+msgctxt "field:sale.opportunity_employee_monthly,number:"
+msgid "Number"
+msgstr "Номер"
+
+msgctxt "field:sale.opportunity_employee_monthly,winning_amount_rate:"
+msgid "Winning Amount Rate"
+msgstr ""
+
+msgctxt "field:sale.opportunity_employee_monthly,winning_rate:"
+msgid "Winning Rate"
+msgstr ""
+
+#, fuzzy
+msgctxt "field:sale.opportunity_employee_monthly,won:"
+msgid "Won"
+msgstr "Вона"
+
+msgctxt "field:sale.opportunity_employee_monthly,won_amount:"
+msgid "Won Amount"
+msgstr ""
+
+msgctxt "field:sale.opportunity_employee_monthly,year:"
+msgid "Year"
+msgstr "Год"
+
+msgctxt "field:sale.opportunity_monthly,amount:"
+msgid "Amount"
+msgstr "Сумма"
+
+msgctxt "field:sale.opportunity_monthly,company:"
+msgid "Company"
+msgstr "Организация"
+
+msgctxt "field:sale.opportunity_monthly,conversion_amount_rate:"
+msgid "Conversion Amount Rate"
+msgstr "Общая частота обращения"
+
+msgctxt "field:sale.opportunity_monthly,conversion_rate:"
+msgid "Conversion Rate"
+msgstr "Частота обращения"
+
+msgctxt "field:sale.opportunity_monthly,converted:"
+msgid "Converted"
+msgstr "Обращенные"
+
+msgctxt "field:sale.opportunity_monthly,converted_amount:"
+msgid "Converted Amount"
+msgstr "Кол-во обращенных"
+
+msgctxt "field:sale.opportunity_monthly,currency:"
+msgid "Currency"
+msgstr "Валюта"
+
+msgctxt "field:sale.opportunity_monthly,currency_digits:"
+msgid "Currency Digits"
+msgstr "Кол-во цифр валюты"
+
+msgctxt "field:sale.opportunity_monthly,lost:"
+msgid "Lost"
+msgstr "Утраченная"
+
+msgctxt "field:sale.opportunity_monthly,month:"
+msgid "Month"
+msgstr "Месяц"
+
+msgctxt "field:sale.opportunity_monthly,number:"
+msgid "Number"
+msgstr "Номер"
+
+msgctxt "field:sale.opportunity_monthly,winning_amount_rate:"
+msgid "Winning Amount Rate"
+msgstr ""
+
+msgctxt "field:sale.opportunity_monthly,winning_rate:"
+msgid "Winning Rate"
+msgstr ""
+
+#, fuzzy
+msgctxt "field:sale.opportunity_monthly,won:"
+msgid "Won"
+msgstr "Вона"
+
+msgctxt "field:sale.opportunity_monthly,won_amount:"
+msgid "Won Amount"
+msgstr ""
+
+msgctxt "field:sale.opportunity_monthly,year:"
+msgid "Year"
+msgstr "Год"
+
+msgctxt "field:sale.opportunity_monthly,year_month:"
+msgid "Year-Month"
+msgstr "Год-Месяц"
+
+#, fuzzy
+msgctxt "help:sale.opportunity,amount:"
+msgid "Estimated revenue amount."
+msgstr "Оценочная прибыль"
+
+msgctxt "help:sale.opportunity,conversion_probability:"
+msgid "Percentage between 0 and 100."
+msgstr ""
+
+#, fuzzy
+msgctxt "model:ir.action,name:act_open_sale_form"
+msgid "Sales"
+msgstr "Продажи"
+
+#, fuzzy
+msgctxt "model:ir.action,name:act_opportunity_employee_form"
+msgid "Opportunities per Employee"
+msgstr "Opportunities per Employee"
+
+#, fuzzy
+msgctxt "model:ir.action,name:act_opportunity_employee_monthly_form"
+msgid "Opportunities per Employee per Month"
+msgstr "Opportunities per Employee per Month"
+
+#, fuzzy
+msgctxt "model:ir.action,name:act_opportunity_form"
+msgid "Leads and Opportunities"
+msgstr "Leads and Opportunities"
+
+#, fuzzy
+msgctxt "model:ir.action,name:act_opportunity_form2"
+msgid "Sales Leads/Opportunities"
+msgstr "Sales Leads/Opportunities"
+
+#, fuzzy
+msgctxt "model:ir.action,name:act_opportunity_monthly_form"
+msgid "Opportunities per Month"
+msgstr "Opportunities per Month"
+
+#, fuzzy
+msgctxt ""
+"model:ir.action.act_window.domain,name:act_opportunity_form_domain_all"
+msgid "All"
+msgstr "All"
+
+#, fuzzy
+msgctxt ""
+"model:ir.action.act_window.domain,name:act_opportunity_form_domain_cancelled"
+msgid "Cancelled"
+msgstr "Cancelled"
+
+#, fuzzy
+msgctxt ""
+"model:ir.action.act_window.domain,name:act_opportunity_form_domain_converted"
+msgid "Converted"
+msgstr "Converted"
+
+#, fuzzy
+msgctxt ""
+"model:ir.action.act_window.domain,name:act_opportunity_form_domain_leads"
+msgid "Leads"
+msgstr "Leads"
+
+#, fuzzy
+msgctxt ""
+"model:ir.action.act_window.domain,name:act_opportunity_form_domain_lost"
+msgid "Lost"
+msgstr "Lost"
+
+#, fuzzy
+msgctxt ""
+"model:ir.action.act_window.domain,name:act_opportunity_form_domain_opportunities"
+msgid "Opportunities"
+msgstr "Opportunities"
+
+#, fuzzy
+msgctxt ""
+"model:ir.action.act_window.domain,name:act_opportunity_form_domain_won"
+msgid "Won"
+msgstr "Вона"
+
+msgctxt "model:ir.message,text:msg_modify_origin_opportunity"
+msgid "You cannot modify the opportunity origin of the sale \"%(sale)s\"."
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_opportunity_delete_cancel"
+msgid "To delete opportunity \"%(opportunity)s\", you must cancel it."
+msgstr ""
+
+msgctxt "model:ir.model.button,string:opportunity_cancel_button"
+msgid "Cancel"
+msgstr "Cancel"
+
+msgctxt "model:ir.model.button,string:opportunity_convert_button"
+msgid "Convert to Sale"
+msgstr "Convert to Sale"
+
+msgctxt "model:ir.model.button,string:opportunity_lead_button"
+msgid "Set as Lead"
+msgstr "Set as Lead"
+
+msgctxt "model:ir.model.button,string:opportunity_lost_button"
+msgid "Mark as Lost"
+msgstr "Mark as Lost"
+
+msgctxt "model:ir.model.button,string:opportunity_opportunity_button"
+msgid "Convert to Opportunity"
+msgstr "Convert to Opportunity"
+
+msgctxt "model:ir.rule.group,name:rule_group_opportunity_companies"
+msgid "User in companies"
+msgstr ""
+
+msgctxt "model:ir.rule.group,name:rule_group_opportunity_employee_companies"
+msgid "User in companies"
+msgstr ""
+
+msgctxt ""
+"model:ir.rule.group,name:rule_group_opportunity_employee_monthly_companies"
+msgid "User in companies"
+msgstr ""
+
+msgctxt "model:ir.rule.group,name:rule_group_opportunity_monthly_companies"
+msgid "User in companies"
+msgstr ""
+
+#, fuzzy
+msgctxt "model:ir.sequence,name:sequence_sale_opportunity"
+msgid "Sale Opportunity"
+msgstr "Продажа Возможной"
+
+#, fuzzy
+msgctxt "model:ir.sequence.type,name:sequence_type_sale_opportunity"
+msgid "Sale Opportunity"
+msgstr "Продажа Возможной"
+
+#, fuzzy
+msgctxt "model:ir.ui.menu,name:menu_opportunity_employee_monthly_form"
+msgid "Opportunities per Employee per Month"
+msgstr "Opportunities per Employee per Month"
+
+#, fuzzy
+msgctxt "model:ir.ui.menu,name:menu_opportunity_employee_open"
+msgid "Opportunities per Employee"
+msgstr "Opportunities per Employee"
+
+#, fuzzy
+msgctxt "model:ir.ui.menu,name:menu_opportunity_form"
+msgid "Leads and Opportunities"
+msgstr "Leads and Opportunities"
+
+#, fuzzy
+msgctxt "model:ir.ui.menu,name:menu_opportunity_monthly_form"
+msgid "Opportunities per Month"
+msgstr "Opportunities per Month"
+
+#, fuzzy
+msgctxt "model:res.group,name:group_opportunity"
+msgid "Sale Opportunity"
+msgstr "Sale Opportunity"
+
+msgctxt "model:sale.opportunity,name:"
+msgid "Sale Opportunity"
+msgstr "Продажа Возможной"
+
+msgctxt "model:sale.opportunity.line,name:"
+msgid "Sale Opportunity Line"
+msgstr "Строка продажи Возможных"
+
+msgctxt "model:sale.opportunity_employee,name:"
+msgid "Sale Opportunity per Employee"
+msgstr "Продажа Возможной по сотрудникам"
+
+#, fuzzy
+msgctxt "model:sale.opportunity_employee.context,name:"
+msgid "Sale Opportunity per Employee Context"
+msgstr "Продажа Возможной по сотрудникам по месяцам"
+
+msgctxt "model:sale.opportunity_employee_monthly,name:"
+msgid "Sale Opportunity per Employee per Month"
+msgstr "Продажа Возможной по сотрудникам по месяцам"
+
+msgctxt "model:sale.opportunity_monthly,name:"
+msgid "Sale Opportunity per Month"
+msgstr "Продажа Возможной по месяцам"
+
+msgctxt "selection:sale.opportunity,state:"
+msgid "Cancelled"
+msgstr "Отмененно"
+
+msgctxt "selection:sale.opportunity,state:"
+msgid "Converted"
+msgstr "Обращенные"
+
+msgctxt "selection:sale.opportunity,state:"
+msgid "Lead"
+msgstr "Неопределенная"
+
+msgctxt "selection:sale.opportunity,state:"
+msgid "Lost"
+msgstr "Утраченная"
+
+msgctxt "selection:sale.opportunity,state:"
+msgid "Opportunity"
+msgstr "Возможная продажа"
+
+#, fuzzy
+msgctxt "selection:sale.opportunity,state:"
+msgid "Won"
+msgstr "Вона"
+
+#, fuzzy
+msgctxt "view:sale.opportunity:"
+msgid "%"
+msgstr "%"
+
+msgctxt "view:sale.opportunity:"
+msgid "Lead/Opportunity"
+msgstr "Неопределенная/Возможная"
+
+#, fuzzy
+msgctxt "view:sale.opportunity_employee:"
+msgid "%"
+msgstr "%"
+
+#, fuzzy
+msgctxt "view:sale.opportunity_employee_monthly:"
+msgid "%"
+msgstr "%"
+
+#, fuzzy
+msgctxt "view:sale.opportunity_monthly:"
+msgid "%"
+msgstr "%"
diff --git a/modules/sale_opportunity/locale/sl.po b/modules/sale_opportunity/locale/sl.po
new file mode 100644
index 0000000000..1cb1afcb8a
--- /dev/null
+++ b/modules/sale_opportunity/locale/sl.po
@@ -0,0 +1,554 @@
+#
+msgid ""
+msgstr "Content-Type: text/plain; charset=utf-8\n"
+
+msgctxt "field:sale.configuration,sale_opportunity_sequence:"
+msgid "Opportunity Sequence"
+msgstr "Štetje priložnosti"
+
+msgctxt "field:sale.configuration.sequence,sale_opportunity_sequence:"
+msgid "Opportunity Sequence"
+msgstr "Štetje priložnosti"
+
+msgctxt "field:sale.opportunity,address:"
+msgid "Address"
+msgstr "Naslov"
+
+msgctxt "field:sale.opportunity,amount:"
+msgid "Amount"
+msgstr "Znesek"
+
+msgctxt "field:sale.opportunity,comment:"
+msgid "Comment"
+msgstr "Opomba"
+
+msgctxt "field:sale.opportunity,company:"
+msgid "Company"
+msgstr "Družba"
+
+msgctxt "field:sale.opportunity,contact:"
+msgid "Contact"
+msgstr ""
+
+msgctxt "field:sale.opportunity,conversion_probability:"
+msgid "Conversion Probability"
+msgstr "Verjetnost pretvorbe"
+
+#, fuzzy
+msgctxt "field:sale.opportunity,converted_by:"
+msgid "Converted By"
+msgstr "Pretvorjeno"
+
+msgctxt "field:sale.opportunity,currency:"
+msgid "Currency"
+msgstr "Valuta"
+
+msgctxt "field:sale.opportunity,currency_digits:"
+msgid "Currency Digits"
+msgstr "Decimalke"
+
+msgctxt "field:sale.opportunity,description:"
+msgid "Description"
+msgstr "Opis"
+
+msgctxt "field:sale.opportunity,employee:"
+msgid "Employee"
+msgstr "Zaposlenec"
+
+msgctxt "field:sale.opportunity,end_date:"
+msgid "End Date"
+msgstr "Končni datum"
+
+msgctxt "field:sale.opportunity,lines:"
+msgid "Lines"
+msgstr "Postavke"
+
+msgctxt "field:sale.opportunity,lost_reason:"
+msgid "Reason for loss"
+msgstr "Razlog za zapravljeno priložnost"
+
+msgctxt "field:sale.opportunity,number:"
+msgid "Number"
+msgstr "Številka"
+
+msgctxt "field:sale.opportunity,party:"
+msgid "Party"
+msgstr "Partner"
+
+msgctxt "field:sale.opportunity,payment_term:"
+msgid "Payment Term"
+msgstr "Plačilni rok"
+
+msgctxt "field:sale.opportunity,reference:"
+msgid "Reference"
+msgstr "Sklic"
+
+msgctxt "field:sale.opportunity,sales:"
+msgid "Sales"
+msgstr "Prodajni nalogi"
+
+msgctxt "field:sale.opportunity,start_date:"
+msgid "Start Date"
+msgstr "Začetni datum"
+
+msgctxt "field:sale.opportunity,state:"
+msgid "State"
+msgstr "Stanje"
+
+msgctxt "field:sale.opportunity.line,opportunity:"
+msgid "Opportunity"
+msgstr "Priložnost"
+
+msgctxt "field:sale.opportunity.line,opportunity_state:"
+msgid "Opportunity State"
+msgstr "Stanje priložnosti"
+
+msgctxt "field:sale.opportunity.line,product:"
+msgid "Product"
+msgstr "Izdelek"
+
+msgctxt "field:sale.opportunity.line,quantity:"
+msgid "Quantity"
+msgstr "Količina"
+
+msgctxt "field:sale.opportunity.line,unit:"
+msgid "Unit"
+msgstr "Enota"
+
+msgctxt "field:sale.opportunity.line,unit_digits:"
+msgid "Unit Digits"
+msgstr "Decimalke"
+
+msgctxt "field:sale.opportunity_employee,amount:"
+msgid "Amount"
+msgstr "Znesek"
+
+msgctxt "field:sale.opportunity_employee,company:"
+msgid "Company"
+msgstr "Družba"
+
+msgctxt "field:sale.opportunity_employee,conversion_amount_rate:"
+msgid "Conversion Amount Rate"
+msgstr "Stopnja pretvorjenega zneska"
+
+msgctxt "field:sale.opportunity_employee,conversion_rate:"
+msgid "Conversion Rate"
+msgstr "Stopnja pretvorbe"
+
+msgctxt "field:sale.opportunity_employee,converted:"
+msgid "Converted"
+msgstr "Pretvorjeno"
+
+msgctxt "field:sale.opportunity_employee,converted_amount:"
+msgid "Converted Amount"
+msgstr "Pretvorjen znesek"
+
+msgctxt "field:sale.opportunity_employee,currency:"
+msgid "Currency"
+msgstr "Valuta"
+
+msgctxt "field:sale.opportunity_employee,currency_digits:"
+msgid "Currency Digits"
+msgstr "Decimalke"
+
+msgctxt "field:sale.opportunity_employee,employee:"
+msgid "Employee"
+msgstr "Zaposlenec"
+
+msgctxt "field:sale.opportunity_employee,lost:"
+msgid "Lost"
+msgstr "Zapravljeno"
+
+msgctxt "field:sale.opportunity_employee,number:"
+msgid "Number"
+msgstr "Številka"
+
+msgctxt "field:sale.opportunity_employee,winning_amount_rate:"
+msgid "Winning Amount Rate"
+msgstr "Delež dobljenega zneska"
+
+msgctxt "field:sale.opportunity_employee,winning_rate:"
+msgid "Winning Rate"
+msgstr "Dobljeni delež"
+
+msgctxt "field:sale.opportunity_employee,won:"
+msgid "Won"
+msgstr "Dobljeno"
+
+msgctxt "field:sale.opportunity_employee,won_amount:"
+msgid "Won Amount"
+msgstr "Dobljeni znesek"
+
+msgctxt "field:sale.opportunity_employee.context,end_date:"
+msgid "End Date"
+msgstr "Končni datum"
+
+msgctxt "field:sale.opportunity_employee.context,start_date:"
+msgid "Start Date"
+msgstr "Začetni datum"
+
+msgctxt "field:sale.opportunity_employee_monthly,amount:"
+msgid "Amount"
+msgstr "Znesek"
+
+msgctxt "field:sale.opportunity_employee_monthly,company:"
+msgid "Company"
+msgstr "Družba"
+
+msgctxt "field:sale.opportunity_employee_monthly,conversion_amount_rate:"
+msgid "Conversion Amount Rate"
+msgstr "Stopnja pretvorjenega zneska"
+
+msgctxt "field:sale.opportunity_employee_monthly,conversion_rate:"
+msgid "Conversion Rate"
+msgstr "Stopnja pretvorbe"
+
+msgctxt "field:sale.opportunity_employee_monthly,converted:"
+msgid "Converted"
+msgstr "Pretvorjeno"
+
+msgctxt "field:sale.opportunity_employee_monthly,converted_amount:"
+msgid "Converted Amount"
+msgstr "Pretvorjen znesek"
+
+msgctxt "field:sale.opportunity_employee_monthly,currency:"
+msgid "Currency"
+msgstr "Valuta"
+
+msgctxt "field:sale.opportunity_employee_monthly,currency_digits:"
+msgid "Currency Digits"
+msgstr "Decimalke"
+
+msgctxt "field:sale.opportunity_employee_monthly,employee:"
+msgid "Employee"
+msgstr "Zaposlenec"
+
+msgctxt "field:sale.opportunity_employee_monthly,lost:"
+msgid "Lost"
+msgstr "Zapravljeno"
+
+msgctxt "field:sale.opportunity_employee_monthly,month:"
+msgid "Month"
+msgstr "Mesec"
+
+msgctxt "field:sale.opportunity_employee_monthly,number:"
+msgid "Number"
+msgstr "Številka"
+
+msgctxt "field:sale.opportunity_employee_monthly,winning_amount_rate:"
+msgid "Winning Amount Rate"
+msgstr "Delež dobljenega zneska"
+
+msgctxt "field:sale.opportunity_employee_monthly,winning_rate:"
+msgid "Winning Rate"
+msgstr "Dobljeni delež"
+
+msgctxt "field:sale.opportunity_employee_monthly,won:"
+msgid "Won"
+msgstr "Dobljeno"
+
+msgctxt "field:sale.opportunity_employee_monthly,won_amount:"
+msgid "Won Amount"
+msgstr "Dobljeni znesek"
+
+msgctxt "field:sale.opportunity_employee_monthly,year:"
+msgid "Year"
+msgstr "Leto"
+
+msgctxt "field:sale.opportunity_monthly,amount:"
+msgid "Amount"
+msgstr "Znesek"
+
+msgctxt "field:sale.opportunity_monthly,company:"
+msgid "Company"
+msgstr "Družba"
+
+msgctxt "field:sale.opportunity_monthly,conversion_amount_rate:"
+msgid "Conversion Amount Rate"
+msgstr "Stopnja pretvorjenega zneska"
+
+msgctxt "field:sale.opportunity_monthly,conversion_rate:"
+msgid "Conversion Rate"
+msgstr "Stopnja pretvorbe"
+
+msgctxt "field:sale.opportunity_monthly,converted:"
+msgid "Converted"
+msgstr "Pretvorjeno"
+
+msgctxt "field:sale.opportunity_monthly,converted_amount:"
+msgid "Converted Amount"
+msgstr "Pretvorjen znesek"
+
+msgctxt "field:sale.opportunity_monthly,currency:"
+msgid "Currency"
+msgstr "Valuta"
+
+msgctxt "field:sale.opportunity_monthly,currency_digits:"
+msgid "Currency Digits"
+msgstr "Decimalke"
+
+msgctxt "field:sale.opportunity_monthly,lost:"
+msgid "Lost"
+msgstr "Zapravljeno"
+
+msgctxt "field:sale.opportunity_monthly,month:"
+msgid "Month"
+msgstr "Mesec"
+
+msgctxt "field:sale.opportunity_monthly,number:"
+msgid "Number"
+msgstr "Številka"
+
+msgctxt "field:sale.opportunity_monthly,winning_amount_rate:"
+msgid "Winning Amount Rate"
+msgstr "Delež dobljenega zneska"
+
+msgctxt "field:sale.opportunity_monthly,winning_rate:"
+msgid "Winning Rate"
+msgstr "Dobljeni delež"
+
+msgctxt "field:sale.opportunity_monthly,won:"
+msgid "Won"
+msgstr "Dobljeno"
+
+msgctxt "field:sale.opportunity_monthly,won_amount:"
+msgid "Won Amount"
+msgstr "Dobljeni znesek"
+
+msgctxt "field:sale.opportunity_monthly,year:"
+msgid "Year"
+msgstr "Leto"
+
+msgctxt "field:sale.opportunity_monthly,year_month:"
+msgid "Year-Month"
+msgstr "Leto-Mesec"
+
+#, fuzzy
+msgctxt "help:sale.opportunity,amount:"
+msgid "Estimated revenue amount."
+msgstr "Ocenjen znesek prihodkov"
+
+#, fuzzy
+msgctxt "help:sale.opportunity,conversion_probability:"
+msgid "Percentage between 0 and 100."
+msgstr "Odstotek med 0 in 100"
+
+#, fuzzy
+msgctxt "model:ir.action,name:act_open_sale_form"
+msgid "Sales"
+msgstr "Sales"
+
+#, fuzzy
+msgctxt "model:ir.action,name:act_opportunity_employee_form"
+msgid "Opportunities per Employee"
+msgstr "Opportunities per Employee"
+
+#, fuzzy
+msgctxt "model:ir.action,name:act_opportunity_employee_monthly_form"
+msgid "Opportunities per Employee per Month"
+msgstr "Opportunities per Employee per Month"
+
+#, fuzzy
+msgctxt "model:ir.action,name:act_opportunity_form"
+msgid "Leads and Opportunities"
+msgstr "Leads and Opportunities"
+
+#, fuzzy
+msgctxt "model:ir.action,name:act_opportunity_form2"
+msgid "Sales Leads/Opportunities"
+msgstr "Sales Leads/Opportunities"
+
+#, fuzzy
+msgctxt "model:ir.action,name:act_opportunity_monthly_form"
+msgid "Opportunities per Month"
+msgstr "Opportunities per Month"
+
+#, fuzzy
+msgctxt ""
+"model:ir.action.act_window.domain,name:act_opportunity_form_domain_all"
+msgid "All"
+msgstr "All"
+
+#, fuzzy
+msgctxt ""
+"model:ir.action.act_window.domain,name:act_opportunity_form_domain_cancelled"
+msgid "Cancelled"
+msgstr "Cancelled"
+
+#, fuzzy
+msgctxt ""
+"model:ir.action.act_window.domain,name:act_opportunity_form_domain_converted"
+msgid "Converted"
+msgstr "Converted"
+
+#, fuzzy
+msgctxt ""
+"model:ir.action.act_window.domain,name:act_opportunity_form_domain_leads"
+msgid "Leads"
+msgstr "Leads"
+
+#, fuzzy
+msgctxt ""
+"model:ir.action.act_window.domain,name:act_opportunity_form_domain_lost"
+msgid "Lost"
+msgstr "Lost"
+
+#, fuzzy
+msgctxt ""
+"model:ir.action.act_window.domain,name:act_opportunity_form_domain_opportunities"
+msgid "Opportunities"
+msgstr "Opportunities"
+
+#, fuzzy
+msgctxt ""
+"model:ir.action.act_window.domain,name:act_opportunity_form_domain_won"
+msgid "Won"
+msgstr "Won"
+
+msgctxt "model:ir.message,text:msg_modify_origin_opportunity"
+msgid "You cannot modify the opportunity origin of the sale \"%(sale)s\"."
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_opportunity_delete_cancel"
+msgid "To delete opportunity \"%(opportunity)s\", you must cancel it."
+msgstr ""
+
+msgctxt "model:ir.model.button,string:opportunity_cancel_button"
+msgid "Cancel"
+msgstr "Cancel"
+
+msgctxt "model:ir.model.button,string:opportunity_convert_button"
+msgid "Convert to Sale"
+msgstr "Convert to Sale"
+
+msgctxt "model:ir.model.button,string:opportunity_lead_button"
+msgid "Set as Lead"
+msgstr "Set as Lead"
+
+msgctxt "model:ir.model.button,string:opportunity_lost_button"
+msgid "Mark as Lost"
+msgstr "Mark as Lost"
+
+msgctxt "model:ir.model.button,string:opportunity_opportunity_button"
+msgid "Convert to Opportunity"
+msgstr "Convert to Opportunity"
+
+msgctxt "model:ir.rule.group,name:rule_group_opportunity_companies"
+msgid "User in companies"
+msgstr ""
+
+msgctxt "model:ir.rule.group,name:rule_group_opportunity_employee_companies"
+msgid "User in companies"
+msgstr ""
+
+msgctxt ""
+"model:ir.rule.group,name:rule_group_opportunity_employee_monthly_companies"
+msgid "User in companies"
+msgstr ""
+
+msgctxt "model:ir.rule.group,name:rule_group_opportunity_monthly_companies"
+msgid "User in companies"
+msgstr ""
+
+#, fuzzy
+msgctxt "model:ir.sequence,name:sequence_sale_opportunity"
+msgid "Sale Opportunity"
+msgstr "Sale Opportunity"
+
+#, fuzzy
+msgctxt "model:ir.sequence.type,name:sequence_type_sale_opportunity"
+msgid "Sale Opportunity"
+msgstr "Sale Opportunity"
+
+#, fuzzy
+msgctxt "model:ir.ui.menu,name:menu_opportunity_employee_monthly_form"
+msgid "Opportunities per Employee per Month"
+msgstr "Opportunities per Employee per Month"
+
+#, fuzzy
+msgctxt "model:ir.ui.menu,name:menu_opportunity_employee_open"
+msgid "Opportunities per Employee"
+msgstr "Opportunities per Employee"
+
+#, fuzzy
+msgctxt "model:ir.ui.menu,name:menu_opportunity_form"
+msgid "Leads and Opportunities"
+msgstr "Leads and Opportunities"
+
+#, fuzzy
+msgctxt "model:ir.ui.menu,name:menu_opportunity_monthly_form"
+msgid "Opportunities per Month"
+msgstr "Opportunities per Month"
+
+#, fuzzy
+msgctxt "model:res.group,name:group_opportunity"
+msgid "Sale Opportunity"
+msgstr "Sale Opportunity"
+
+msgctxt "model:sale.opportunity,name:"
+msgid "Sale Opportunity"
+msgstr "Prodajna priložnost"
+
+msgctxt "model:sale.opportunity.line,name:"
+msgid "Sale Opportunity Line"
+msgstr "Postavka prodajne priložnosti"
+
+msgctxt "model:sale.opportunity_employee,name:"
+msgid "Sale Opportunity per Employee"
+msgstr "Prodajna priložnost na zaposlenca"
+
+msgctxt "model:sale.opportunity_employee.context,name:"
+msgid "Sale Opportunity per Employee Context"
+msgstr "Kontekst prodajne priložnosti na zaposlenca"
+
+msgctxt "model:sale.opportunity_employee_monthly,name:"
+msgid "Sale Opportunity per Employee per Month"
+msgstr "Mesečna prodajna priložnost na zaposlenca"
+
+msgctxt "model:sale.opportunity_monthly,name:"
+msgid "Sale Opportunity per Month"
+msgstr "Mesečna prodajna priložnost"
+
+msgctxt "selection:sale.opportunity,state:"
+msgid "Cancelled"
+msgstr "Preklicano"
+
+msgctxt "selection:sale.opportunity,state:"
+msgid "Converted"
+msgstr "Pretvorjeno"
+
+msgctxt "selection:sale.opportunity,state:"
+msgid "Lead"
+msgstr "Sled"
+
+msgctxt "selection:sale.opportunity,state:"
+msgid "Lost"
+msgstr "Zapravljeno"
+
+msgctxt "selection:sale.opportunity,state:"
+msgid "Opportunity"
+msgstr "Priložnost"
+
+msgctxt "selection:sale.opportunity,state:"
+msgid "Won"
+msgstr "Dobljeno"
+
+msgctxt "view:sale.opportunity:"
+msgid "%"
+msgstr "%"
+
+msgctxt "view:sale.opportunity:"
+msgid "Lead/Opportunity"
+msgstr "Sled/Priložnost"
+
+msgctxt "view:sale.opportunity_employee:"
+msgid "%"
+msgstr "%"
+
+msgctxt "view:sale.opportunity_employee_monthly:"
+msgid "%"
+msgstr "%"
+
+msgctxt "view:sale.opportunity_monthly:"
+msgid "%"
+msgstr "%"
diff --git a/modules/sale_opportunity/locale/tr.po b/modules/sale_opportunity/locale/tr.po
new file mode 100644
index 0000000000..cc0894b74f
--- /dev/null
+++ b/modules/sale_opportunity/locale/tr.po
@@ -0,0 +1,555 @@
+#
+msgid ""
+msgstr "Content-Type: text/plain; charset=utf-8\n"
+
+msgctxt "field:sale.configuration,sale_opportunity_sequence:"
+msgid "Opportunity Sequence"
+msgstr ""
+
+msgctxt "field:sale.configuration.sequence,sale_opportunity_sequence:"
+msgid "Opportunity Sequence"
+msgstr ""
+
+msgctxt "field:sale.opportunity,address:"
+msgid "Address"
+msgstr ""
+
+msgctxt "field:sale.opportunity,amount:"
+msgid "Amount"
+msgstr ""
+
+msgctxt "field:sale.opportunity,comment:"
+msgid "Comment"
+msgstr ""
+
+msgctxt "field:sale.opportunity,company:"
+msgid "Company"
+msgstr ""
+
+msgctxt "field:sale.opportunity,contact:"
+msgid "Contact"
+msgstr ""
+
+msgctxt "field:sale.opportunity,conversion_probability:"
+msgid "Conversion Probability"
+msgstr ""
+
+#, fuzzy
+msgctxt "field:sale.opportunity,converted_by:"
+msgid "Converted By"
+msgstr "Converted"
+
+msgctxt "field:sale.opportunity,currency:"
+msgid "Currency"
+msgstr ""
+
+msgctxt "field:sale.opportunity,currency_digits:"
+msgid "Currency Digits"
+msgstr ""
+
+msgctxt "field:sale.opportunity,description:"
+msgid "Description"
+msgstr ""
+
+msgctxt "field:sale.opportunity,employee:"
+msgid "Employee"
+msgstr ""
+
+msgctxt "field:sale.opportunity,end_date:"
+msgid "End Date"
+msgstr ""
+
+msgctxt "field:sale.opportunity,lines:"
+msgid "Lines"
+msgstr ""
+
+msgctxt "field:sale.opportunity,lost_reason:"
+msgid "Reason for loss"
+msgstr ""
+
+msgctxt "field:sale.opportunity,number:"
+msgid "Number"
+msgstr ""
+
+msgctxt "field:sale.opportunity,party:"
+msgid "Party"
+msgstr ""
+
+msgctxt "field:sale.opportunity,payment_term:"
+msgid "Payment Term"
+msgstr ""
+
+msgctxt "field:sale.opportunity,reference:"
+msgid "Reference"
+msgstr ""
+
+#, fuzzy
+msgctxt "field:sale.opportunity,sales:"
+msgid "Sales"
+msgstr "Sales"
+
+msgctxt "field:sale.opportunity,start_date:"
+msgid "Start Date"
+msgstr ""
+
+msgctxt "field:sale.opportunity,state:"
+msgid "State"
+msgstr ""
+
+#, fuzzy
+msgctxt "field:sale.opportunity.line,opportunity:"
+msgid "Opportunity"
+msgstr "Opportunities"
+
+msgctxt "field:sale.opportunity.line,opportunity_state:"
+msgid "Opportunity State"
+msgstr ""
+
+msgctxt "field:sale.opportunity.line,product:"
+msgid "Product"
+msgstr ""
+
+msgctxt "field:sale.opportunity.line,quantity:"
+msgid "Quantity"
+msgstr ""
+
+msgctxt "field:sale.opportunity.line,unit:"
+msgid "Unit"
+msgstr ""
+
+msgctxt "field:sale.opportunity.line,unit_digits:"
+msgid "Unit Digits"
+msgstr ""
+
+msgctxt "field:sale.opportunity_employee,amount:"
+msgid "Amount"
+msgstr ""
+
+msgctxt "field:sale.opportunity_employee,company:"
+msgid "Company"
+msgstr ""
+
+msgctxt "field:sale.opportunity_employee,conversion_amount_rate:"
+msgid "Conversion Amount Rate"
+msgstr ""
+
+msgctxt "field:sale.opportunity_employee,conversion_rate:"
+msgid "Conversion Rate"
+msgstr ""
+
+#, fuzzy
+msgctxt "field:sale.opportunity_employee,converted:"
+msgid "Converted"
+msgstr "Converted"
+
+msgctxt "field:sale.opportunity_employee,converted_amount:"
+msgid "Converted Amount"
+msgstr ""
+
+msgctxt "field:sale.opportunity_employee,currency:"
+msgid "Currency"
+msgstr ""
+
+msgctxt "field:sale.opportunity_employee,currency_digits:"
+msgid "Currency Digits"
+msgstr ""
+
+msgctxt "field:sale.opportunity_employee,employee:"
+msgid "Employee"
+msgstr ""
+
+#, fuzzy
+msgctxt "field:sale.opportunity_employee,lost:"
+msgid "Lost"
+msgstr "Lost"
+
+msgctxt "field:sale.opportunity_employee,number:"
+msgid "Number"
+msgstr ""
+
+msgctxt "field:sale.opportunity_employee,winning_amount_rate:"
+msgid "Winning Amount Rate"
+msgstr ""
+
+msgctxt "field:sale.opportunity_employee,winning_rate:"
+msgid "Winning Rate"
+msgstr ""
+
+#, fuzzy
+msgctxt "field:sale.opportunity_employee,won:"
+msgid "Won"
+msgstr "Won"
+
+msgctxt "field:sale.opportunity_employee,won_amount:"
+msgid "Won Amount"
+msgstr ""
+
+msgctxt "field:sale.opportunity_employee.context,end_date:"
+msgid "End Date"
+msgstr ""
+
+msgctxt "field:sale.opportunity_employee.context,start_date:"
+msgid "Start Date"
+msgstr ""
+
+msgctxt "field:sale.opportunity_employee_monthly,amount:"
+msgid "Amount"
+msgstr ""
+
+msgctxt "field:sale.opportunity_employee_monthly,company:"
+msgid "Company"
+msgstr ""
+
+msgctxt "field:sale.opportunity_employee_monthly,conversion_amount_rate:"
+msgid "Conversion Amount Rate"
+msgstr ""
+
+msgctxt "field:sale.opportunity_employee_monthly,conversion_rate:"
+msgid "Conversion Rate"
+msgstr ""
+
+#, fuzzy
+msgctxt "field:sale.opportunity_employee_monthly,converted:"
+msgid "Converted"
+msgstr "Converted"
+
+msgctxt "field:sale.opportunity_employee_monthly,converted_amount:"
+msgid "Converted Amount"
+msgstr ""
+
+msgctxt "field:sale.opportunity_employee_monthly,currency:"
+msgid "Currency"
+msgstr ""
+
+msgctxt "field:sale.opportunity_employee_monthly,currency_digits:"
+msgid "Currency Digits"
+msgstr ""
+
+msgctxt "field:sale.opportunity_employee_monthly,employee:"
+msgid "Employee"
+msgstr ""
+
+#, fuzzy
+msgctxt "field:sale.opportunity_employee_monthly,lost:"
+msgid "Lost"
+msgstr "Lost"
+
+msgctxt "field:sale.opportunity_employee_monthly,month:"
+msgid "Month"
+msgstr ""
+
+msgctxt "field:sale.opportunity_employee_monthly,number:"
+msgid "Number"
+msgstr ""
+
+msgctxt "field:sale.opportunity_employee_monthly,winning_amount_rate:"
+msgid "Winning Amount Rate"
+msgstr ""
+
+msgctxt "field:sale.opportunity_employee_monthly,winning_rate:"
+msgid "Winning Rate"
+msgstr ""
+
+#, fuzzy
+msgctxt "field:sale.opportunity_employee_monthly,won:"
+msgid "Won"
+msgstr "Won"
+
+msgctxt "field:sale.opportunity_employee_monthly,won_amount:"
+msgid "Won Amount"
+msgstr ""
+
+msgctxt "field:sale.opportunity_employee_monthly,year:"
+msgid "Year"
+msgstr ""
+
+msgctxt "field:sale.opportunity_monthly,amount:"
+msgid "Amount"
+msgstr ""
+
+msgctxt "field:sale.opportunity_monthly,company:"
+msgid "Company"
+msgstr ""
+
+msgctxt "field:sale.opportunity_monthly,conversion_amount_rate:"
+msgid "Conversion Amount Rate"
+msgstr ""
+
+msgctxt "field:sale.opportunity_monthly,conversion_rate:"
+msgid "Conversion Rate"
+msgstr ""
+
+#, fuzzy
+msgctxt "field:sale.opportunity_monthly,converted:"
+msgid "Converted"
+msgstr "Converted"
+
+msgctxt "field:sale.opportunity_monthly,converted_amount:"
+msgid "Converted Amount"
+msgstr ""
+
+msgctxt "field:sale.opportunity_monthly,currency:"
+msgid "Currency"
+msgstr ""
+
+msgctxt "field:sale.opportunity_monthly,currency_digits:"
+msgid "Currency Digits"
+msgstr ""
+
+#, fuzzy
+msgctxt "field:sale.opportunity_monthly,lost:"
+msgid "Lost"
+msgstr "Lost"
+
+msgctxt "field:sale.opportunity_monthly,month:"
+msgid "Month"
+msgstr ""
+
+msgctxt "field:sale.opportunity_monthly,number:"
+msgid "Number"
+msgstr ""
+
+msgctxt "field:sale.opportunity_monthly,winning_amount_rate:"
+msgid "Winning Amount Rate"
+msgstr ""
+
+msgctxt "field:sale.opportunity_monthly,winning_rate:"
+msgid "Winning Rate"
+msgstr ""
+
+#, fuzzy
+msgctxt "field:sale.opportunity_monthly,won:"
+msgid "Won"
+msgstr "Won"
+
+msgctxt "field:sale.opportunity_monthly,won_amount:"
+msgid "Won Amount"
+msgstr ""
+
+msgctxt "field:sale.opportunity_monthly,year:"
+msgid "Year"
+msgstr ""
+
+msgctxt "field:sale.opportunity_monthly,year_month:"
+msgid "Year-Month"
+msgstr ""
+
+msgctxt "help:sale.opportunity,amount:"
+msgid "Estimated revenue amount."
+msgstr ""
+
+msgctxt "help:sale.opportunity,conversion_probability:"
+msgid "Percentage between 0 and 100."
+msgstr ""
+
+msgctxt "model:ir.action,name:act_open_sale_form"
+msgid "Sales"
+msgstr "Sales"
+
+msgctxt "model:ir.action,name:act_opportunity_employee_form"
+msgid "Opportunities per Employee"
+msgstr "Opportunities per Employee"
+
+msgctxt "model:ir.action,name:act_opportunity_employee_monthly_form"
+msgid "Opportunities per Employee per Month"
+msgstr "Opportunities per Employee per Month"
+
+msgctxt "model:ir.action,name:act_opportunity_form"
+msgid "Leads and Opportunities"
+msgstr "Leads and Opportunities"
+
+msgctxt "model:ir.action,name:act_opportunity_form2"
+msgid "Sales Leads/Opportunities"
+msgstr "Sales Leads/Opportunities"
+
+msgctxt "model:ir.action,name:act_opportunity_monthly_form"
+msgid "Opportunities per Month"
+msgstr "Opportunities per Month"
+
+msgctxt ""
+"model:ir.action.act_window.domain,name:act_opportunity_form_domain_all"
+msgid "All"
+msgstr "All"
+
+msgctxt ""
+"model:ir.action.act_window.domain,name:act_opportunity_form_domain_cancelled"
+msgid "Cancelled"
+msgstr "Cancelled"
+
+msgctxt ""
+"model:ir.action.act_window.domain,name:act_opportunity_form_domain_converted"
+msgid "Converted"
+msgstr "Converted"
+
+msgctxt ""
+"model:ir.action.act_window.domain,name:act_opportunity_form_domain_leads"
+msgid "Leads"
+msgstr "Leads"
+
+msgctxt ""
+"model:ir.action.act_window.domain,name:act_opportunity_form_domain_lost"
+msgid "Lost"
+msgstr "Lost"
+
+msgctxt ""
+"model:ir.action.act_window.domain,name:act_opportunity_form_domain_opportunities"
+msgid "Opportunities"
+msgstr "Opportunities"
+
+msgctxt ""
+"model:ir.action.act_window.domain,name:act_opportunity_form_domain_won"
+msgid "Won"
+msgstr "Won"
+
+msgctxt "model:ir.message,text:msg_modify_origin_opportunity"
+msgid "You cannot modify the opportunity origin of the sale \"%(sale)s\"."
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_opportunity_delete_cancel"
+msgid "To delete opportunity \"%(opportunity)s\", you must cancel it."
+msgstr ""
+
+msgctxt "model:ir.model.button,string:opportunity_cancel_button"
+msgid "Cancel"
+msgstr "Cancel"
+
+msgctxt "model:ir.model.button,string:opportunity_convert_button"
+msgid "Convert to Sale"
+msgstr "Convert to Sale"
+
+msgctxt "model:ir.model.button,string:opportunity_lead_button"
+msgid "Set as Lead"
+msgstr "Set as Lead"
+
+msgctxt "model:ir.model.button,string:opportunity_lost_button"
+msgid "Mark as Lost"
+msgstr "Mark as Lost"
+
+msgctxt "model:ir.model.button,string:opportunity_opportunity_button"
+msgid "Convert to Opportunity"
+msgstr "Convert to Opportunity"
+
+msgctxt "model:ir.rule.group,name:rule_group_opportunity_companies"
+msgid "User in companies"
+msgstr ""
+
+msgctxt "model:ir.rule.group,name:rule_group_opportunity_employee_companies"
+msgid "User in companies"
+msgstr ""
+
+msgctxt ""
+"model:ir.rule.group,name:rule_group_opportunity_employee_monthly_companies"
+msgid "User in companies"
+msgstr ""
+
+msgctxt "model:ir.rule.group,name:rule_group_opportunity_monthly_companies"
+msgid "User in companies"
+msgstr ""
+
+msgctxt "model:ir.sequence,name:sequence_sale_opportunity"
+msgid "Sale Opportunity"
+msgstr "Sale Opportunity"
+
+msgctxt "model:ir.sequence.type,name:sequence_type_sale_opportunity"
+msgid "Sale Opportunity"
+msgstr "Sale Opportunity"
+
+msgctxt "model:ir.ui.menu,name:menu_opportunity_employee_monthly_form"
+msgid "Opportunities per Employee per Month"
+msgstr "Opportunities per Employee per Month"
+
+msgctxt "model:ir.ui.menu,name:menu_opportunity_employee_open"
+msgid "Opportunities per Employee"
+msgstr "Opportunities per Employee"
+
+msgctxt "model:ir.ui.menu,name:menu_opportunity_form"
+msgid "Leads and Opportunities"
+msgstr "Leads and Opportunities"
+
+msgctxt "model:ir.ui.menu,name:menu_opportunity_monthly_form"
+msgid "Opportunities per Month"
+msgstr "Opportunities per Month"
+
+msgctxt "model:res.group,name:group_opportunity"
+msgid "Sale Opportunity"
+msgstr "Sale Opportunity"
+
+#, fuzzy
+msgctxt "model:sale.opportunity,name:"
+msgid "Sale Opportunity"
+msgstr "Sale Opportunity"
+
+#, fuzzy
+msgctxt "model:sale.opportunity.line,name:"
+msgid "Sale Opportunity Line"
+msgstr "Sale Opportunity"
+
+#, fuzzy
+msgctxt "model:sale.opportunity_employee,name:"
+msgid "Sale Opportunity per Employee"
+msgstr "Opportunities per Employee per Month"
+
+#, fuzzy
+msgctxt "model:sale.opportunity_employee.context,name:"
+msgid "Sale Opportunity per Employee Context"
+msgstr "Opportunities per Employee per Month"
+
+#, fuzzy
+msgctxt "model:sale.opportunity_employee_monthly,name:"
+msgid "Sale Opportunity per Employee per Month"
+msgstr "Opportunities per Employee per Month"
+
+#, fuzzy
+msgctxt "model:sale.opportunity_monthly,name:"
+msgid "Sale Opportunity per Month"
+msgstr "Opportunities per Employee per Month"
+
+#, fuzzy
+msgctxt "selection:sale.opportunity,state:"
+msgid "Cancelled"
+msgstr "Cancelled"
+
+#, fuzzy
+msgctxt "selection:sale.opportunity,state:"
+msgid "Converted"
+msgstr "Converted"
+
+#, fuzzy
+msgctxt "selection:sale.opportunity,state:"
+msgid "Lead"
+msgstr "Leads"
+
+#, fuzzy
+msgctxt "selection:sale.opportunity,state:"
+msgid "Lost"
+msgstr "Lost"
+
+#, fuzzy
+msgctxt "selection:sale.opportunity,state:"
+msgid "Opportunity"
+msgstr "Opportunities"
+
+#, fuzzy
+msgctxt "selection:sale.opportunity,state:"
+msgid "Won"
+msgstr "Won"
+
+msgctxt "view:sale.opportunity:"
+msgid "%"
+msgstr "%"
+
+msgctxt "view:sale.opportunity:"
+msgid "Lead/Opportunity"
+msgstr ""
+
+msgctxt "view:sale.opportunity_employee:"
+msgid "%"
+msgstr "%"
+
+msgctxt "view:sale.opportunity_employee_monthly:"
+msgid "%"
+msgstr "%"
+
+msgctxt "view:sale.opportunity_monthly:"
+msgid "%"
+msgstr "%"
diff --git a/modules/sale_opportunity/locale/zh_CN.po b/modules/sale_opportunity/locale/zh_CN.po
new file mode 100644
index 0000000000..3b2c858a28
--- /dev/null
+++ b/modules/sale_opportunity/locale/zh_CN.po
@@ -0,0 +1,563 @@
+#
+msgid ""
+msgstr "Content-Type: text/plain; charset=utf-8\n"
+
+msgctxt "field:sale.configuration,sale_opportunity_sequence:"
+msgid "Opportunity Sequence"
+msgstr ""
+
+msgctxt "field:sale.configuration.sequence,sale_opportunity_sequence:"
+msgid "Opportunity Sequence"
+msgstr ""
+
+msgctxt "field:sale.opportunity,address:"
+msgid "Address"
+msgstr ""
+
+msgctxt "field:sale.opportunity,amount:"
+msgid "Amount"
+msgstr ""
+
+msgctxt "field:sale.opportunity,comment:"
+msgid "Comment"
+msgstr ""
+
+msgctxt "field:sale.opportunity,company:"
+msgid "Company"
+msgstr ""
+
+msgctxt "field:sale.opportunity,contact:"
+msgid "Contact"
+msgstr ""
+
+msgctxt "field:sale.opportunity,conversion_probability:"
+msgid "Conversion Probability"
+msgstr ""
+
+#, fuzzy
+msgctxt "field:sale.opportunity,converted_by:"
+msgid "Converted By"
+msgstr "Converted"
+
+msgctxt "field:sale.opportunity,currency:"
+msgid "Currency"
+msgstr ""
+
+msgctxt "field:sale.opportunity,currency_digits:"
+msgid "Currency Digits"
+msgstr ""
+
+#, fuzzy
+msgctxt "field:sale.opportunity,description:"
+msgid "Description"
+msgstr "描述"
+
+msgctxt "field:sale.opportunity,employee:"
+msgid "Employee"
+msgstr ""
+
+msgctxt "field:sale.opportunity,end_date:"
+msgid "End Date"
+msgstr ""
+
+msgctxt "field:sale.opportunity,lines:"
+msgid "Lines"
+msgstr ""
+
+msgctxt "field:sale.opportunity,lost_reason:"
+msgid "Reason for loss"
+msgstr ""
+
+msgctxt "field:sale.opportunity,number:"
+msgid "Number"
+msgstr ""
+
+msgctxt "field:sale.opportunity,party:"
+msgid "Party"
+msgstr ""
+
+msgctxt "field:sale.opportunity,payment_term:"
+msgid "Payment Term"
+msgstr ""
+
+msgctxt "field:sale.opportunity,reference:"
+msgid "Reference"
+msgstr ""
+
+#, fuzzy
+msgctxt "field:sale.opportunity,sales:"
+msgid "Sales"
+msgstr "Sales"
+
+msgctxt "field:sale.opportunity,start_date:"
+msgid "Start Date"
+msgstr ""
+
+#, fuzzy
+msgctxt "field:sale.opportunity,state:"
+msgid "State"
+msgstr "状态"
+
+#, fuzzy
+msgctxt "field:sale.opportunity.line,opportunity:"
+msgid "Opportunity"
+msgstr "Opportunities"
+
+msgctxt "field:sale.opportunity.line,opportunity_state:"
+msgid "Opportunity State"
+msgstr ""
+
+msgctxt "field:sale.opportunity.line,product:"
+msgid "Product"
+msgstr ""
+
+msgctxt "field:sale.opportunity.line,quantity:"
+msgid "Quantity"
+msgstr ""
+
+msgctxt "field:sale.opportunity.line,unit:"
+msgid "Unit"
+msgstr ""
+
+msgctxt "field:sale.opportunity.line,unit_digits:"
+msgid "Unit Digits"
+msgstr ""
+
+msgctxt "field:sale.opportunity_employee,amount:"
+msgid "Amount"
+msgstr ""
+
+msgctxt "field:sale.opportunity_employee,company:"
+msgid "Company"
+msgstr ""
+
+msgctxt "field:sale.opportunity_employee,conversion_amount_rate:"
+msgid "Conversion Amount Rate"
+msgstr ""
+
+msgctxt "field:sale.opportunity_employee,conversion_rate:"
+msgid "Conversion Rate"
+msgstr ""
+
+#, fuzzy
+msgctxt "field:sale.opportunity_employee,converted:"
+msgid "Converted"
+msgstr "Converted"
+
+msgctxt "field:sale.opportunity_employee,converted_amount:"
+msgid "Converted Amount"
+msgstr ""
+
+msgctxt "field:sale.opportunity_employee,currency:"
+msgid "Currency"
+msgstr ""
+
+msgctxt "field:sale.opportunity_employee,currency_digits:"
+msgid "Currency Digits"
+msgstr ""
+
+msgctxt "field:sale.opportunity_employee,employee:"
+msgid "Employee"
+msgstr ""
+
+#, fuzzy
+msgctxt "field:sale.opportunity_employee,lost:"
+msgid "Lost"
+msgstr "Lost"
+
+msgctxt "field:sale.opportunity_employee,number:"
+msgid "Number"
+msgstr ""
+
+msgctxt "field:sale.opportunity_employee,winning_amount_rate:"
+msgid "Winning Amount Rate"
+msgstr ""
+
+msgctxt "field:sale.opportunity_employee,winning_rate:"
+msgid "Winning Rate"
+msgstr ""
+
+#, fuzzy
+msgctxt "field:sale.opportunity_employee,won:"
+msgid "Won"
+msgstr "圆"
+
+msgctxt "field:sale.opportunity_employee,won_amount:"
+msgid "Won Amount"
+msgstr ""
+
+msgctxt "field:sale.opportunity_employee.context,end_date:"
+msgid "End Date"
+msgstr ""
+
+msgctxt "field:sale.opportunity_employee.context,start_date:"
+msgid "Start Date"
+msgstr ""
+
+msgctxt "field:sale.opportunity_employee_monthly,amount:"
+msgid "Amount"
+msgstr ""
+
+msgctxt "field:sale.opportunity_employee_monthly,company:"
+msgid "Company"
+msgstr ""
+
+msgctxt "field:sale.opportunity_employee_monthly,conversion_amount_rate:"
+msgid "Conversion Amount Rate"
+msgstr ""
+
+msgctxt "field:sale.opportunity_employee_monthly,conversion_rate:"
+msgid "Conversion Rate"
+msgstr ""
+
+#, fuzzy
+msgctxt "field:sale.opportunity_employee_monthly,converted:"
+msgid "Converted"
+msgstr "Converted"
+
+msgctxt "field:sale.opportunity_employee_monthly,converted_amount:"
+msgid "Converted Amount"
+msgstr ""
+
+msgctxt "field:sale.opportunity_employee_monthly,currency:"
+msgid "Currency"
+msgstr ""
+
+msgctxt "field:sale.opportunity_employee_monthly,currency_digits:"
+msgid "Currency Digits"
+msgstr ""
+
+msgctxt "field:sale.opportunity_employee_monthly,employee:"
+msgid "Employee"
+msgstr ""
+
+#, fuzzy
+msgctxt "field:sale.opportunity_employee_monthly,lost:"
+msgid "Lost"
+msgstr "Lost"
+
+msgctxt "field:sale.opportunity_employee_monthly,month:"
+msgid "Month"
+msgstr ""
+
+msgctxt "field:sale.opportunity_employee_monthly,number:"
+msgid "Number"
+msgstr ""
+
+msgctxt "field:sale.opportunity_employee_monthly,winning_amount_rate:"
+msgid "Winning Amount Rate"
+msgstr ""
+
+msgctxt "field:sale.opportunity_employee_monthly,winning_rate:"
+msgid "Winning Rate"
+msgstr ""
+
+#, fuzzy
+msgctxt "field:sale.opportunity_employee_monthly,won:"
+msgid "Won"
+msgstr "圆"
+
+msgctxt "field:sale.opportunity_employee_monthly,won_amount:"
+msgid "Won Amount"
+msgstr ""
+
+msgctxt "field:sale.opportunity_employee_monthly,year:"
+msgid "Year"
+msgstr ""
+
+msgctxt "field:sale.opportunity_monthly,amount:"
+msgid "Amount"
+msgstr ""
+
+msgctxt "field:sale.opportunity_monthly,company:"
+msgid "Company"
+msgstr ""
+
+msgctxt "field:sale.opportunity_monthly,conversion_amount_rate:"
+msgid "Conversion Amount Rate"
+msgstr ""
+
+msgctxt "field:sale.opportunity_monthly,conversion_rate:"
+msgid "Conversion Rate"
+msgstr ""
+
+#, fuzzy
+msgctxt "field:sale.opportunity_monthly,converted:"
+msgid "Converted"
+msgstr "Converted"
+
+msgctxt "field:sale.opportunity_monthly,converted_amount:"
+msgid "Converted Amount"
+msgstr ""
+
+msgctxt "field:sale.opportunity_monthly,currency:"
+msgid "Currency"
+msgstr ""
+
+msgctxt "field:sale.opportunity_monthly,currency_digits:"
+msgid "Currency Digits"
+msgstr ""
+
+#, fuzzy
+msgctxt "field:sale.opportunity_monthly,lost:"
+msgid "Lost"
+msgstr "Lost"
+
+msgctxt "field:sale.opportunity_monthly,month:"
+msgid "Month"
+msgstr ""
+
+msgctxt "field:sale.opportunity_monthly,number:"
+msgid "Number"
+msgstr ""
+
+msgctxt "field:sale.opportunity_monthly,winning_amount_rate:"
+msgid "Winning Amount Rate"
+msgstr ""
+
+msgctxt "field:sale.opportunity_monthly,winning_rate:"
+msgid "Winning Rate"
+msgstr ""
+
+#, fuzzy
+msgctxt "field:sale.opportunity_monthly,won:"
+msgid "Won"
+msgstr "圆"
+
+msgctxt "field:sale.opportunity_monthly,won_amount:"
+msgid "Won Amount"
+msgstr ""
+
+msgctxt "field:sale.opportunity_monthly,year:"
+msgid "Year"
+msgstr ""
+
+msgctxt "field:sale.opportunity_monthly,year_month:"
+msgid "Year-Month"
+msgstr ""
+
+msgctxt "help:sale.opportunity,amount:"
+msgid "Estimated revenue amount."
+msgstr ""
+
+msgctxt "help:sale.opportunity,conversion_probability:"
+msgid "Percentage between 0 and 100."
+msgstr ""
+
+msgctxt "model:ir.action,name:act_open_sale_form"
+msgid "Sales"
+msgstr "Sales"
+
+msgctxt "model:ir.action,name:act_opportunity_employee_form"
+msgid "Opportunities per Employee"
+msgstr "Opportunities per Employee"
+
+msgctxt "model:ir.action,name:act_opportunity_employee_monthly_form"
+msgid "Opportunities per Employee per Month"
+msgstr "Opportunities per Employee per Month"
+
+msgctxt "model:ir.action,name:act_opportunity_form"
+msgid "Leads and Opportunities"
+msgstr "Leads and Opportunities"
+
+msgctxt "model:ir.action,name:act_opportunity_form2"
+msgid "Sales Leads/Opportunities"
+msgstr "Sales Leads/Opportunities"
+
+msgctxt "model:ir.action,name:act_opportunity_monthly_form"
+msgid "Opportunities per Month"
+msgstr "Opportunities per Month"
+
+#, fuzzy
+msgctxt ""
+"model:ir.action.act_window.domain,name:act_opportunity_form_domain_all"
+msgid "All"
+msgstr "全部"
+
+msgctxt ""
+"model:ir.action.act_window.domain,name:act_opportunity_form_domain_cancelled"
+msgid "Cancelled"
+msgstr "Cancelled"
+
+msgctxt ""
+"model:ir.action.act_window.domain,name:act_opportunity_form_domain_converted"
+msgid "Converted"
+msgstr "Converted"
+
+msgctxt ""
+"model:ir.action.act_window.domain,name:act_opportunity_form_domain_leads"
+msgid "Leads"
+msgstr "Leads"
+
+msgctxt ""
+"model:ir.action.act_window.domain,name:act_opportunity_form_domain_lost"
+msgid "Lost"
+msgstr "Lost"
+
+msgctxt ""
+"model:ir.action.act_window.domain,name:act_opportunity_form_domain_opportunities"
+msgid "Opportunities"
+msgstr "Opportunities"
+
+#, fuzzy
+msgctxt ""
+"model:ir.action.act_window.domain,name:act_opportunity_form_domain_won"
+msgid "Won"
+msgstr "圆"
+
+msgctxt "model:ir.message,text:msg_modify_origin_opportunity"
+msgid "You cannot modify the opportunity origin of the sale \"%(sale)s\"."
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_opportunity_delete_cancel"
+msgid "To delete opportunity \"%(opportunity)s\", you must cancel it."
+msgstr ""
+
+msgctxt "model:ir.model.button,string:opportunity_cancel_button"
+msgid "Cancel"
+msgstr "Cancel"
+
+msgctxt "model:ir.model.button,string:opportunity_convert_button"
+msgid "Convert to Sale"
+msgstr "Convert to Sale"
+
+msgctxt "model:ir.model.button,string:opportunity_lead_button"
+msgid "Set as Lead"
+msgstr "Set as Lead"
+
+msgctxt "model:ir.model.button,string:opportunity_lost_button"
+msgid "Mark as Lost"
+msgstr "Mark as Lost"
+
+msgctxt "model:ir.model.button,string:opportunity_opportunity_button"
+msgid "Convert to Opportunity"
+msgstr "Convert to Opportunity"
+
+msgctxt "model:ir.rule.group,name:rule_group_opportunity_companies"
+msgid "User in companies"
+msgstr ""
+
+msgctxt "model:ir.rule.group,name:rule_group_opportunity_employee_companies"
+msgid "User in companies"
+msgstr ""
+
+msgctxt ""
+"model:ir.rule.group,name:rule_group_opportunity_employee_monthly_companies"
+msgid "User in companies"
+msgstr ""
+
+msgctxt "model:ir.rule.group,name:rule_group_opportunity_monthly_companies"
+msgid "User in companies"
+msgstr ""
+
+msgctxt "model:ir.sequence,name:sequence_sale_opportunity"
+msgid "Sale Opportunity"
+msgstr "Sale Opportunity"
+
+msgctxt "model:ir.sequence.type,name:sequence_type_sale_opportunity"
+msgid "Sale Opportunity"
+msgstr "Sale Opportunity"
+
+msgctxt "model:ir.ui.menu,name:menu_opportunity_employee_monthly_form"
+msgid "Opportunities per Employee per Month"
+msgstr "Opportunities per Employee per Month"
+
+msgctxt "model:ir.ui.menu,name:menu_opportunity_employee_open"
+msgid "Opportunities per Employee"
+msgstr "Opportunities per Employee"
+
+msgctxt "model:ir.ui.menu,name:menu_opportunity_form"
+msgid "Leads and Opportunities"
+msgstr "Leads and Opportunities"
+
+msgctxt "model:ir.ui.menu,name:menu_opportunity_monthly_form"
+msgid "Opportunities per Month"
+msgstr "Opportunities per Month"
+
+msgctxt "model:res.group,name:group_opportunity"
+msgid "Sale Opportunity"
+msgstr "Sale Opportunity"
+
+#, fuzzy
+msgctxt "model:sale.opportunity,name:"
+msgid "Sale Opportunity"
+msgstr "Sale Opportunity"
+
+#, fuzzy
+msgctxt "model:sale.opportunity.line,name:"
+msgid "Sale Opportunity Line"
+msgstr "Sale Opportunity"
+
+#, fuzzy
+msgctxt "model:sale.opportunity_employee,name:"
+msgid "Sale Opportunity per Employee"
+msgstr "Opportunities per Employee per Month"
+
+#, fuzzy
+msgctxt "model:sale.opportunity_employee.context,name:"
+msgid "Sale Opportunity per Employee Context"
+msgstr "Opportunities per Employee per Month"
+
+#, fuzzy
+msgctxt "model:sale.opportunity_employee_monthly,name:"
+msgid "Sale Opportunity per Employee per Month"
+msgstr "Opportunities per Employee per Month"
+
+#, fuzzy
+msgctxt "model:sale.opportunity_monthly,name:"
+msgid "Sale Opportunity per Month"
+msgstr "Opportunities per Employee per Month"
+
+#, fuzzy
+msgctxt "selection:sale.opportunity,state:"
+msgid "Cancelled"
+msgstr "Cancelled"
+
+#, fuzzy
+msgctxt "selection:sale.opportunity,state:"
+msgid "Converted"
+msgstr "Converted"
+
+#, fuzzy
+msgctxt "selection:sale.opportunity,state:"
+msgid "Lead"
+msgstr "Leads"
+
+#, fuzzy
+msgctxt "selection:sale.opportunity,state:"
+msgid "Lost"
+msgstr "Lost"
+
+#, fuzzy
+msgctxt "selection:sale.opportunity,state:"
+msgid "Opportunity"
+msgstr "Opportunities"
+
+#, fuzzy
+msgctxt "selection:sale.opportunity,state:"
+msgid "Won"
+msgstr "圆"
+
+#, fuzzy
+msgctxt "view:sale.opportunity:"
+msgid "%"
+msgstr "%"
+
+msgctxt "view:sale.opportunity:"
+msgid "Lead/Opportunity"
+msgstr ""
+
+#, fuzzy
+msgctxt "view:sale.opportunity_employee:"
+msgid "%"
+msgstr "%"
+
+#, fuzzy
+msgctxt "view:sale.opportunity_employee_monthly:"
+msgid "%"
+msgstr "%"
+
+#, fuzzy
+msgctxt "view:sale.opportunity_monthly:"
+msgid "%"
+msgstr "%"
diff --git a/modules/sale_opportunity/message.xml b/modules/sale_opportunity/message.xml
new file mode 100644
index 0000000000..6f493980b5
--- /dev/null
+++ b/modules/sale_opportunity/message.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+ To delete opportunity "%(opportunity)s", you must cancel it.
+
+
+ You cannot modify the opportunity origin of the sale "%(sale)s".
+
+
+
diff --git a/modules/sale_opportunity/opportunity.py b/modules/sale_opportunity/opportunity.py
new file mode 100644
index 0000000000..5362f9bf43
--- /dev/null
+++ b/modules/sale_opportunity/opportunity.py
@@ -0,0 +1,797 @@
+# This file is part of Tryton. The COPYRIGHT file at the top level of
+# this repository contains the full copyright notices and license terms.
+"Sales extension for managing leads and opportunities"
+import datetime
+
+from sql import Literal, Null
+from sql.aggregate import Max, Count, Sum
+from sql.conditionals import Case, Coalesce
+from sql.functions import Extract
+
+from trytond.i18n import gettext
+from trytond.model import ModelView, ModelSQL, Workflow, fields, \
+ sequence_ordered
+from trytond.model.exceptions import AccessError
+from trytond.pyson import Eval, In, If, Get, Bool
+from trytond.transaction import Transaction
+from trytond.pool import Pool
+
+from trytond.ir.attachment import AttachmentCopyMixin
+from trytond.ir.note import NoteCopyMixin
+from trytond.modules.company.model import employee_field, set_employee
+
+
+class SaleOpportunity(
+ Workflow, ModelSQL, ModelView,
+ AttachmentCopyMixin, NoteCopyMixin):
+ 'Sale Opportunity'
+ __name__ = "sale.opportunity"
+ _history = True
+ _rec_name = 'number'
+
+ _states_start = {
+ 'readonly': Eval('state') != 'lead',
+ }
+ _depends_start = ['state']
+ _states_stop = {
+ 'readonly': Eval('state').in_(
+ ['converted', 'won', 'lost', 'cancelled']),
+ }
+ _depends_stop = ['state']
+
+ number = fields.Char('Number', readonly=True, required=True, select=True)
+ reference = fields.Char('Reference', select=True)
+ party = fields.Many2One(
+ 'party.party', "Party", select=True,
+ states={
+ 'readonly': Eval('state').in_(['converted', 'lost', 'cancelled']),
+ 'required': ~Eval('state').in_(['lead', 'lost', 'cancelled']),
+ },
+ context={
+ 'company': Eval('company', -1),
+ },
+ depends=['state', 'company'])
+ contact = fields.Many2One(
+ 'party.contact_mechanism', "Contact",
+ context={
+ 'company': Eval('company', -1),
+ },
+ search_context={
+ 'related_party': Eval('party'),
+ },
+ depends=['party', 'company'])
+ address = fields.Many2One('party.address', 'Address',
+ domain=[('party', '=', Eval('party'))],
+ select=True, depends=['party', 'state'],
+ states=_states_stop)
+ company = fields.Many2One('company.company', 'Company', required=True,
+ select=True,
+ states={
+ 'readonly': _states_stop['readonly'] | Eval('party', True),
+ },
+ domain=[
+ ('id', If(In('company', Eval('context', {})), '=', '!='),
+ Get(Eval('context', {}), 'company', 0)),
+ ],
+ depends=_depends_stop)
+ currency = fields.Function(fields.Many2One('currency.currency',
+ 'Currency'), 'get_currency')
+ currency_digits = fields.Function(fields.Integer('Currency Digits'),
+ 'get_currency_digits')
+ amount = fields.Numeric('Amount', digits=(16, Eval('currency_digits', 2)),
+ states=_states_stop, depends=_depends_stop + ['currency_digits'],
+ help='Estimated revenue amount.')
+ payment_term = fields.Many2One('account.invoice.payment_term',
+ 'Payment Term', states={
+ 'readonly': In(Eval('state'),
+ ['converted', 'lost', 'cancelled']),
+ },
+ depends=['state'])
+ employee = fields.Many2One('company.employee', 'Employee',
+ states={
+ 'readonly': _states_stop['readonly'],
+ 'required': ~Eval('state').in_(['lead', 'lost', 'cancelled']),
+ },
+ depends=['state', 'company'],
+ domain=[('company', '=', Eval('company'))])
+ start_date = fields.Date('Start Date', required=True, select=True,
+ states=_states_start, depends=_depends_start)
+ end_date = fields.Date('End Date', select=True,
+ states=_states_stop, depends=_depends_stop)
+ description = fields.Char('Description',
+ states=_states_stop, depends=_depends_stop)
+ comment = fields.Text('Comment', states=_states_stop,
+ depends=_depends_stop)
+ lines = fields.One2Many('sale.opportunity.line', 'opportunity', 'Lines',
+ states=_states_stop, depends=_depends_stop)
+ conversion_probability = fields.Float('Conversion Probability',
+ digits=(1, 4), required=True,
+ domain=[
+ ('conversion_probability', '>=', 0),
+ ('conversion_probability', '<=', 1),
+ ],
+ states={
+ 'readonly': ~Eval('state').in_(
+ ['opportunity', 'lead', 'converted']),
+ },
+ depends=['state'], help="Percentage between 0 and 100.")
+ lost_reason = fields.Text('Reason for loss', states={
+ 'invisible': Eval('state') != 'lost',
+ }, depends=['state'])
+ sales = fields.One2Many('sale.sale', 'origin', 'Sales')
+
+ converted_by = employee_field(
+ "Converted By", states=['converted', 'won', 'lost', 'cancelled'])
+ state = fields.Selection([
+ ('lead', "Lead"),
+ ('opportunity', "Opportunity"),
+ ('converted', "Converted"),
+ ('won', "Won"),
+ ('cancelled', "Cancelled"),
+ ('lost', "Lost"),
+ ], "State", required=True, select=True,
+ sort=False, readonly=True)
+
+ del _states_start, _depends_start
+ del _states_stop, _depends_stop
+
+ @classmethod
+ def __register__(cls, module_name):
+ pool = Pool()
+ Sale = pool.get('sale.sale')
+ transaction = Transaction()
+ cursor = transaction.connection.cursor()
+ update = transaction.connection.cursor()
+ sql_table = cls.__table__()
+ sale = Sale.__table__()
+
+ table = cls.__table_handler__(module_name)
+ number_exists = table.column_exist('number')
+
+ # Migration from 3.8: rename reference into number
+ if table.column_exist('reference') and not number_exists:
+ table.column_rename('reference', 'number')
+ number_exists = True
+
+ super(SaleOpportunity, cls).__register__(module_name)
+ table = cls.__table_handler__(module_name)
+
+ # Migration from 3.4: replace sale by origin
+ if table.column_exist('sale'):
+ cursor.execute(*sql_table.select(
+ sql_table.id, sql_table.sale,
+ where=sql_table.sale != Null))
+ for id_, sale_id in cursor:
+ update.execute(*sale.update(
+ columns=[sale.origin],
+ values=['%s,%s' % (cls.__name__, id_)],
+ where=sale.id == sale_id))
+ table.drop_column('sale')
+
+ # Migration from 4.0: change probability into conversion probability
+ if table.column_exist('probability'):
+ cursor.execute(*sql_table.update(
+ [sql_table.conversion_probability],
+ [sql_table.probability / 100.0]))
+ table.drop_constraint('check_percentage')
+ table.drop_column('probability')
+
+ # Migration from 4.2: make employee not required
+ table.not_null_action('employee', action='remove')
+
+ # Migration from 5.0: drop required on description
+ table.not_null_action('description', action='remove')
+
+ @classmethod
+ def __setup__(cls):
+ super(SaleOpportunity, cls).__setup__()
+ cls._order.insert(0, ('start_date', 'DESC'))
+ cls._transitions |= set((
+ ('lead', 'opportunity'),
+ ('lead', 'lost'),
+ ('lead', 'cancelled'),
+ ('lead', 'converted'),
+ ('opportunity', 'converted'),
+ ('opportunity', 'lead'),
+ ('opportunity', 'lost'),
+ ('opportunity', 'cancelled'),
+ ('converted', 'won'),
+ ('converted', 'lost'),
+ ('won', 'converted'),
+ ('lost', 'converted'),
+ ('lost', 'lead'),
+ ('cancelled', 'lead'),
+ ))
+ cls._buttons.update({
+ 'lead': {
+ 'invisible': ~Eval('state').in_(
+ ['cancelled', 'lost', 'opportunity']),
+ 'icon': If(Eval('state').in_(['cancelled', 'lost']),
+ 'tryton-undo', 'tryton-back'),
+ 'depends': ['state'],
+ },
+ 'opportunity': {
+ 'invisible': ~Eval('state').in_(['lead']),
+ 'depends': ['state'],
+ },
+ 'convert': {
+ 'invisible': ~Eval('state').in_(['opportunity']),
+ 'depends': ['state'],
+ },
+ 'lost': {
+ 'invisible': ~Eval('state').in_(['lead', 'opportunity']),
+ 'depends': ['state'],
+ },
+ 'cancel': {
+ 'invisible': ~Eval('state').in_(['lead', 'opportunity']),
+ 'depends': ['state'],
+ },
+ })
+
+ @staticmethod
+ def default_state():
+ return 'lead'
+
+ @staticmethod
+ def default_start_date():
+ Date = Pool().get('ir.date')
+ return Date.today()
+
+ @staticmethod
+ def default_conversion_probability():
+ return 0.5
+
+ @staticmethod
+ def default_company():
+ return Transaction().context.get('company')
+
+ @staticmethod
+ def default_employee():
+ return Transaction().context.get('employee')
+
+ @classmethod
+ def default_payment_term(cls):
+ PaymentTerm = Pool().get('account.invoice.payment_term')
+ payment_terms = PaymentTerm.search(cls.payment_term.domain)
+ if len(payment_terms) == 1:
+ return payment_terms[0].id
+
+ @classmethod
+ def view_attributes(cls):
+ return super().view_attributes() + [
+ ('/tree', 'visual', If(Eval('state') == 'cancelled', 'muted', '')),
+ ]
+
+ @classmethod
+ def get_resources_to_copy(cls, name):
+ return {
+ 'sale.sale',
+ }
+
+ @classmethod
+ def create(cls, vlist):
+ pool = Pool()
+ Config = pool.get('sale.configuration')
+
+ config = Config(1)
+ vlist = [x.copy() for x in vlist]
+ default_company = cls.default_company()
+ for vals in vlist:
+ if vals.get('number') is None:
+ vals['number'] = config.get_multivalue(
+ 'sale_opportunity_sequence',
+ company=vals.get('company', default_company)).get()
+ return super(SaleOpportunity, cls).create(vlist)
+
+ @classmethod
+ def copy(cls, opportunities, default=None):
+ if default is None:
+ default = {}
+ else:
+ default = default.copy()
+ default.setdefault('number', None)
+ default.setdefault('sales', None)
+ default.setdefault('converted_by')
+ return super(SaleOpportunity, cls).copy(opportunities, default=default)
+
+ def get_currency(self, name):
+ return self.company.currency.id
+
+ def get_currency_digits(self, name):
+ return self.company.currency.digits
+
+ @fields.depends('company')
+ def on_change_company(self):
+ if self.company:
+ self.currency = self.company.currency
+ self.currency_digits = self.company.currency.digits
+
+ @fields.depends('party')
+ def on_change_party(self):
+ if self.party and self.party.customer_payment_term:
+ self.payment_term = self.party.customer_payment_term
+ else:
+ self.payment_term = self.default_payment_term()
+
+ def _get_sale_opportunity(self):
+ '''
+ Return sale for an opportunity
+ '''
+ Sale = Pool().get('sale.sale')
+ return Sale(
+ description=self.description,
+ party=self.party,
+ contact=self.contact,
+ payment_term=self.payment_term,
+ company=self.company,
+ invoice_address=self.address,
+ shipment_address=self.address,
+ currency=self.company.currency,
+ comment=self.comment,
+ sale_date=None,
+ origin=self,
+ warehouse=Sale.default_warehouse(),
+ )
+
+ def create_sale(self):
+ '''
+ Create a sale for the opportunity and return the sale
+ '''
+ sale = self._get_sale_opportunity()
+ sale_lines = []
+ for line in self.lines:
+ sale_lines.append(line.get_sale_line(sale))
+ sale.lines = sale_lines
+ return sale
+
+ @classmethod
+ def delete(cls, opportunities):
+ # Cancel before delete
+ cls.cancel(opportunities)
+ for opportunity in opportunities:
+ if opportunity.state != 'cancelled':
+ raise AccessError(
+ gettext('sale_opportunity.msg_opportunity_delete_cancel',
+ opportunity=opportunity.rec_name))
+ super(SaleOpportunity, cls).delete(opportunities)
+
+ @classmethod
+ @ModelView.button
+ @Workflow.transition('lead')
+ def lead(cls, opportunities):
+ pass
+
+ @classmethod
+ @ModelView.button
+ @Workflow.transition('opportunity')
+ def opportunity(cls, opportunities):
+ pass
+
+ @classmethod
+ @ModelView.button
+ @Workflow.transition('converted')
+ @set_employee('converted_by')
+ def convert(cls, opportunities):
+ pool = Pool()
+ Sale = pool.get('sale.sale')
+ sales = [o.create_sale() for o in opportunities if not o.sales]
+ Sale.save(sales)
+ for sale in sales:
+ sale.origin.copy_resources_to(sale)
+
+ @property
+ def is_forecast(self):
+ pool = Pool()
+ Date = pool.get('ir.date')
+ today = Date.today()
+ return self.end_date or datetime.date.max > today
+
+ @classmethod
+ @Workflow.transition('won')
+ def won(cls, opportunities):
+ pool = Pool()
+ Date = pool.get('ir.date')
+ cls.write([o for o in opportunities if o.is_forecast], {
+ 'end_date': Date.today(),
+ 'state': 'won',
+ })
+
+ @classmethod
+ @ModelView.button
+ @Workflow.transition('lost')
+ def lost(cls, opportunities):
+ Date = Pool().get('ir.date')
+ cls.write([o for o in opportunities if o.is_forecast], {
+ 'end_date': Date.today(),
+ 'state': 'lost',
+ })
+
+ @classmethod
+ @ModelView.button
+ @Workflow.transition('cancelled')
+ def cancel(cls, opportunities):
+ Date = Pool().get('ir.date')
+ cls.write([o for o in opportunities if o.is_forecast], {
+ 'end_date': Date.today(),
+ })
+
+ @staticmethod
+ def _sale_won_states():
+ return ['confirmed', 'processing', 'done']
+
+ @staticmethod
+ def _sale_lost_states():
+ return ['cancelled']
+
+ def is_won(self):
+ sale_won_states = self._sale_won_states()
+ sale_lost_states = self._sale_lost_states()
+ end_states = sale_won_states + sale_lost_states
+ return (self.sales
+ and all(s.state in end_states for s in self.sales)
+ and any(s.state in sale_won_states for s in self.sales))
+
+ def is_lost(self):
+ sale_lost_states = self._sale_lost_states()
+ return (self.sales
+ and all(s.state in sale_lost_states for s in self.sales))
+
+ @property
+ def sale_amount(self):
+ pool = Pool()
+ Currency = pool.get('currency.currency')
+
+ if not self.sales:
+ return
+
+ sale_lost_states = self._sale_lost_states()
+ amount = 0
+ for sale in self.sales:
+ if sale.state not in sale_lost_states:
+ amount += Currency.compute(sale.currency, sale.untaxed_amount,
+ self.currency)
+ return amount
+
+ @classmethod
+ def process(cls, opportunities):
+ won = []
+ lost = []
+ converted = []
+ for opportunity in opportunities:
+ sale_amount = opportunity.sale_amount
+ if opportunity.amount != sale_amount:
+ opportunity.amount = sale_amount
+ if opportunity.is_won():
+ won.append(opportunity)
+ elif opportunity.is_lost():
+ lost.append(opportunity)
+ elif (opportunity.state != 'converted'
+ and opportunity.sales):
+ converted.append(opportunity)
+ cls.save(opportunities)
+ if won:
+ cls.won(won)
+ if lost:
+ cls.lost(lost)
+ if converted:
+ cls.convert(converted)
+
+
+class SaleOpportunityLine(sequence_ordered(), ModelSQL, ModelView):
+ 'Sale Opportunity Line'
+ __name__ = "sale.opportunity.line"
+ _history = True
+ _states = {
+ 'readonly': Eval('opportunity_state').in_(
+ ['converted', 'won', 'lost', 'cancelled']),
+ }
+ _depends = ['opportunity_state']
+
+ opportunity = fields.Many2One('sale.opportunity', 'Opportunity',
+ ondelete='CASCADE', select=True, required=True,
+ states={
+ 'readonly': _states['readonly'] & Bool(Eval('opportunity')),
+ },
+ depends=_depends)
+ opportunity_state = fields.Function(
+ fields.Selection('get_opportunity_states', "Opportunity State"),
+ 'on_change_with_opportunity_state')
+ product = fields.Many2One('product.product', 'Product', required=True,
+ domain=[('salable', '=', True)], states=_states, depends=_depends)
+ quantity = fields.Float('Quantity', required=True,
+ digits=(16, Eval('unit_digits', 2)),
+ states=_states, depends=['unit_digits'] + _depends)
+ unit = fields.Many2One('product.uom', 'Unit', required=True,
+ states=_states, depends=_depends)
+ unit_digits = fields.Function(fields.Integer('Unit Digits'),
+ 'on_change_with_unit_digits')
+
+ del _states, _depends
+
+ @classmethod
+ def __setup__(cls):
+ super().__setup__()
+ cls.__access__.add('opportunity')
+
+ @classmethod
+ def get_opportunity_states(cls):
+ pool = Pool()
+ Opportunity = pool.get('sale.opportunity')
+ return Opportunity.fields_get(['state'])['state']['selection']
+
+ @fields.depends('opportunity', '_parent_opportunity.state')
+ def on_change_with_opportunity_state(self, name=None):
+ if self.opportunity:
+ return self.opportunity.state
+
+ @fields.depends('unit')
+ def on_change_with_unit_digits(self, name=None):
+ if self.unit:
+ return self.unit.digits
+ return 2
+
+ @fields.depends('product', 'unit')
+ def on_change_product(self):
+ if not self.product:
+ return
+
+ category = self.product.sale_uom.category
+ if not self.unit or self.unit.category != category:
+ self.unit = self.product.sale_uom
+ self.unit_digits = self.product.sale_uom.digits
+
+ def get_sale_line(self, sale):
+ '''
+ Return sale line for opportunity line
+ '''
+ SaleLine = Pool().get('sale.line')
+ sale_line = SaleLine(
+ type='line',
+ product=self.product,
+ sale=sale,
+ description=None,
+ )
+ sale_line.on_change_product()
+ self._set_sale_line_quantity(sale_line)
+ sale_line.on_change_quantity()
+ return sale_line
+
+ def _set_sale_line_quantity(self, sale_line):
+ sale_line.quantity = self.quantity
+ sale_line.unit = self.unit
+
+ def get_rec_name(self, name):
+ pool = Pool()
+ Lang = pool.get('ir.lang')
+ lang = Lang.get()
+ return (lang.format(
+ '%.*f', (self.unit.digits, self.quantity or 0))
+ + '%s %s @ %s' % (
+ self.unit.symbol, self.product.rec_name,
+ self.opportunity.rec_name))
+
+ @classmethod
+ def search_rec_name(cls, name, clause):
+ return [('product.rec_name',) + tuple(clause[1:])]
+
+
+class SaleOpportunityReportMixin:
+ __slots__ = ()
+ number = fields.Integer('Number')
+ converted = fields.Integer('Converted')
+ conversion_rate = fields.Function(fields.Float('Conversion Rate',
+ digits=(1, 4)), 'get_conversion_rate')
+ won = fields.Integer('Won')
+ winning_rate = fields.Function(fields.Float('Winning Rate', digits=(1, 4)),
+ 'get_winning_rate')
+ lost = fields.Integer('Lost')
+ company = fields.Many2One('company.company', 'Company')
+ currency = fields.Function(fields.Many2One('currency.currency',
+ 'Currency'), 'get_currency')
+ currency_digits = fields.Function(fields.Integer('Currency Digits'),
+ 'get_currency_digits')
+ amount = fields.Numeric('Amount', digits=(16, Eval('currency_digits', 2)),
+ depends=['currency_digits'])
+ converted_amount = fields.Numeric('Converted Amount',
+ digits=(16, Eval('currency_digits', 2)),
+ depends=['currency_digits'])
+ conversion_amount_rate = fields.Function(fields.Float(
+ 'Conversion Amount Rate', digits=(1, 4)), 'get_conversion_amount_rate')
+ won_amount = fields.Numeric('Won Amount',
+ digits=(16, Eval('currency_digits', 2)),
+ depends=['currency_digits'])
+ winning_amount_rate = fields.Function(fields.Float(
+ 'Winning Amount Rate', digits=(1, 4)), 'get_winning_amount_rate')
+
+ @staticmethod
+ def _converted_state():
+ return ['converted', 'won']
+
+ @staticmethod
+ def _won_state():
+ return ['won']
+
+ @staticmethod
+ def _lost_state():
+ return ['lost']
+
+ def get_conversion_rate(self, name):
+ if self.number:
+ digits = getattr(self.__class__, name).digits[1]
+ return round(float(self.converted) / self.number, digits)
+ else:
+ return 0.0
+
+ def get_winning_rate(self, name):
+ if self.number:
+ digits = getattr(self.__class__, name).digits[1]
+ return round(float(self.won) / self.number, digits)
+ else:
+ return 0.0
+
+ def get_currency(self, name):
+ return self.company.currency.id
+
+ def get_currency_digits(self, name):
+ return self.company.currency.digits
+
+ def get_conversion_amount_rate(self, name):
+ if self.amount:
+ digits = getattr(self.__class__, name).digits[1]
+ return round(
+ float(self.converted_amount) / float(self.amount), digits)
+ else:
+ return 0.0
+
+ def get_winning_amount_rate(self, name):
+ if self.amount:
+ digits = getattr(self.__class__, name).digits[1]
+ return round(float(self.won_amount) / float(self.amount), digits)
+ else:
+ return 0.0
+
+ @classmethod
+ def table_query(cls):
+ Opportunity = Pool().get('sale.opportunity')
+ opportunity = Opportunity.__table__()
+ return opportunity.select(
+ Max(opportunity.create_uid).as_('create_uid'),
+ Max(opportunity.create_date).as_('create_date'),
+ Max(opportunity.write_uid).as_('write_uid'),
+ Max(opportunity.write_date).as_('write_date'),
+ opportunity.company,
+ Count(Literal(1)).as_('number'),
+ Sum(Case(
+ (opportunity.state.in_(cls._converted_state()),
+ Literal(1)), else_=Literal(0))).as_('converted'),
+ Sum(Case(
+ (opportunity.state.in_(cls._won_state()),
+ Literal(1)), else_=Literal(0))).as_('won'),
+ Sum(Case(
+ (opportunity.state.in_(cls._lost_state()),
+ Literal(1)), else_=Literal(0))).as_('lost'),
+ Sum(opportunity.amount).as_('amount'),
+ Sum(Case(
+ (opportunity.state.in_(cls._converted_state()),
+ opportunity.amount),
+ else_=Literal(0))).as_('converted_amount'),
+ Sum(Case(
+ (opportunity.state.in_(cls._won_state()),
+ opportunity.amount),
+ else_=Literal(0))).as_('won_amount'))
+
+
+class SaleOpportunityEmployee(SaleOpportunityReportMixin, ModelSQL, ModelView):
+ 'Sale Opportunity per Employee'
+ __name__ = 'sale.opportunity_employee'
+ employee = fields.Many2One('company.employee', 'Employee')
+
+ @classmethod
+ def table_query(cls):
+ query = super(SaleOpportunityEmployee, cls).table_query()
+ opportunity, = query.from_
+ query.columns += (
+ Coalesce(opportunity.employee, 0).as_('id'),
+ opportunity.employee,
+ )
+ where = Literal(True)
+ if Transaction().context.get('start_date'):
+ where &= (opportunity.start_date
+ >= Transaction().context['start_date'])
+ if Transaction().context.get('end_date'):
+ where &= (opportunity.start_date
+ <= Transaction().context['end_date'])
+ query.where = where
+ query.group_by = (opportunity.employee, opportunity.company)
+ return query
+
+
+class SaleOpportunityEmployeeContext(ModelView):
+ 'Sale Opportunity per Employee Context'
+ __name__ = 'sale.opportunity_employee.context'
+ start_date = fields.Date('Start Date')
+ end_date = fields.Date('End Date')
+
+
+class SaleOpportunityMonthly(SaleOpportunityReportMixin, ModelSQL, ModelView):
+ 'Sale Opportunity per Month'
+ __name__ = 'sale.opportunity_monthly'
+ year = fields.Char('Year')
+ month = fields.Many2One('ir.calendar.month', "Month")
+ year_month = fields.Function(fields.Char('Year-Month'),
+ 'get_year_month')
+
+ @classmethod
+ def __setup__(cls):
+ super(SaleOpportunityMonthly, cls).__setup__()
+ cls._order.insert(0, ('year', 'DESC'))
+ cls._order.insert(1, ('month.index', 'DESC'))
+
+ def get_year_month(self, name):
+ return '%s-%s' % (self.year, self.month.index)
+
+ @classmethod
+ def table_query(cls):
+ pool = Pool()
+ Month = pool.get('ir.calendar.month')
+ month = Month.__table__()
+ query = super(SaleOpportunityMonthly, cls).table_query()
+ opportunity, = query.from_
+ type_id = cls.id.sql_type().base
+ type_year = cls.year.sql_type().base
+ year_column = Extract('YEAR', opportunity.start_date
+ ).cast(type_year).as_('year')
+ month_index = Extract('MONTH', opportunity.start_date)
+ query.from_ = opportunity.join(
+ month, condition=month_index == month.index)
+ query.columns += (
+ Max(Extract('MONTH', opportunity.start_date)
+ + Extract('YEAR', opportunity.start_date) * 100
+ ).cast(type_id).as_('id'),
+ year_column,
+ month.id.as_('month'))
+ query.group_by = (year_column, month.id, opportunity.company)
+ return query
+
+
+class SaleOpportunityEmployeeMonthly(
+ SaleOpportunityReportMixin, ModelSQL, ModelView):
+ 'Sale Opportunity per Employee per Month'
+ __name__ = 'sale.opportunity_employee_monthly'
+ year = fields.Char('Year')
+ month = fields.Many2One('ir.calendar.month', "Month")
+ employee = fields.Many2One('company.employee', 'Employee')
+
+ @classmethod
+ def __setup__(cls):
+ super(SaleOpportunityEmployeeMonthly, cls).__setup__()
+ cls._order.insert(0, ('year', 'DESC'))
+ cls._order.insert(1, ('month.index', 'DESC'))
+ cls._order.insert(2, ('employee', 'ASC'))
+
+ @classmethod
+ def table_query(cls):
+ pool = Pool()
+ Month = pool.get('ir.calendar.month')
+ month = Month.__table__()
+ query = super(SaleOpportunityEmployeeMonthly, cls).table_query()
+ opportunity, = query.from_
+ type_id = cls.id.sql_type().base
+ type_year = cls.year.sql_type().base
+ year_column = Extract('YEAR', opportunity.start_date
+ ).cast(type_year).as_('year')
+ month_index = Extract('MONTH', opportunity.start_date)
+ query.from_ = opportunity.join(
+ month, condition=month_index == month.index)
+ query.columns += (
+ Max(Extract('MONTH', opportunity.start_date)
+ + Extract('YEAR', opportunity.start_date) * 100
+ + Coalesce(opportunity.employee, 0) * 1000000
+ ).cast(type_id).as_('id'),
+ year_column,
+ month.id.as_('month'),
+ opportunity.employee,
+ )
+ query.group_by = (year_column, month.id,
+ opportunity.employee, opportunity.company)
+ return query
diff --git a/modules/sale_opportunity/opportunity.xml b/modules/sale_opportunity/opportunity.xml
new file mode 100644
index 0000000000..2869faef42
--- /dev/null
+++ b/modules/sale_opportunity/opportunity.xml
@@ -0,0 +1,406 @@
+
+
+
+
+
+ tryton-sale-opportunity
+ icons/tryton-sale-opportunity.svg
+
+
+
+ Sale Opportunity
+
+
+
+
+
+
+
+ sale.opportunity
+ form
+ opportunity_form
+
+
+
+ sale.opportunity
+ tree
+ opportunity_tree
+
+
+
+ Sale Opportunity
+
+
+
+
+
+
+
+
+
+
+
+ Sale Opportunity
+
+
+
+
+ Leads and Opportunities
+ sale.opportunity
+
+
+
+
+
+
+
+
+
+
+
+
+ Leads
+
+
+
+
+
+
+ Opportunities
+
+
+
+
+
+
+ Converted
+
+
+
+
+
+ Won
+
+
+
+
+
+ Cancelled
+
+
+
+
+
+ Lost
+
+
+
+
+
+ All
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ lead
+ Set as Lead
+
+
+
+
+
+
+
+
+ opportunity
+ Convert to Opportunity
+
+
+
+
+
+
+
+
+ convert
+ Convert to Sale
+
+
+
+
+
+
+
+
+ lost
+ Mark as Lost
+
+
+
+
+
+
+
+
+ cancel
+ Cancel
+
+
+
+
+
+
+
+
+ User in companies
+
+
+
+
+
+
+
+
+
+ Sales
+ sale.sale
+
+
+
+ form_relate
+ sale.opportunity,-1
+
+
+
+
+ sale.opportunity.line
+ form
+ opportunity_line_form
+
+
+ sale.opportunity.line
+ tree
+ opportunity_line_tree
+
+
+
+ sale.opportunity_employee
+ tree
+ opportunity_employee_tree
+
+
+
+ sale.opportunity_employee
+ graph
+ opportunity_employee_graph1
+
+
+
+ sale.opportunity_employee
+ graph
+ opportunity_employee_graph2
+
+
+
+ sale.opportunity_employee.context
+ form
+ opportunity_employee_context_form
+
+
+
+ Opportunities per Employee
+ sale.opportunity_employee
+ sale.opportunity_employee.context
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ User in companies
+
+
+
+
+
+
+
+
+
+
+
+ sale.opportunity_monthly
+ tree
+ opportunity_monthly_tree
+
+
+
+ sale.opportunity_monthly
+ graph
+ opportunity_monthly_graph1
+
+
+
+ sale.opportunity_monthly
+ graph
+ opportunity_monthly_graph2
+
+
+
+ Opportunities per Month
+ sale.opportunity_monthly
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ User in companies
+
+
+
+
+
+
+
+
+
+ sale.opportunity_employee_monthly
+ tree
+ opportunity_employee_monthly_tree
+
+
+
+ Opportunities per Employee per Month
+ sale.opportunity_employee_monthly
+
+
+
+
+
+
+
+
+
+
+ User in companies
+
+
+
+
+
+
+
+
+
+
diff --git a/modules/sale_opportunity/party.py b/modules/sale_opportunity/party.py
new file mode 100644
index 0000000000..9dc7b79729
--- /dev/null
+++ b/modules/sale_opportunity/party.py
@@ -0,0 +1,23 @@
+# This file is part of Tryton. The COPYRIGHT file at the top level of
+# this repository contains the full copyright notices and license terms.
+from trytond.pool import PoolMeta
+
+
+class Party(metaclass=PoolMeta):
+ __name__ = 'party.party'
+ _history = True
+
+
+class Address(metaclass=PoolMeta):
+ __name__ = 'party.address'
+ _history = True
+
+
+class Replace(metaclass=PoolMeta):
+ __name__ = 'party.replace'
+
+ @classmethod
+ def fields_to_replace(cls):
+ return super().fields_to_replace() + [
+ ('sale.opportunity', 'party'),
+ ]
diff --git a/modules/sale_opportunity/party.xml b/modules/sale_opportunity/party.xml
new file mode 100644
index 0000000000..2a23132768
--- /dev/null
+++ b/modules/sale_opportunity/party.xml
@@ -0,0 +1,28 @@
+
+
+
+
+
+ party.party
+
+ party_form
+
+
+
+ Sales Leads/Opportunities
+ sale.opportunity
+
+
+
+
+ form_relate
+ party.party,-1
+
+
+
+
+
diff --git a/modules/sale_opportunity/product.py b/modules/sale_opportunity/product.py
new file mode 100644
index 0000000000..c04a2848c3
--- /dev/null
+++ b/modules/sale_opportunity/product.py
@@ -0,0 +1,13 @@
+# This file is part of Tryton. The COPYRIGHT file at the top level of
+# this repository contains the full copyright notices and license terms.
+from trytond.pool import PoolMeta
+
+
+class Template(metaclass=PoolMeta):
+ __name__ = 'product.template'
+ _history = True
+
+
+class Product(metaclass=PoolMeta):
+ __name__ = 'product.product'
+ _history = True
diff --git a/modules/sale_opportunity/sale.py b/modules/sale_opportunity/sale.py
new file mode 100644
index 0000000000..3dd377e68a
--- /dev/null
+++ b/modules/sale_opportunity/sale.py
@@ -0,0 +1,76 @@
+# This file is part of Tryton. The COPYRIGHT file at the top level of
+# this repository contains the full copyright notices and license terms.
+from functools import wraps
+
+from trytond.i18n import gettext
+from trytond.model.exceptions import AccessError
+from trytond.pool import PoolMeta, Pool
+from trytond.transaction import Transaction
+
+
+def process_opportunity(func):
+ @wraps(func)
+ def wrapper(cls, sales):
+ pool = Pool()
+ Opportunity = pool.get('sale.opportunity')
+ with Transaction().set_context(_check_access=False):
+ opportunities = Opportunity.browse(
+ set(s.origin for s in cls.browse(sales)
+ if isinstance(s.origin, Opportunity)))
+ func(cls, sales)
+ with Transaction().set_context(_check_access=False):
+ Opportunity.process(opportunities)
+ return wrapper
+
+
+class Sale(metaclass=PoolMeta):
+ __name__ = 'sale.sale'
+
+ @classmethod
+ def _get_origin(cls):
+ return super(Sale, cls)._get_origin() + ['sale.opportunity']
+
+ @classmethod
+ def write(cls, *args):
+ pool = Pool()
+ Opportunity = pool.get('sale.opportunity')
+ actions = iter(args)
+ for sales, values in zip(actions, actions):
+ if 'origin' in values:
+ for sale in sales:
+ if isinstance(sale.origin, Opportunity):
+ raise AccessError(gettext(
+ 'sale_opportunity'
+ '.msg_modify_origin_opportunity',
+ sale=sale.rec_name))
+ super().write(*args)
+
+ @classmethod
+ @process_opportunity
+ def delete(cls, sales):
+ super(Sale, cls).delete(sales)
+
+ @classmethod
+ @process_opportunity
+ def cancel(cls, sales):
+ super(Sale, cls).cancel(sales)
+
+ @classmethod
+ @process_opportunity
+ def quote(cls, sales):
+ super(Sale, cls).quote(sales)
+
+ @classmethod
+ @process_opportunity
+ def confirm(cls, sales):
+ super(Sale, cls).confirm(sales)
+
+ @classmethod
+ @process_opportunity
+ def proceed(cls, sales):
+ super(Sale, cls).proceed(sales)
+
+ @classmethod
+ @process_opportunity
+ def do(cls, sales):
+ super(Sale, cls).do(sales)
diff --git a/modules/sale_opportunity/setup.py b/modules/sale_opportunity/setup.py
new file mode 100755
index 0000000000..296c57bcd4
--- /dev/null
+++ b/modules/sale_opportunity/setup.py
@@ -0,0 +1,149 @@
+#!/usr/bin/env python3
+# This file is part of Tryton. The COPYRIGHT file at the top level of
+# this repository contains the full copyright notices and license terms.
+
+import io
+import os
+import re
+from configparser import ConfigParser
+from setuptools import setup, find_packages
+
+
+def read(fname):
+ return io.open(
+ os.path.join(os.path.dirname(__file__), fname),
+ 'r', encoding='utf-8').read()
+
+
+def get_require_version(name):
+ if minor_version % 2:
+ require = '%s >= %s.%s.dev0, < %s.%s'
+ else:
+ require = '%s >= %s.%s, < %s.%s'
+ require %= (name, major_version, minor_version,
+ major_version, minor_version + 1)
+ return require
+
+
+config = ConfigParser()
+config.read_file(open(os.path.join(os.path.dirname(__file__), 'tryton.cfg')))
+info = dict(config.items('tryton'))
+for key in ('depends', 'extras_depend', 'xml'):
+ if key in info:
+ info[key] = info[key].strip().splitlines()
+version = info.get('version', '0.0.1')
+major_version, minor_version, _ = version.split('.', 2)
+major_version = int(major_version)
+minor_version = int(minor_version)
+name = 'trytond_sale_opportunity'
+
+download_url = 'http://downloads.tryton.org/%s.%s/' % (
+ major_version, minor_version)
+if minor_version % 2:
+ version = '%s.%s.dev0' % (major_version, minor_version)
+ download_url = (
+ 'hg+http://hg.tryton.org/modules/%s#egg=%s-%s' % (
+ name[8:], name, version))
+local_version = []
+if os.environ.get('CI_JOB_ID'):
+ local_version.append(os.environ['CI_JOB_ID'])
+else:
+ for build in ['CI_BUILD_NUMBER', 'CI_JOB_NUMBER']:
+ if os.environ.get(build):
+ local_version.append(os.environ[build])
+ else:
+ local_version = []
+ break
+if local_version:
+ version += '+' + '.'.join(local_version)
+
+requires = ['python-sql >= 0.4']
+for dep in info.get('depends', []):
+ if not re.match(r'(ir|res)(\W|$)', dep):
+ requires.append(get_require_version('trytond_%s' % dep))
+requires.append(get_require_version('trytond'))
+
+tests_require = [get_require_version('proteus')]
+dependency_links = []
+if minor_version % 2:
+ dependency_links.append(
+ 'https://trydevpi.tryton.org/?local_version='
+ + '.'.join(local_version))
+
+setup(name=name,
+ version=version,
+ description='Tryton module with leads and opportunities',
+ long_description=read('README.rst'),
+ author='Tryton',
+ author_email='bugs@tryton.org',
+ url='http://www.tryton.org/',
+ download_url=download_url,
+ project_urls={
+ "Bug Tracker": 'https://bugs.tryton.org/',
+ "Documentation": 'https://docs.tryton.org/',
+ "Forum": 'https://www.tryton.org/forum',
+ "Source Code": 'https://hg.tryton.org/modules/sale_opportunity',
+ },
+ keywords='tryton sale opportunity',
+ package_dir={'trytond.modules.sale_opportunity': '.'},
+ packages=(
+ ['trytond.modules.sale_opportunity']
+ + ['trytond.modules.sale_opportunity.%s' % p for p in find_packages()]
+ ),
+ package_data={
+ 'trytond.modules.sale_opportunity': (info.get('xml', [])
+ + ['tryton.cfg', 'view/*.xml', 'locale/*.po', 'icons/*.svg',
+ 'tests/*.rst']),
+ },
+ classifiers=[
+ 'Development Status :: 5 - Production/Stable',
+ 'Environment :: Plugins',
+ 'Framework :: Tryton',
+ 'Intended Audience :: Developers',
+ 'Intended Audience :: Financial and Insurance Industry',
+ 'Intended Audience :: Legal Industry',
+ 'License :: OSI Approved :: '
+ 'GNU General Public License v3 or later (GPLv3+)',
+ 'Natural Language :: Bulgarian',
+ 'Natural Language :: Catalan',
+ 'Natural Language :: Chinese (Simplified)',
+ 'Natural Language :: Czech',
+ 'Natural Language :: Dutch',
+ 'Natural Language :: English',
+ 'Natural Language :: Finnish',
+ 'Natural Language :: French',
+ 'Natural Language :: German',
+ 'Natural Language :: Hungarian',
+ 'Natural Language :: Indonesian',
+ 'Natural Language :: Italian',
+ 'Natural Language :: Persian',
+ 'Natural Language :: Polish',
+ 'Natural Language :: Portuguese (Brazilian)',
+ 'Natural Language :: Romanian',
+ 'Natural Language :: Russian',
+ 'Natural Language :: Slovenian',
+ 'Natural Language :: Spanish',
+ 'Natural Language :: Turkish',
+ 'Operating System :: OS Independent',
+ 'Programming Language :: Python :: 3',
+ 'Programming Language :: Python :: 3.6',
+ 'Programming Language :: Python :: 3.7',
+ 'Programming Language :: Python :: 3.8',
+ 'Programming Language :: Python :: 3.9',
+ 'Programming Language :: Python :: Implementation :: CPython',
+ 'Programming Language :: Python :: Implementation :: PyPy',
+ 'Topic :: Office/Business',
+ ],
+ license='GPL-3',
+ python_requires='>=3.6',
+ install_requires=requires,
+ dependency_links=dependency_links,
+ zip_safe=False,
+ entry_points="""
+ [trytond.modules]
+ sale_opportunity = trytond.modules.sale_opportunity
+ """,
+ test_suite='tests',
+ test_loader='trytond.test_loader:Loader',
+ tests_require=tests_require,
+ )
diff --git a/modules/sale_opportunity/tests/__init__.py b/modules/sale_opportunity/tests/__init__.py
new file mode 100644
index 0000000000..10c1f40590
--- /dev/null
+++ b/modules/sale_opportunity/tests/__init__.py
@@ -0,0 +1,9 @@
+# This file is part of Tryton. The COPYRIGHT file at the top level of
+# this repository contains the full copyright notices and license terms.
+
+try:
+ from trytond.modules.sale_opportunity.tests.test_sale_opportunity import suite # noqa: E501
+except ImportError:
+ from .test_sale_opportunity import suite
+
+__all__ = ['suite']
diff --git a/modules/sale_opportunity/tests/scenario_sale_opportunity.rst b/modules/sale_opportunity/tests/scenario_sale_opportunity.rst
new file mode 100644
index 0000000000..65c07fb836
--- /dev/null
+++ b/modules/sale_opportunity/tests/scenario_sale_opportunity.rst
@@ -0,0 +1,209 @@
+=========================
+Sale Opportunity Scenario
+=========================
+
+Imports::
+
+ >>> from decimal import Decimal
+ >>> from proteus import Model, Wizard
+ >>> from trytond.tests.tools import activate_modules, set_user
+ >>> from trytond.modules.company.tests.tools import create_company, \
+ ... get_company
+ >>> from trytond.modules.account.tests.tools import create_chart, \
+ ... get_accounts
+ >>> from trytond.modules.account_invoice.tests.tools import \
+ ... create_payment_term
+
+Activate modules::
+
+ >>> config = activate_modules('sale_opportunity')
+
+Create company::
+
+ >>> _ = create_company()
+ >>> company = get_company()
+
+Create chart of accounts::
+
+ >>> _ = create_chart(company)
+ >>> accounts = get_accounts(company)
+ >>> revenue = accounts['revenue']
+
+Create sale opportunity user::
+
+ >>> User = Model.get('res.user')
+ >>> Group = Model.get('res.group')
+ >>> sale_opportunity_user = User()
+ >>> sale_opportunity_user.name = 'Sale Opportunity'
+ >>> sale_opportunity_user.login = 'sale_opportunity'
+ >>> sale_opportunity_group, = Group.find(
+ ... [('name', '=', 'Sale Opportunity')])
+ >>> sale_opportunity_user.groups.append(sale_opportunity_group)
+
+ >>> Employee = Model.get('company.employee')
+ >>> Party = Model.get('party.party')
+ >>> employee_party = Party(name='Employee')
+ >>> employee_party.save()
+ >>> employee = Employee(party=employee_party)
+ >>> employee.save()
+ >>> sale_opportunity_user.employees.append(employee)
+ >>> sale_opportunity_user.employee = employee
+
+ >>> sale_opportunity_user.save()
+
+Create sale user::
+
+ >>> sale_user = User()
+ >>> sale_user.name = 'Sale'
+ >>> sale_user.login = 'sale'
+ >>> sale_group, = Group.find([('name', '=', 'Sales')])
+ >>> sale_user.groups.append(sale_group)
+ >>> sale_user.save()
+
+Create party::
+
+ >>> Party = Model.get('party.party')
+ >>> customer = Party(name='Customer')
+ >>> customer.save()
+
+Create account category::
+
+ >>> ProductCategory = Model.get('product.category')
+ >>> account_category = ProductCategory(name="Account Category")
+ >>> account_category.accounting = True
+ >>> account_category.account_revenue = revenue
+ >>> account_category.save()
+
+Create product::
+
+ >>> ProductUom = Model.get('product.uom')
+ >>> unit, = ProductUom.find([('name', '=', 'Unit')])
+ >>> ProductTemplate = Model.get('product.template')
+
+ >>> template = ProductTemplate()
+ >>> template.name = 'product'
+ >>> template.default_uom = unit
+ >>> template.type = 'goods'
+ >>> template.salable = True
+ >>> template.list_price = Decimal('10')
+ >>> template.account_category = account_category
+ >>> template.save()
+ >>> product, = template.products
+
+Create payment term::
+
+ >>> payment_term = create_payment_term()
+ >>> payment_term.save()
+
+Create an lead::
+
+ >>> set_user(sale_opportunity_user)
+ >>> Opportunity = Model.get('sale.opportunity')
+ >>> opportunity = Opportunity()
+ >>> opportunity.description = 'Opportunity'
+ >>> opportunity.save()
+ >>> opportunity.state
+ 'lead'
+
+Convert to opportunity::
+
+ >>> opportunity.party = customer
+ >>> opportunity.address, = customer.addresses
+ >>> opportunity.payment_term = payment_term
+ >>> opportunity.amount = Decimal(100)
+ >>> opportunity.employee = employee
+ >>> opportunity.click('opportunity')
+ >>> opportunity.state
+ 'opportunity'
+
+Add a line::
+
+ >>> line = opportunity.lines.new()
+ >>> line.product = product
+ >>> line.quantity = 10
+ >>> opportunity.save()
+
+Convert to sale::
+
+ >>> opportunity.click('convert')
+ >>> opportunity.state
+ 'converted'
+
+Find the sale::
+
+ >>> set_user(sale_user)
+ >>> Sale = Model.get('sale.sale')
+ >>> sale, = Sale.find(
+ ... [('origin', '=', 'sale.opportunity,%s' % opportunity.id)])
+ >>> line, = sale.lines
+ >>> line.product == product
+ True
+ >>> line.quantity
+ 10.0
+
+Quote different quantity::
+
+ >>> line.quantity = 9
+ >>> sale.click('quote')
+
+Check opportunity amount updated::
+
+ >>> set_user(sale_opportunity_user)
+ >>> opportunity.reload()
+ >>> opportunity.amount
+ Decimal('90.00')
+ >>> opportunity.state
+ 'converted'
+
+Add a second quotation::
+
+ >>> set_user(sale_user)
+ >>> second_sale = Sale()
+ >>> second_sale.origin = opportunity
+ >>> second_sale.party = customer
+ >>> second_sale.payment_term = payment_term
+ >>> line = second_sale.lines.new()
+ >>> line.product = product
+ >>> line.quantity = 1
+ >>> second_sale.click('quote')
+
+Check opportunity amount updated::
+
+ >>> set_user(sale_opportunity_user)
+ >>> opportunity.reload()
+ >>> opportunity.amount
+ Decimal('100.00')
+ >>> opportunity.state
+ 'converted'
+
+Cancel second quotation::
+
+ >>> set_user(sale_user)
+ >>> second_sale.click('cancel')
+ >>> second_sale.state
+ 'cancelled'
+
+Check opportunity amount updated::
+
+ >>> set_user(sale_opportunity_user)
+ >>> opportunity.reload()
+ >>> opportunity.amount
+ Decimal('90.00')
+ >>> opportunity.state
+ 'converted'
+
+Won opportunity::
+
+ >>> set_user(sale_user)
+ >>> sale.click('confirm')
+ >>> set_user(sale_opportunity_user)
+ >>> opportunity.reload()
+ >>> opportunity.state
+ 'won'
+
+Check opportunity state updated::
+
+ >>> set_user(sale_opportunity_user)
+ >>> opportunity.reload()
+ >>> opportunity.state
+ 'won'
diff --git a/modules/sale_opportunity/tests/test_sale_opportunity.py b/modules/sale_opportunity/tests/test_sale_opportunity.py
new file mode 100644
index 0000000000..e3048729a9
--- /dev/null
+++ b/modules/sale_opportunity/tests/test_sale_opportunity.py
@@ -0,0 +1,26 @@
+# This file is part of Tryton. The COPYRIGHT file at the top level of
+# this repository contains the full copyright notices and license terms.
+import unittest
+import doctest
+import trytond.tests.test_tryton
+from trytond.tests.test_tryton import ModuleTestCase
+from trytond.tests.test_tryton import doctest_teardown
+from trytond.tests.test_tryton import doctest_checker
+
+from trytond.modules.company.tests import CompanyTestMixin
+
+
+class SaleOpportunityTestCase(CompanyTestMixin, ModuleTestCase):
+ 'Test SaleOpportunity module'
+ module = 'sale_opportunity'
+
+
+def suite():
+ suite = trytond.tests.test_tryton.suite()
+ suite.addTests(unittest.TestLoader().loadTestsFromTestCase(
+ SaleOpportunityTestCase))
+ suite.addTests(doctest.DocFileSuite('scenario_sale_opportunity.rst',
+ tearDown=doctest_teardown, encoding='utf-8',
+ checker=doctest_checker,
+ optionflags=doctest.REPORT_ONLY_FIRST_FAILURE))
+ return suite
diff --git a/modules/sale_opportunity/tox.ini b/modules/sale_opportunity/tox.ini
new file mode 100644
index 0000000000..197496c0cb
--- /dev/null
+++ b/modules/sale_opportunity/tox.ini
@@ -0,0 +1,15 @@
+[tox]
+envlist = {py36,py37,py38,py39}-{sqlite,postgresql},pypy3-{sqlite,postgresql}
+
+[testenv]
+commands = {envpython} setup.py test
+deps =
+ {py36,py37,py38,py39}-postgresql: psycopg2 >= 2.5
+ pypy3-postgresql: psycopg2cffi >= 2.5
+ py36-sqlite: sqlitebck
+setenv =
+ sqlite: TRYTOND_DATABASE_URI={env:SQLITE_URI:sqlite://}
+ postgresql: TRYTOND_DATABASE_URI={env:POSTGRESQL_URI:postgresql://}
+ sqlite: DB_NAME={env:SQLITE_NAME::memory:}
+ postgresql: DB_NAME={env:POSTGRESQL_NAME:test}
+install_command = pip install --pre --find-links https://trydevpi.tryton.org/?local_version={env:CI_JOB_ID:{env:CI_BUILD_NUMBER}.{env:CI_JOB_NUMBER}} {opts} {packages}
diff --git a/modules/sale_opportunity/tryton.cfg b/modules/sale_opportunity/tryton.cfg
new file mode 100644
index 0000000000..5035153c2d
--- /dev/null
+++ b/modules/sale_opportunity/tryton.cfg
@@ -0,0 +1,16 @@
+[tryton]
+version=6.0.2
+depends:
+ account
+ account_invoice
+ company
+ currency
+ party
+ product
+ sale
+ stock
+xml:
+ opportunity.xml
+ party.xml
+ configuration.xml
+ message.xml
diff --git a/modules/sale_opportunity/view/configuration_form.xml b/modules/sale_opportunity/view/configuration_form.xml
new file mode 100644
index 0000000000..20bba2951d
--- /dev/null
+++ b/modules/sale_opportunity/view/configuration_form.xml
@@ -0,0 +1,9 @@
+
+
+
+
+
+
+
+
diff --git a/modules/sale_opportunity/view/opportunity_employee_context_form.xml b/modules/sale_opportunity/view/opportunity_employee_context_form.xml
new file mode 100644
index 0000000000..029f1a04e5
--- /dev/null
+++ b/modules/sale_opportunity/view/opportunity_employee_context_form.xml
@@ -0,0 +1,9 @@
+
+
+
diff --git a/modules/sale_opportunity/view/opportunity_employee_graph1.xml b/modules/sale_opportunity/view/opportunity_employee_graph1.xml
new file mode 100644
index 0000000000..f132cb96b6
--- /dev/null
+++ b/modules/sale_opportunity/view/opportunity_employee_graph1.xml
@@ -0,0 +1,14 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/modules/sale_opportunity/view/opportunity_employee_graph2.xml b/modules/sale_opportunity/view/opportunity_employee_graph2.xml
new file mode 100644
index 0000000000..3686d76e8d
--- /dev/null
+++ b/modules/sale_opportunity/view/opportunity_employee_graph2.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/modules/sale_opportunity/view/opportunity_employee_monthly_tree.xml b/modules/sale_opportunity/view/opportunity_employee_monthly_tree.xml
new file mode 100644
index 0000000000..0cf92116c8
--- /dev/null
+++ b/modules/sale_opportunity/view/opportunity_employee_monthly_tree.xml
@@ -0,0 +1,27 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/modules/sale_opportunity/view/opportunity_employee_tree.xml b/modules/sale_opportunity/view/opportunity_employee_tree.xml
new file mode 100644
index 0000000000..e489d7e19b
--- /dev/null
+++ b/modules/sale_opportunity/view/opportunity_employee_tree.xml
@@ -0,0 +1,25 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/modules/sale_opportunity/view/opportunity_form.xml b/modules/sale_opportunity/view/opportunity_form.xml
new file mode 100644
index 0000000000..846285fd50
--- /dev/null
+++ b/modules/sale_opportunity/view/opportunity_form.xml
@@ -0,0 +1,66 @@
+
+
+
diff --git a/modules/sale_opportunity/view/opportunity_line_form.xml b/modules/sale_opportunity/view/opportunity_line_form.xml
new file mode 100644
index 0000000000..725d808946
--- /dev/null
+++ b/modules/sale_opportunity/view/opportunity_line_form.xml
@@ -0,0 +1,15 @@
+
+
+
diff --git a/modules/sale_opportunity/view/opportunity_line_tree.xml b/modules/sale_opportunity/view/opportunity_line_tree.xml
new file mode 100644
index 0000000000..e936483c25
--- /dev/null
+++ b/modules/sale_opportunity/view/opportunity_line_tree.xml
@@ -0,0 +1,8 @@
+
+
+
+
+
+
+
diff --git a/modules/sale_opportunity/view/opportunity_monthly_graph1.xml b/modules/sale_opportunity/view/opportunity_monthly_graph1.xml
new file mode 100644
index 0000000000..17373df5f5
--- /dev/null
+++ b/modules/sale_opportunity/view/opportunity_monthly_graph1.xml
@@ -0,0 +1,14 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/modules/sale_opportunity/view/opportunity_monthly_graph2.xml b/modules/sale_opportunity/view/opportunity_monthly_graph2.xml
new file mode 100644
index 0000000000..cf55d094ff
--- /dev/null
+++ b/modules/sale_opportunity/view/opportunity_monthly_graph2.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/modules/sale_opportunity/view/opportunity_monthly_tree.xml b/modules/sale_opportunity/view/opportunity_monthly_tree.xml
new file mode 100644
index 0000000000..630697adbe
--- /dev/null
+++ b/modules/sale_opportunity/view/opportunity_monthly_tree.xml
@@ -0,0 +1,27 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/modules/sale_opportunity/view/opportunity_tree.xml b/modules/sale_opportunity/view/opportunity_tree.xml
new file mode 100644
index 0000000000..81b5b146ac
--- /dev/null
+++ b/modules/sale_opportunity/view/opportunity_tree.xml
@@ -0,0 +1,17 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/modules/sale_opportunity/view/party_form.xml b/modules/sale_opportunity/view/party_form.xml
new file mode 100644
index 0000000000..2f5982b35b
--- /dev/null
+++ b/modules/sale_opportunity/view/party_form.xml
@@ -0,0 +1,8 @@
+
+
+
+
+
+
+
diff --git a/modules/sale_payment/.drone.yml b/modules/sale_payment/.drone.yml
new file mode 100644
index 0000000000..2049d30a49
--- /dev/null
+++ b/modules/sale_payment/.drone.yml
@@ -0,0 +1,68 @@
+clone:
+ hg:
+ image: plugins/hg
+ environment:
+ - HG_SHARE_POOL=/root/.cache/hg
+ volumes:
+ - cache:/root/.cache
+
+pipeline:
+ tox:
+ image: ${IMAGE}
+ environment:
+ - CFLAGS=-O0
+ - DB_CACHE=/cache
+ - TOX_TESTENV_PASSENV=CFLAGS DB_CACHE CI_BUILD_NUMBER CI_JOB_NUMBER CI_JOB_ID
+ - POSTGRESQL_URI=postgresql://postgres@postgresql:5432/
+ commands:
+ - echo "[extensions]" >> /root/.hgrc
+ - echo "hgext.share =" >> /root/.hgrc
+ - echo "[share]" >> /root/.hgrc
+ - echo "pool = /root/.cache/hg" >> /root/.hgrc
+ - pip install tox
+ - tox -e "${TOXENV}-${DATABASE}"
+ volumes:
+ - cache:/root/.cache
+ check_dist:
+ image: ${IMAGE}
+ commands:
+ - pip install twine
+ - python setup.py sdist
+ - twine check dist/*
+
+services:
+ postgresql:
+ image: postgres
+ environment:
+ - POSTGRES_HOST_AUTH_METHOD=trust
+ command: "-c fsync=off -c synchronous_commit=off -c full_page_writes=off"
+ when:
+ matrix:
+ DATABASE: postgresql
+
+matrix:
+ include:
+ - IMAGE: python:3.6
+ TOXENV: py36
+ DATABASE: sqlite
+ - IMAGE: python:3.6
+ TOXENV: py36
+ DATABASE: postgresql
+ - IMAGE: python:3.7
+ TOXENV: py37
+ DATABASE: sqlite
+ - IMAGE: python:3.7
+ TOXENV: py37
+ DATABASE: postgresql
+ - IMAGE: python:3.8
+ TOXENV: py38
+ DATABASE: sqlite
+ - IMAGE: python:3.8
+ TOXENV: py38
+ DATABASE: postgresql
+ - IMAGE: python:3.9
+ TOXENV: py39
+ DATABASE: sqlite
+ - IMAGE: python:3.9
+ TOXENV: py39
+ DATABASE: postgresql
diff --git a/modules/sale_payment/.flake8 b/modules/sale_payment/.flake8
new file mode 100644
index 0000000000..fa6b4f66d1
--- /dev/null
+++ b/modules/sale_payment/.flake8
@@ -0,0 +1,2 @@
+[flake8]
+ignore=E123,E124,E126,E128,E741,W503
diff --git a/modules/sale_payment/CHANGELOG b/modules/sale_payment/CHANGELOG
new file mode 100644
index 0000000000..c876d0c430
--- /dev/null
+++ b/modules/sale_payment/CHANGELOG
@@ -0,0 +1,33 @@
+Version 6.0.2 - 2022-11-05
+--------------------------
+* Bug fixes (see mercurial logs for details)
+
+Version 6.0.1 - 2022-02-01
+* Bug fixes (see mercurial logs for details)
+
+Version 6.0.0 - 2021-05-03
+* Bug fixes (see mercurial logs for details)
+
+Version 5.8.0 - 2020-11-02
+* Bug fixes (see mercurial logs for details)
+* Remove support for Python 3.5
+* Fill payment with sale data
+
+Version 5.6.0 - 2020-05-04
+* Bug fixes (see mercurial logs for details)
+
+Version 5.4.0 - 2019-11-04
+* Bug fixes (see mercurial logs for details)
+
+Version 5.2.0 - 2019-05-06
+* Bug fixes (see mercurial logs for details)
+
+Version 5.0.0 - 2018-10-01
+* Bug fixes (see mercurial logs for details)
+* Remove support for Python 2.7
+
+Version 4.8.0 - 2018-04-23
+* Bug fixes (see mercurial logs for details)
+
+Version 4.6.0 - 2017-10-30
+* Initial release
diff --git a/modules/sale_payment/COPYRIGHT b/modules/sale_payment/COPYRIGHT
new file mode 100644
index 0000000000..ccf79c7ee9
--- /dev/null
+++ b/modules/sale_payment/COPYRIGHT
@@ -0,0 +1,17 @@
+Copyright (c) 2017 Mark S Hayden.
+Copyright (c) 2017 Coalesco Digital Systemc Inc.
+Copyright (c) 2017-2022 Cédric Krier.
+Copyright (c) 2017-2022 B2CK.
+
+This program is free software: you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation, either version 3 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program. If not, see .
diff --git a/modules/sale_payment/LICENSE b/modules/sale_payment/LICENSE
new file mode 100644
index 0000000000..20d40b6bce
--- /dev/null
+++ b/modules/sale_payment/LICENSE
@@ -0,0 +1,674 @@
+ GNU GENERAL PUBLIC LICENSE
+ Version 3, 29 June 2007
+
+ Copyright (C) 2007 Free Software Foundation, Inc.
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+ Preamble
+
+ The GNU General Public License is a free, copyleft license for
+software and other kinds of works.
+
+ The licenses for most software and other practical works are designed
+to take away your freedom to share and change the works. By contrast,
+the GNU General Public License is intended to guarantee your freedom to
+share and change all versions of a program--to make sure it remains free
+software for all its users. We, the Free Software Foundation, use the
+GNU General Public License for most of our software; it applies also to
+any other work released this way by its authors. You can apply it to
+your programs, too.
+
+ When we speak of free software, we are referring to freedom, not
+price. Our General Public Licenses are designed to make sure that you
+have the freedom to distribute copies of free software (and charge for
+them if you wish), that you receive source code or can get it if you
+want it, that you can change the software or use pieces of it in new
+free programs, and that you know you can do these things.
+
+ To protect your rights, we need to prevent others from denying you
+these rights or asking you to surrender the rights. Therefore, you have
+certain responsibilities if you distribute copies of the software, or if
+you modify it: responsibilities to respect the freedom of others.
+
+ For example, if you distribute copies of such a program, whether
+gratis or for a fee, you must pass on to the recipients the same
+freedoms that you received. You must make sure that they, too, receive
+or can get the source code. And you must show them these terms so they
+know their rights.
+
+ Developers that use the GNU GPL protect your rights with two steps:
+(1) assert copyright on the software, and (2) offer you this License
+giving you legal permission to copy, distribute and/or modify it.
+
+ For the developers' and authors' protection, the GPL clearly explains
+that there is no warranty for this free software. For both users' and
+authors' sake, the GPL requires that modified versions be marked as
+changed, so that their problems will not be attributed erroneously to
+authors of previous versions.
+
+ Some devices are designed to deny users access to install or run
+modified versions of the software inside them, although the manufacturer
+can do so. This is fundamentally incompatible with the aim of
+protecting users' freedom to change the software. The systematic
+pattern of such abuse occurs in the area of products for individuals to
+use, which is precisely where it is most unacceptable. Therefore, we
+have designed this version of the GPL to prohibit the practice for those
+products. If such problems arise substantially in other domains, we
+stand ready to extend this provision to those domains in future versions
+of the GPL, as needed to protect the freedom of users.
+
+ Finally, every program is threatened constantly by software patents.
+States should not allow patents to restrict development and use of
+software on general-purpose computers, but in those that do, we wish to
+avoid the special danger that patents applied to a free program could
+make it effectively proprietary. To prevent this, the GPL assures that
+patents cannot be used to render the program non-free.
+
+ The precise terms and conditions for copying, distribution and
+modification follow.
+
+ TERMS AND CONDITIONS
+
+ 0. Definitions.
+
+ "This License" refers to version 3 of the GNU General Public License.
+
+ "Copyright" also means copyright-like laws that apply to other kinds of
+works, such as semiconductor masks.
+
+ "The Program" refers to any copyrightable work licensed under this
+License. Each licensee is addressed as "you". "Licensees" and
+"recipients" may be individuals or organizations.
+
+ To "modify" a work means to copy from or adapt all or part of the work
+in a fashion requiring copyright permission, other than the making of an
+exact copy. The resulting work is called a "modified version" of the
+earlier work or a work "based on" the earlier work.
+
+ A "covered work" means either the unmodified Program or a work based
+on the Program.
+
+ To "propagate" a work means to do anything with it that, without
+permission, would make you directly or secondarily liable for
+infringement under applicable copyright law, except executing it on a
+computer or modifying a private copy. Propagation includes copying,
+distribution (with or without modification), making available to the
+public, and in some countries other activities as well.
+
+ To "convey" a work means any kind of propagation that enables other
+parties to make or receive copies. Mere interaction with a user through
+a computer network, with no transfer of a copy, is not conveying.
+
+ An interactive user interface displays "Appropriate Legal Notices"
+to the extent that it includes a convenient and prominently visible
+feature that (1) displays an appropriate copyright notice, and (2)
+tells the user that there is no warranty for the work (except to the
+extent that warranties are provided), that licensees may convey the
+work under this License, and how to view a copy of this License. If
+the interface presents a list of user commands or options, such as a
+menu, a prominent item in the list meets this criterion.
+
+ 1. Source Code.
+
+ The "source code" for a work means the preferred form of the work
+for making modifications to it. "Object code" means any non-source
+form of a work.
+
+ A "Standard Interface" means an interface that either is an official
+standard defined by a recognized standards body, or, in the case of
+interfaces specified for a particular programming language, one that
+is widely used among developers working in that language.
+
+ The "System Libraries" of an executable work include anything, other
+than the work as a whole, that (a) is included in the normal form of
+packaging a Major Component, but which is not part of that Major
+Component, and (b) serves only to enable use of the work with that
+Major Component, or to implement a Standard Interface for which an
+implementation is available to the public in source code form. A
+"Major Component", in this context, means a major essential component
+(kernel, window system, and so on) of the specific operating system
+(if any) on which the executable work runs, or a compiler used to
+produce the work, or an object code interpreter used to run it.
+
+ The "Corresponding Source" for a work in object code form means all
+the source code needed to generate, install, and (for an executable
+work) run the object code and to modify the work, including scripts to
+control those activities. However, it does not include the work's
+System Libraries, or general-purpose tools or generally available free
+programs which are used unmodified in performing those activities but
+which are not part of the work. For example, Corresponding Source
+includes interface definition files associated with source files for
+the work, and the source code for shared libraries and dynamically
+linked subprograms that the work is specifically designed to require,
+such as by intimate data communication or control flow between those
+subprograms and other parts of the work.
+
+ The Corresponding Source need not include anything that users
+can regenerate automatically from other parts of the Corresponding
+Source.
+
+ The Corresponding Source for a work in source code form is that
+same work.
+
+ 2. Basic Permissions.
+
+ All rights granted under this License are granted for the term of
+copyright on the Program, and are irrevocable provided the stated
+conditions are met. This License explicitly affirms your unlimited
+permission to run the unmodified Program. The output from running a
+covered work is covered by this License only if the output, given its
+content, constitutes a covered work. This License acknowledges your
+rights of fair use or other equivalent, as provided by copyright law.
+
+ You may make, run and propagate covered works that you do not
+convey, without conditions so long as your license otherwise remains
+in force. You may convey covered works to others for the sole purpose
+of having them make modifications exclusively for you, or provide you
+with facilities for running those works, provided that you comply with
+the terms of this License in conveying all material for which you do
+not control copyright. Those thus making or running the covered works
+for you must do so exclusively on your behalf, under your direction
+and control, on terms that prohibit them from making any copies of
+your copyrighted material outside their relationship with you.
+
+ Conveying under any other circumstances is permitted solely under
+the conditions stated below. Sublicensing is not allowed; section 10
+makes it unnecessary.
+
+ 3. Protecting Users' Legal Rights From Anti-Circumvention Law.
+
+ No covered work shall be deemed part of an effective technological
+measure under any applicable law fulfilling obligations under article
+11 of the WIPO copyright treaty adopted on 20 December 1996, or
+similar laws prohibiting or restricting circumvention of such
+measures.
+
+ When you convey a covered work, you waive any legal power to forbid
+circumvention of technological measures to the extent such circumvention
+is effected by exercising rights under this License with respect to
+the covered work, and you disclaim any intention to limit operation or
+modification of the work as a means of enforcing, against the work's
+users, your or third parties' legal rights to forbid circumvention of
+technological measures.
+
+ 4. Conveying Verbatim Copies.
+
+ You may convey verbatim copies of the Program's source code as you
+receive it, in any medium, provided that you conspicuously and
+appropriately publish on each copy an appropriate copyright notice;
+keep intact all notices stating that this License and any
+non-permissive terms added in accord with section 7 apply to the code;
+keep intact all notices of the absence of any warranty; and give all
+recipients a copy of this License along with the Program.
+
+ You may charge any price or no price for each copy that you convey,
+and you may offer support or warranty protection for a fee.
+
+ 5. Conveying Modified Source Versions.
+
+ You may convey a work based on the Program, or the modifications to
+produce it from the Program, in the form of source code under the
+terms of section 4, provided that you also meet all of these conditions:
+
+ a) The work must carry prominent notices stating that you modified
+ it, and giving a relevant date.
+
+ b) The work must carry prominent notices stating that it is
+ released under this License and any conditions added under section
+ 7. This requirement modifies the requirement in section 4 to
+ "keep intact all notices".
+
+ c) You must license the entire work, as a whole, under this
+ License to anyone who comes into possession of a copy. This
+ License will therefore apply, along with any applicable section 7
+ additional terms, to the whole of the work, and all its parts,
+ regardless of how they are packaged. This License gives no
+ permission to license the work in any other way, but it does not
+ invalidate such permission if you have separately received it.
+
+ d) If the work has interactive user interfaces, each must display
+ Appropriate Legal Notices; however, if the Program has interactive
+ interfaces that do not display Appropriate Legal Notices, your
+ work need not make them do so.
+
+ A compilation of a covered work with other separate and independent
+works, which are not by their nature extensions of the covered work,
+and which are not combined with it such as to form a larger program,
+in or on a volume of a storage or distribution medium, is called an
+"aggregate" if the compilation and its resulting copyright are not
+used to limit the access or legal rights of the compilation's users
+beyond what the individual works permit. Inclusion of a covered work
+in an aggregate does not cause this License to apply to the other
+parts of the aggregate.
+
+ 6. Conveying Non-Source Forms.
+
+ You may convey a covered work in object code form under the terms
+of sections 4 and 5, provided that you also convey the
+machine-readable Corresponding Source under the terms of this License,
+in one of these ways:
+
+ a) Convey the object code in, or embodied in, a physical product
+ (including a physical distribution medium), accompanied by the
+ Corresponding Source fixed on a durable physical medium
+ customarily used for software interchange.
+
+ b) Convey the object code in, or embodied in, a physical product
+ (including a physical distribution medium), accompanied by a
+ written offer, valid for at least three years and valid for as
+ long as you offer spare parts or customer support for that product
+ model, to give anyone who possesses the object code either (1) a
+ copy of the Corresponding Source for all the software in the
+ product that is covered by this License, on a durable physical
+ medium customarily used for software interchange, for a price no
+ more than your reasonable cost of physically performing this
+ conveying of source, or (2) access to copy the
+ Corresponding Source from a network server at no charge.
+
+ c) Convey individual copies of the object code with a copy of the
+ written offer to provide the Corresponding Source. This
+ alternative is allowed only occasionally and noncommercially, and
+ only if you received the object code with such an offer, in accord
+ with subsection 6b.
+
+ d) Convey the object code by offering access from a designated
+ place (gratis or for a charge), and offer equivalent access to the
+ Corresponding Source in the same way through the same place at no
+ further charge. You need not require recipients to copy the
+ Corresponding Source along with the object code. If the place to
+ copy the object code is a network server, the Corresponding Source
+ may be on a different server (operated by you or a third party)
+ that supports equivalent copying facilities, provided you maintain
+ clear directions next to the object code saying where to find the
+ Corresponding Source. Regardless of what server hosts the
+ Corresponding Source, you remain obligated to ensure that it is
+ available for as long as needed to satisfy these requirements.
+
+ e) Convey the object code using peer-to-peer transmission, provided
+ you inform other peers where the object code and Corresponding
+ Source of the work are being offered to the general public at no
+ charge under subsection 6d.
+
+ A separable portion of the object code, whose source code is excluded
+from the Corresponding Source as a System Library, need not be
+included in conveying the object code work.
+
+ A "User Product" is either (1) a "consumer product", which means any
+tangible personal property which is normally used for personal, family,
+or household purposes, or (2) anything designed or sold for incorporation
+into a dwelling. In determining whether a product is a consumer product,
+doubtful cases shall be resolved in favor of coverage. For a particular
+product received by a particular user, "normally used" refers to a
+typical or common use of that class of product, regardless of the status
+of the particular user or of the way in which the particular user
+actually uses, or expects or is expected to use, the product. A product
+is a consumer product regardless of whether the product has substantial
+commercial, industrial or non-consumer uses, unless such uses represent
+the only significant mode of use of the product.
+
+ "Installation Information" for a User Product means any methods,
+procedures, authorization keys, or other information required to install
+and execute modified versions of a covered work in that User Product from
+a modified version of its Corresponding Source. The information must
+suffice to ensure that the continued functioning of the modified object
+code is in no case prevented or interfered with solely because
+modification has been made.
+
+ If you convey an object code work under this section in, or with, or
+specifically for use in, a User Product, and the conveying occurs as
+part of a transaction in which the right of possession and use of the
+User Product is transferred to the recipient in perpetuity or for a
+fixed term (regardless of how the transaction is characterized), the
+Corresponding Source conveyed under this section must be accompanied
+by the Installation Information. But this requirement does not apply
+if neither you nor any third party retains the ability to install
+modified object code on the User Product (for example, the work has
+been installed in ROM).
+
+ The requirement to provide Installation Information does not include a
+requirement to continue to provide support service, warranty, or updates
+for a work that has been modified or installed by the recipient, or for
+the User Product in which it has been modified or installed. Access to a
+network may be denied when the modification itself materially and
+adversely affects the operation of the network or violates the rules and
+protocols for communication across the network.
+
+ Corresponding Source conveyed, and Installation Information provided,
+in accord with this section must be in a format that is publicly
+documented (and with an implementation available to the public in
+source code form), and must require no special password or key for
+unpacking, reading or copying.
+
+ 7. Additional Terms.
+
+ "Additional permissions" are terms that supplement the terms of this
+License by making exceptions from one or more of its conditions.
+Additional permissions that are applicable to the entire Program shall
+be treated as though they were included in this License, to the extent
+that they are valid under applicable law. If additional permissions
+apply only to part of the Program, that part may be used separately
+under those permissions, but the entire Program remains governed by
+this License without regard to the additional permissions.
+
+ When you convey a copy of a covered work, you may at your option
+remove any additional permissions from that copy, or from any part of
+it. (Additional permissions may be written to require their own
+removal in certain cases when you modify the work.) You may place
+additional permissions on material, added by you to a covered work,
+for which you have or can give appropriate copyright permission.
+
+ Notwithstanding any other provision of this License, for material you
+add to a covered work, you may (if authorized by the copyright holders of
+that material) supplement the terms of this License with terms:
+
+ a) Disclaiming warranty or limiting liability differently from the
+ terms of sections 15 and 16 of this License; or
+
+ b) Requiring preservation of specified reasonable legal notices or
+ author attributions in that material or in the Appropriate Legal
+ Notices displayed by works containing it; or
+
+ c) Prohibiting misrepresentation of the origin of that material, or
+ requiring that modified versions of such material be marked in
+ reasonable ways as different from the original version; or
+
+ d) Limiting the use for publicity purposes of names of licensors or
+ authors of the material; or
+
+ e) Declining to grant rights under trademark law for use of some
+ trade names, trademarks, or service marks; or
+
+ f) Requiring indemnification of licensors and authors of that
+ material by anyone who conveys the material (or modified versions of
+ it) with contractual assumptions of liability to the recipient, for
+ any liability that these contractual assumptions directly impose on
+ those licensors and authors.
+
+ All other non-permissive additional terms are considered "further
+restrictions" within the meaning of section 10. If the Program as you
+received it, or any part of it, contains a notice stating that it is
+governed by this License along with a term that is a further
+restriction, you may remove that term. If a license document contains
+a further restriction but permits relicensing or conveying under this
+License, you may add to a covered work material governed by the terms
+of that license document, provided that the further restriction does
+not survive such relicensing or conveying.
+
+ If you add terms to a covered work in accord with this section, you
+must place, in the relevant source files, a statement of the
+additional terms that apply to those files, or a notice indicating
+where to find the applicable terms.
+
+ Additional terms, permissive or non-permissive, may be stated in the
+form of a separately written license, or stated as exceptions;
+the above requirements apply either way.
+
+ 8. Termination.
+
+ You may not propagate or modify a covered work except as expressly
+provided under this License. Any attempt otherwise to propagate or
+modify it is void, and will automatically terminate your rights under
+this License (including any patent licenses granted under the third
+paragraph of section 11).
+
+ However, if you cease all violation of this License, then your
+license from a particular copyright holder is reinstated (a)
+provisionally, unless and until the copyright holder explicitly and
+finally terminates your license, and (b) permanently, if the copyright
+holder fails to notify you of the violation by some reasonable means
+prior to 60 days after the cessation.
+
+ Moreover, your license from a particular copyright holder is
+reinstated permanently if the copyright holder notifies you of the
+violation by some reasonable means, this is the first time you have
+received notice of violation of this License (for any work) from that
+copyright holder, and you cure the violation prior to 30 days after
+your receipt of the notice.
+
+ Termination of your rights under this section does not terminate the
+licenses of parties who have received copies or rights from you under
+this License. If your rights have been terminated and not permanently
+reinstated, you do not qualify to receive new licenses for the same
+material under section 10.
+
+ 9. Acceptance Not Required for Having Copies.
+
+ You are not required to accept this License in order to receive or
+run a copy of the Program. Ancillary propagation of a covered work
+occurring solely as a consequence of using peer-to-peer transmission
+to receive a copy likewise does not require acceptance. However,
+nothing other than this License grants you permission to propagate or
+modify any covered work. These actions infringe copyright if you do
+not accept this License. Therefore, by modifying or propagating a
+covered work, you indicate your acceptance of this License to do so.
+
+ 10. Automatic Licensing of Downstream Recipients.
+
+ Each time you convey a covered work, the recipient automatically
+receives a license from the original licensors, to run, modify and
+propagate that work, subject to this License. You are not responsible
+for enforcing compliance by third parties with this License.
+
+ An "entity transaction" is a transaction transferring control of an
+organization, or substantially all assets of one, or subdividing an
+organization, or merging organizations. If propagation of a covered
+work results from an entity transaction, each party to that
+transaction who receives a copy of the work also receives whatever
+licenses to the work the party's predecessor in interest had or could
+give under the previous paragraph, plus a right to possession of the
+Corresponding Source of the work from the predecessor in interest, if
+the predecessor has it or can get it with reasonable efforts.
+
+ You may not impose any further restrictions on the exercise of the
+rights granted or affirmed under this License. For example, you may
+not impose a license fee, royalty, or other charge for exercise of
+rights granted under this License, and you may not initiate litigation
+(including a cross-claim or counterclaim in a lawsuit) alleging that
+any patent claim is infringed by making, using, selling, offering for
+sale, or importing the Program or any portion of it.
+
+ 11. Patents.
+
+ A "contributor" is a copyright holder who authorizes use under this
+License of the Program or a work on which the Program is based. The
+work thus licensed is called the contributor's "contributor version".
+
+ A contributor's "essential patent claims" are all patent claims
+owned or controlled by the contributor, whether already acquired or
+hereafter acquired, that would be infringed by some manner, permitted
+by this License, of making, using, or selling its contributor version,
+but do not include claims that would be infringed only as a
+consequence of further modification of the contributor version. For
+purposes of this definition, "control" includes the right to grant
+patent sublicenses in a manner consistent with the requirements of
+this License.
+
+ Each contributor grants you a non-exclusive, worldwide, royalty-free
+patent license under the contributor's essential patent claims, to
+make, use, sell, offer for sale, import and otherwise run, modify and
+propagate the contents of its contributor version.
+
+ In the following three paragraphs, a "patent license" is any express
+agreement or commitment, however denominated, not to enforce a patent
+(such as an express permission to practice a patent or covenant not to
+sue for patent infringement). To "grant" such a patent license to a
+party means to make such an agreement or commitment not to enforce a
+patent against the party.
+
+ If you convey a covered work, knowingly relying on a patent license,
+and the Corresponding Source of the work is not available for anyone
+to copy, free of charge and under the terms of this License, through a
+publicly available network server or other readily accessible means,
+then you must either (1) cause the Corresponding Source to be so
+available, or (2) arrange to deprive yourself of the benefit of the
+patent license for this particular work, or (3) arrange, in a manner
+consistent with the requirements of this License, to extend the patent
+license to downstream recipients. "Knowingly relying" means you have
+actual knowledge that, but for the patent license, your conveying the
+covered work in a country, or your recipient's use of the covered work
+in a country, would infringe one or more identifiable patents in that
+country that you have reason to believe are valid.
+
+ If, pursuant to or in connection with a single transaction or
+arrangement, you convey, or propagate by procuring conveyance of, a
+covered work, and grant a patent license to some of the parties
+receiving the covered work authorizing them to use, propagate, modify
+or convey a specific copy of the covered work, then the patent license
+you grant is automatically extended to all recipients of the covered
+work and works based on it.
+
+ A patent license is "discriminatory" if it does not include within
+the scope of its coverage, prohibits the exercise of, or is
+conditioned on the non-exercise of one or more of the rights that are
+specifically granted under this License. You may not convey a covered
+work if you are a party to an arrangement with a third party that is
+in the business of distributing software, under which you make payment
+to the third party based on the extent of your activity of conveying
+the work, and under which the third party grants, to any of the
+parties who would receive the covered work from you, a discriminatory
+patent license (a) in connection with copies of the covered work
+conveyed by you (or copies made from those copies), or (b) primarily
+for and in connection with specific products or compilations that
+contain the covered work, unless you entered into that arrangement,
+or that patent license was granted, prior to 28 March 2007.
+
+ Nothing in this License shall be construed as excluding or limiting
+any implied license or other defenses to infringement that may
+otherwise be available to you under applicable patent law.
+
+ 12. No Surrender of Others' Freedom.
+
+ If conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License. If you cannot convey a
+covered work so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you may
+not convey it at all. For example, if you agree to terms that obligate you
+to collect a royalty for further conveying from those to whom you convey
+the Program, the only way you could satisfy both those terms and this
+License would be to refrain entirely from conveying the Program.
+
+ 13. Use with the GNU Affero General Public License.
+
+ Notwithstanding any other provision of this License, you have
+permission to link or combine any covered work with a work licensed
+under version 3 of the GNU Affero General Public License into a single
+combined work, and to convey the resulting work. The terms of this
+License will continue to apply to the part which is the covered work,
+but the special requirements of the GNU Affero General Public License,
+section 13, concerning interaction through a network will apply to the
+combination as such.
+
+ 14. Revised Versions of this License.
+
+ The Free Software Foundation may publish revised and/or new versions of
+the GNU General Public License from time to time. Such new versions will
+be similar in spirit to the present version, but may differ in detail to
+address new problems or concerns.
+
+ Each version is given a distinguishing version number. If the
+Program specifies that a certain numbered version of the GNU General
+Public License "or any later version" applies to it, you have the
+option of following the terms and conditions either of that numbered
+version or of any later version published by the Free Software
+Foundation. If the Program does not specify a version number of the
+GNU General Public License, you may choose any version ever published
+by the Free Software Foundation.
+
+ If the Program specifies that a proxy can decide which future
+versions of the GNU General Public License can be used, that proxy's
+public statement of acceptance of a version permanently authorizes you
+to choose that version for the Program.
+
+ Later license versions may give you additional or different
+permissions. However, no additional obligations are imposed on any
+author or copyright holder as a result of your choosing to follow a
+later version.
+
+ 15. Disclaimer of Warranty.
+
+ THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY
+APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT
+HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY
+OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO,
+THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM
+IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF
+ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
+
+ 16. Limitation of Liability.
+
+ IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS
+THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY
+GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE
+USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF
+DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD
+PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS),
+EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF
+SUCH DAMAGES.
+
+ 17. Interpretation of Sections 15 and 16.
+
+ If the disclaimer of warranty and limitation of liability provided
+above cannot be given local legal effect according to their terms,
+reviewing courts shall apply local law that most closely approximates
+an absolute waiver of all civil liability in connection with the
+Program, unless a warranty or assumption of liability accompanies a
+copy of the Program in return for a fee.
+
+ END OF TERMS AND CONDITIONS
+
+ How to Apply These Terms to Your New Programs
+
+ If you develop a new program, and you want it to be of the greatest
+possible use to the public, the best way to achieve this is to make it
+free software which everyone can redistribute and change under these terms.
+
+ To do so, attach the following notices to the program. It is safest
+to attach them to the start of each source file to most effectively
+state the exclusion of warranty; and each file should have at least
+the "copyright" line and a pointer to where the full notice is found.
+
+
+ Copyright (C)
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see .
+
+Also add information on how to contact you by electronic and paper mail.
+
+ If the program does terminal interaction, make it output a short
+notice like this when it starts in an interactive mode:
+
+ Copyright (C)
+ This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
+ This is free software, and you are welcome to redistribute it
+ under certain conditions; type `show c' for details.
+
+The hypothetical commands `show w' and `show c' should show the appropriate
+parts of the General Public License. Of course, your program's commands
+might be different; for a GUI interface, you would use an "about box".
+
+ You should also get your employer (if you work as a programmer) or school,
+if any, to sign a "copyright disclaimer" for the program, if necessary.
+For more information on this, and how to apply and follow the GNU GPL, see
+.
+
+ The GNU General Public License does not permit incorporating your program
+into proprietary programs. If your program is a subroutine library, you
+may consider it more useful to permit linking proprietary applications with
+the library. If this is what you want to do, use the GNU Lesser General
+Public License instead of this License. But first, please read
+.
\ No newline at end of file
diff --git a/modules/sale_payment/MANIFEST.in b/modules/sale_payment/MANIFEST.in
new file mode 100644
index 0000000000..e88b2348a3
--- /dev/null
+++ b/modules/sale_payment/MANIFEST.in
@@ -0,0 +1,5 @@
+include CHANGELOG
+include COPYRIGHT
+include LICENSE
+include README.rst
+include doc/*
diff --git a/modules/sale_payment/README.rst b/modules/sale_payment/README.rst
new file mode 120000
index 0000000000..176d9c2695
--- /dev/null
+++ b/modules/sale_payment/README.rst
@@ -0,0 +1 @@
+doc/index.rst
\ No newline at end of file
diff --git a/modules/sale_payment/__init__.py b/modules/sale_payment/__init__.py
new file mode 100644
index 0000000000..f44e97c876
--- /dev/null
+++ b/modules/sale_payment/__init__.py
@@ -0,0 +1,14 @@
+# This file is part of Tryton. The COPYRIGHT file at the top level of
+# this repository contains the full copyright notices and license terms.
+from trytond.pool import Pool
+
+from . import account
+from . import sale
+
+
+def register():
+ Pool.register(
+ sale.Sale,
+ account.Payment,
+ account.Invoice,
+ module='sale_payment', type_='model')
diff --git a/modules/sale_payment/account.py b/modules/sale_payment/account.py
new file mode 100644
index 0000000000..7dd93bb83a
--- /dev/null
+++ b/modules/sale_payment/account.py
@@ -0,0 +1,202 @@
+# This file is part of Tryton. The COPYRIGHT file at the top level of
+# this repository contains the full copyright notices and license terms.
+import functools
+from decimal import Decimal
+
+from trytond.i18n import gettext
+from trytond.model import fields
+from trytond.pool import Pool, PoolMeta
+
+from trytond.modules.account_payment.exceptions import PaymentValidationError
+
+
+def sale_payment_confirm(func):
+ @functools.wraps(func)
+ def wrapper(cls, payments, *args, **kwargs):
+ pool = Pool()
+ Sale = pool.get('sale.sale')
+
+ result = func(cls, payments, *args, **kwargs)
+
+ sales = {p.origin for p in payments
+ if isinstance(p.origin, Sale)}
+ sales = Sale.browse(sales) # optimize cache
+ Sale.payment_confirm(sales)
+
+ return result
+ return wrapper
+
+
+class Payment(metaclass=PoolMeta):
+ __name__ = 'account.payment'
+
+ @classmethod
+ def _get_origin(cls):
+ return super(Payment, cls)._get_origin() + ['sale.sale']
+
+ @fields.depends('origin')
+ def on_change_origin(self):
+ pool = Pool()
+ Sale = pool.get('sale.sale')
+ try:
+ super().on_change_origin()
+ except AttributeError:
+ pass
+ if self.origin and isinstance(self.origin, Sale):
+ sale = self.origin
+ party = (
+ getattr(sale, 'invoice_party', None)
+ or getattr(sale, 'party', None))
+ if party:
+ self.party = party
+ sale_amount = getattr(sale, 'total_amount', None)
+ payment_amount = sum(
+ (p.amount for p in getattr(sale, 'payments', [])
+ if p.state != 'failed'),
+ Decimal(0))
+ if sale_amount is not None:
+ self.kind = 'receivable' if sale_amount > 0 else 'payable'
+ self.amount = abs(sale_amount) - payment_amount
+ currency = getattr(sale, 'currency', None)
+ if currency is not None:
+ self.currency = currency
+
+ @classmethod
+ def validate(cls, payments):
+ pool = Pool()
+ Sale = pool.get('sale.sale')
+ super(Payment, cls).validate(payments)
+ for payment in payments:
+ if isinstance(payment.origin, Sale):
+ payment.check_sale_state()
+
+ def check_sale_state(self):
+ assert isinstance(self.origin, Pool().get('sale.sale'))
+ if self.state == 'succeeded':
+ # Do not prevent succeeding payment
+ return
+ if self.state != 'failed' and self.origin.state == 'draft':
+ raise PaymentValidationError(
+ gettext('sale_payment.msg_payment_sale_draft',
+ sale=self.origin.rec_name,
+ payment=self.rec_name))
+ elif self.state == 'draft' and self.origin.state == 'cancelled':
+ raise PaymentValidationError(
+ gettext('sale_payment.msg_payment_sale_cancel',
+ sale=self.origin.rec_name,
+ payment=self.rec_name))
+
+ @classmethod
+ def create(cls, vlist):
+ payments = super(Payment, cls).create(vlist)
+ cls.trigger_authorized([p for p in payments if p.is_authorized])
+ return payments
+
+ @classmethod
+ def write(cls, *args):
+ payments = sum(args[0:None:2], [])
+ unauthorized = {p for p in payments if not p.is_authorized}
+ super(Payment, cls).write(*args)
+ authorized = {p for p in payments if p.is_authorized}
+ cls.trigger_authorized(cls.browse(unauthorized & authorized))
+
+ @property
+ def is_authorized(self): # TODO: move to account_payment
+ return self.state == 'succeeded'
+
+ @classmethod
+ @sale_payment_confirm
+ def trigger_authorized(cls, payments):
+ pass
+
+
+class Invoice(metaclass=PoolMeta):
+ __name__ = 'account.invoice'
+
+ def add_payments(self, payments=None):
+ "Add payments from sales lines to pay"
+ if payments is None:
+ payments = []
+ else:
+ payments = payments[:]
+ for sale in self.sales:
+ payments.extend(sale.payments)
+
+ # Knapsack problem:
+ # simple heuristic by trying to fill biggest amount first.
+ payments.sort(key=lambda p: p.amount)
+ lines_to_pay = sorted(
+ self.lines_to_pay, key=lambda l: l.payment_amount)
+ for line in lines_to_pay:
+ if line.reconciliation:
+ continue
+ payment_amount = line.payment_amount
+ for payment in payments:
+ if payment.line or payment.state == 'failed':
+ continue
+ if ((payment.kind == 'receivable' and line.credit > 0)
+ or (payment.kind == 'payable' and line.debit > 0)):
+ continue
+ if payment.party != line.party:
+ continue
+ if (getattr(payment, 'account', None)
+ and payment.account != line.account):
+ continue
+ if payment.amount <= payment_amount:
+ payment.line = line
+ if hasattr(payment, 'account'):
+ payment.account = None
+ payment_amount -= payment.amount
+ return payments
+
+ def reconcile_payments(self):
+ pool = Pool()
+ Payment = pool.get('account.payment')
+ Line = pool.get('account.move.line')
+ if not hasattr(Payment, 'clearing_move'):
+ return
+ to_reconcile = []
+ for line in self.lines_to_pay:
+ if line.reconciliation:
+ continue
+ lines = [line]
+ for payment in line.payments:
+ if payment.state == 'succeeded' and payment.clearing_move:
+ for pline in payment.clearing_move.lines:
+ if (pline.account == line.account
+ and not pline.reconciliation):
+ lines.append(pline)
+ if not sum(l.debit - l.credit for l in lines):
+ to_reconcile.append(lines)
+ for lines in to_reconcile:
+ Line.reconcile(lines)
+
+ @classmethod
+ def _post(cls, invoices):
+ pool = Pool()
+ Payment = pool.get('account.payment')
+ Move = pool.get('account.move')
+
+ super()._post(invoices)
+
+ payments = []
+ for invoice in invoices:
+ payments.extend(invoice.add_payments())
+ if payments:
+ Payment.save(payments)
+ if hasattr(Payment, 'clearing_move'):
+ moves = []
+ for payment in payments:
+ if payment.state == 'succeeded':
+ # Ensure clearing move is created as succeed may happen
+ # before the payment has a line.
+ move = payment.create_clearing_move()
+ if move:
+ moves.append(move)
+ if moves:
+ Move.save(moves)
+ Payment.write(*sum((([m.origin], {'clearing_move': m.id})
+ for m in moves), ()))
+
+ for invoice in invoices:
+ invoice.reconcile_payments()
diff --git a/modules/sale_payment/doc/index.rst b/modules/sale_payment/doc/index.rst
new file mode 100644
index 0000000000..62fe13f85d
--- /dev/null
+++ b/modules/sale_payment/doc/index.rst
@@ -0,0 +1,15 @@
+Sale Payment Module
+###################
+
+The sale_payment module extends *Sale* to allow payments prior to the creation
+of any invoice.
+
+A field *Payments* is added on the sale which can be filled in quotation state.
+The sale can not be reset to draft or cancelled if there are no failed payment
+linked.
+
+The payment authorization of the full sale amount is used as confirmation of
+the sale.
+
+When an invoice from a sale is posted, its payments are used to pay invoice's
+*Lines to Pay*.
diff --git a/modules/sale_payment/locale/bg.po b/modules/sale_payment/locale/bg.po
new file mode 100644
index 0000000000..c51b26bc48
--- /dev/null
+++ b/modules/sale_payment/locale/bg.po
@@ -0,0 +1,31 @@
+#
+msgid ""
+msgstr "Content-Type: text/plain; charset=utf-8\n"
+
+msgctxt "field:sale.sale,payments:"
+msgid "Payments"
+msgstr ""
+
+msgctxt "model:ir.action,name:act_payments_relate"
+msgid "Payments"
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_payment_sale_cancel"
+msgid ""
+"You cannot use sale \"%(sale)s\" on payment \"%(payment)s\" because it is a "
+"cancelled sale."
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_payment_sale_draft"
+msgid ""
+"You cannot use sale \"%(sale)s\" on payment \"%(payment)s\" because it is a "
+"draft sale."
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_sale_cancel_payment"
+msgid "You cannot cancel sale \"%(sale)s\" because it has payments."
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_sale_draft_payment"
+msgid "You cannot reset to draft sale \"%(sale)s\" because it has payments."
+msgstr ""
diff --git a/modules/sale_payment/locale/ca.po b/modules/sale_payment/locale/ca.po
new file mode 100644
index 0000000000..90ff95492e
--- /dev/null
+++ b/modules/sale_payment/locale/ca.po
@@ -0,0 +1,35 @@
+#
+msgid ""
+msgstr "Content-Type: text/plain; charset=utf-8\n"
+
+msgctxt "field:sale.sale,payments:"
+msgid "Payments"
+msgstr "Cobraments"
+
+msgctxt "model:ir.action,name:act_payments_relate"
+msgid "Payments"
+msgstr "Cobraments"
+
+msgctxt "model:ir.message,text:msg_payment_sale_cancel"
+msgid ""
+"You cannot use sale \"%(sale)s\" on payment \"%(payment)s\" because it is a "
+"cancelled sale."
+msgstr ""
+"No podeu utilitzar la venda \"%(sale)s\" al pagament \"%(payment)s\" perquè "
+"és una venda cancel·lada."
+
+msgctxt "model:ir.message,text:msg_payment_sale_draft"
+msgid ""
+"You cannot use sale \"%(sale)s\" on payment \"%(payment)s\" because it is a "
+"draft sale."
+msgstr ""
+"No podeu utilitzar la venda \"%(sale)s\" al pagament \"%(payment)s\" perquè "
+"és una venda en esborrany."
+
+msgctxt "model:ir.message,text:msg_sale_cancel_payment"
+msgid "You cannot cancel sale \"%(sale)s\" because it has payments."
+msgstr "No podeu cancel·lar la venda \"%(sale)s\" perquè té pagaments."
+
+msgctxt "model:ir.message,text:msg_sale_draft_payment"
+msgid "You cannot reset to draft sale \"%(sale)s\" because it has payments."
+msgstr "No podeu restablir a esborrany la venda \"%(sale)s\" perquè té pagaments."
diff --git a/modules/sale_payment/locale/cs.po b/modules/sale_payment/locale/cs.po
new file mode 100644
index 0000000000..c51b26bc48
--- /dev/null
+++ b/modules/sale_payment/locale/cs.po
@@ -0,0 +1,31 @@
+#
+msgid ""
+msgstr "Content-Type: text/plain; charset=utf-8\n"
+
+msgctxt "field:sale.sale,payments:"
+msgid "Payments"
+msgstr ""
+
+msgctxt "model:ir.action,name:act_payments_relate"
+msgid "Payments"
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_payment_sale_cancel"
+msgid ""
+"You cannot use sale \"%(sale)s\" on payment \"%(payment)s\" because it is a "
+"cancelled sale."
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_payment_sale_draft"
+msgid ""
+"You cannot use sale \"%(sale)s\" on payment \"%(payment)s\" because it is a "
+"draft sale."
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_sale_cancel_payment"
+msgid "You cannot cancel sale \"%(sale)s\" because it has payments."
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_sale_draft_payment"
+msgid "You cannot reset to draft sale \"%(sale)s\" because it has payments."
+msgstr ""
diff --git a/modules/sale_payment/locale/de.po b/modules/sale_payment/locale/de.po
new file mode 100644
index 0000000000..e8a29d8ea6
--- /dev/null
+++ b/modules/sale_payment/locale/de.po
@@ -0,0 +1,39 @@
+#
+msgid ""
+msgstr "Content-Type: text/plain; charset=utf-8\n"
+
+msgctxt "field:sale.sale,payments:"
+msgid "Payments"
+msgstr "Zahlungen"
+
+msgctxt "model:ir.action,name:act_payments_relate"
+msgid "Payments"
+msgstr "Zahlungen"
+
+msgctxt "model:ir.message,text:msg_payment_sale_cancel"
+msgid ""
+"You cannot use sale \"%(sale)s\" on payment \"%(payment)s\" because it is a "
+"cancelled sale."
+msgstr ""
+"Der Verkauf \"%(sale)s\" kann nicht auf Zahlung \"%(payment)s\" verwendet "
+"werden, da der Verkauf annulliert wurde."
+
+msgctxt "model:ir.message,text:msg_payment_sale_draft"
+msgid ""
+"You cannot use sale \"%(sale)s\" on payment \"%(payment)s\" because it is a "
+"draft sale."
+msgstr ""
+"Der Verkauf \"%(sale)s\" kann nicht auf Zahlung \"%(payment)s\" verwendet "
+"werden, weil der Verkauf im Entwurfsstatus ist."
+
+msgctxt "model:ir.message,text:msg_sale_cancel_payment"
+msgid "You cannot cancel sale \"%(sale)s\" because it has payments."
+msgstr ""
+"Der Verkauf \"%(sale)s\" kann nicht annulliert werden, weil es zugehörige "
+"Zahlungen gibt."
+
+msgctxt "model:ir.message,text:msg_sale_draft_payment"
+msgid "You cannot reset to draft sale \"%(sale)s\" because it has payments."
+msgstr ""
+"Der Verkauf \"%(sale)s\" kann nicht auf den Entwurfsstatus zurückgesetzt "
+"werden, weil es zu ihm gehörende Zahlungen gibt."
diff --git a/modules/sale_payment/locale/es.po b/modules/sale_payment/locale/es.po
new file mode 100644
index 0000000000..3e3608f2cd
--- /dev/null
+++ b/modules/sale_payment/locale/es.po
@@ -0,0 +1,35 @@
+#
+msgid ""
+msgstr "Content-Type: text/plain; charset=utf-8\n"
+
+msgctxt "field:sale.sale,payments:"
+msgid "Payments"
+msgstr "Cobros"
+
+msgctxt "model:ir.action,name:act_payments_relate"
+msgid "Payments"
+msgstr "Cobros"
+
+msgctxt "model:ir.message,text:msg_payment_sale_cancel"
+msgid ""
+"You cannot use sale \"%(sale)s\" on payment \"%(payment)s\" because it is a "
+"cancelled sale."
+msgstr ""
+"No puede utilizar la venta \"%(sale)s\" en el pago \"%(payment)s\" porque es"
+" una venta cancelada."
+
+msgctxt "model:ir.message,text:msg_payment_sale_draft"
+msgid ""
+"You cannot use sale \"%(sale)s\" on payment \"%(payment)s\" because it is a "
+"draft sale."
+msgstr ""
+"No puede usar la venta \"%(sale)s\" en el pago \"%(payment)s\" porque es una"
+" venta en borrador."
+
+msgctxt "model:ir.message,text:msg_sale_cancel_payment"
+msgid "You cannot cancel sale \"%(sale)s\" because it has payments."
+msgstr "No puede cancelar la venta \"%(sale)s\" porque tiene pagos."
+
+msgctxt "model:ir.message,text:msg_sale_draft_payment"
+msgid "You cannot reset to draft sale \"%(sale)s\" because it has payments."
+msgstr "No puede restablecer a borrador la venta \"%(sale)s\" porque tiene pagos."
diff --git a/modules/sale_payment/locale/es_419.po b/modules/sale_payment/locale/es_419.po
new file mode 100644
index 0000000000..c51b26bc48
--- /dev/null
+++ b/modules/sale_payment/locale/es_419.po
@@ -0,0 +1,31 @@
+#
+msgid ""
+msgstr "Content-Type: text/plain; charset=utf-8\n"
+
+msgctxt "field:sale.sale,payments:"
+msgid "Payments"
+msgstr ""
+
+msgctxt "model:ir.action,name:act_payments_relate"
+msgid "Payments"
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_payment_sale_cancel"
+msgid ""
+"You cannot use sale \"%(sale)s\" on payment \"%(payment)s\" because it is a "
+"cancelled sale."
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_payment_sale_draft"
+msgid ""
+"You cannot use sale \"%(sale)s\" on payment \"%(payment)s\" because it is a "
+"draft sale."
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_sale_cancel_payment"
+msgid "You cannot cancel sale \"%(sale)s\" because it has payments."
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_sale_draft_payment"
+msgid "You cannot reset to draft sale \"%(sale)s\" because it has payments."
+msgstr ""
diff --git a/modules/sale_payment/locale/et.po b/modules/sale_payment/locale/et.po
new file mode 100644
index 0000000000..67422a2080
--- /dev/null
+++ b/modules/sale_payment/locale/et.po
@@ -0,0 +1,38 @@
+#
+msgid ""
+msgstr "Content-Type: text/plain; charset=utf-8\n"
+
+msgctxt "field:sale.sale,payments:"
+msgid "Payments"
+msgstr "Laekumised"
+
+#, fuzzy
+msgctxt "model:ir.action,name:act_payments_relate"
+msgid "Payments"
+msgstr "Laekumised"
+
+msgctxt "model:ir.message,text:msg_payment_sale_cancel"
+msgid ""
+"You cannot use sale \"%(sale)s\" on payment \"%(payment)s\" because it is a "
+"cancelled sale."
+msgstr ""
+"Ei saa kasutada laekumisel \"%(payment)s\" müüki \"%(sale)s\", kuna see on "
+"tühistatud."
+
+msgctxt "model:ir.message,text:msg_payment_sale_draft"
+msgid ""
+"You cannot use sale \"%(sale)s\" on payment \"%(payment)s\" because it is a "
+"draft sale."
+msgstr ""
+"Ei saa kasutada laekumisel \"%(payment)s\" müüki \"%(sale)s\", kuna see on "
+"mustand."
+
+msgctxt "model:ir.message,text:msg_sale_cancel_payment"
+msgid "You cannot cancel sale \"%(sale)s\" because it has payments."
+msgstr "Ei saa tühistada müüki \"%(sale)s\", kuna sellega on seotud laekumised."
+
+msgctxt "model:ir.message,text:msg_sale_draft_payment"
+msgid "You cannot reset to draft sale \"%(sale)s\" because it has payments."
+msgstr ""
+"Ei saa muuta müüki \"%(sale)s\" mustandiks, kuna sellega on seotud "
+"laekumised."
diff --git a/modules/sale_payment/locale/fa.po b/modules/sale_payment/locale/fa.po
new file mode 100644
index 0000000000..396957ce77
--- /dev/null
+++ b/modules/sale_payment/locale/fa.po
@@ -0,0 +1,38 @@
+#
+msgid ""
+msgstr "Content-Type: text/plain; charset=utf-8\n"
+
+msgctxt "field:sale.sale,payments:"
+msgid "Payments"
+msgstr "پرداخت ها"
+
+#, fuzzy
+msgctxt "model:ir.action,name:act_payments_relate"
+msgid "Payments"
+msgstr "پرداخت ها"
+
+msgctxt "model:ir.message,text:msg_payment_sale_cancel"
+msgid ""
+"You cannot use sale \"%(sale)s\" on payment \"%(payment)s\" because it is a "
+"cancelled sale."
+msgstr ""
+"شما نمیتوانید از فروش :\"%(sale)s\"روی پرداخت :\"%(payment)s\" استفاده کنید،"
+" زیرا این یک فروش لغو شده است."
+
+msgctxt "model:ir.message,text:msg_payment_sale_draft"
+msgid ""
+"You cannot use sale \"%(sale)s\" on payment \"%(payment)s\" because it is a "
+"draft sale."
+msgstr ""
+"شما نمیتوانید از فروش :\"%(sale)s\"روی پرداخت :\"%(payment)s\" استفاده کنید،"
+" زیرا این یک فروش پیش نویس است."
+
+msgctxt "model:ir.message,text:msg_sale_cancel_payment"
+msgid "You cannot cancel sale \"%(sale)s\" because it has payments."
+msgstr "شما نمیتوانید فروش :\"%(sale)s\"راحذف کنید، چرا که پرداخت شده است."
+
+msgctxt "model:ir.message,text:msg_sale_draft_payment"
+msgid "You cannot reset to draft sale \"%(sale)s\" because it has payments."
+msgstr ""
+"شما نمیتوانید حالت فروش :\"%(sale)s\" را به پیش نویس بازنشانی کنید، چرا که "
+"پرداخت شده است."
diff --git a/modules/sale_payment/locale/fi.po b/modules/sale_payment/locale/fi.po
new file mode 100644
index 0000000000..c51b26bc48
--- /dev/null
+++ b/modules/sale_payment/locale/fi.po
@@ -0,0 +1,31 @@
+#
+msgid ""
+msgstr "Content-Type: text/plain; charset=utf-8\n"
+
+msgctxt "field:sale.sale,payments:"
+msgid "Payments"
+msgstr ""
+
+msgctxt "model:ir.action,name:act_payments_relate"
+msgid "Payments"
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_payment_sale_cancel"
+msgid ""
+"You cannot use sale \"%(sale)s\" on payment \"%(payment)s\" because it is a "
+"cancelled sale."
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_payment_sale_draft"
+msgid ""
+"You cannot use sale \"%(sale)s\" on payment \"%(payment)s\" because it is a "
+"draft sale."
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_sale_cancel_payment"
+msgid "You cannot cancel sale \"%(sale)s\" because it has payments."
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_sale_draft_payment"
+msgid "You cannot reset to draft sale \"%(sale)s\" because it has payments."
+msgstr ""
diff --git a/modules/sale_payment/locale/fr.po b/modules/sale_payment/locale/fr.po
new file mode 100644
index 0000000000..f2f5076ac7
--- /dev/null
+++ b/modules/sale_payment/locale/fr.po
@@ -0,0 +1,38 @@
+#
+msgid ""
+msgstr "Content-Type: text/plain; charset=utf-8\n"
+
+msgctxt "field:sale.sale,payments:"
+msgid "Payments"
+msgstr "Paiements"
+
+msgctxt "model:ir.action,name:act_payments_relate"
+msgid "Payments"
+msgstr "Paiements"
+
+msgctxt "model:ir.message,text:msg_payment_sale_cancel"
+msgid ""
+"You cannot use sale \"%(sale)s\" on payment \"%(payment)s\" because it is a "
+"cancelled sale."
+msgstr ""
+"Vous ne pouvez pas utiliser la vente « %(sale)s » pour le paiement "
+"« %(payment)s » car la vente est annulée."
+
+msgctxt "model:ir.message,text:msg_payment_sale_draft"
+msgid ""
+"You cannot use sale \"%(sale)s\" on payment \"%(payment)s\" because it is a "
+"draft sale."
+msgstr ""
+"Vous ne pouvez pas utiliser la vente « %(sale)s » pour le paiement "
+"« %(payment)s » car la vente est en brouillon."
+
+msgctxt "model:ir.message,text:msg_sale_cancel_payment"
+msgid "You cannot cancel sale \"%(sale)s\" because it has payments."
+msgstr ""
+"Vous ne pouvez pas annuler la vente « %(sale)s » car elle a des paiements."
+
+msgctxt "model:ir.message,text:msg_sale_draft_payment"
+msgid "You cannot reset to draft sale \"%(sale)s\" because it has payments."
+msgstr ""
+"Vous ne pouvez pas réinitialiser à l'état brouillon la vente « %(sale)s » "
+"car elle a des paiements."
diff --git a/modules/sale_payment/locale/hu.po b/modules/sale_payment/locale/hu.po
new file mode 100644
index 0000000000..c51b26bc48
--- /dev/null
+++ b/modules/sale_payment/locale/hu.po
@@ -0,0 +1,31 @@
+#
+msgid ""
+msgstr "Content-Type: text/plain; charset=utf-8\n"
+
+msgctxt "field:sale.sale,payments:"
+msgid "Payments"
+msgstr ""
+
+msgctxt "model:ir.action,name:act_payments_relate"
+msgid "Payments"
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_payment_sale_cancel"
+msgid ""
+"You cannot use sale \"%(sale)s\" on payment \"%(payment)s\" because it is a "
+"cancelled sale."
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_payment_sale_draft"
+msgid ""
+"You cannot use sale \"%(sale)s\" on payment \"%(payment)s\" because it is a "
+"draft sale."
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_sale_cancel_payment"
+msgid "You cannot cancel sale \"%(sale)s\" because it has payments."
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_sale_draft_payment"
+msgid "You cannot reset to draft sale \"%(sale)s\" because it has payments."
+msgstr ""
diff --git a/modules/sale_payment/locale/id.po b/modules/sale_payment/locale/id.po
new file mode 100644
index 0000000000..2cbeccda4c
--- /dev/null
+++ b/modules/sale_payment/locale/id.po
@@ -0,0 +1,39 @@
+#
+msgid ""
+msgstr "Content-Type: text/plain; charset=utf-8\n"
+
+msgctxt "field:sale.sale,payments:"
+msgid "Payments"
+msgstr "Pembayaran"
+
+msgctxt "model:ir.action,name:act_payments_relate"
+msgid "Payments"
+msgstr "Pembayaran"
+
+msgctxt "model:ir.message,text:msg_payment_sale_cancel"
+msgid ""
+"You cannot use sale \"%(sale)s\" on payment \"%(payment)s\" because it is a "
+"cancelled sale."
+msgstr ""
+"Anda tidak dapat menggunakan penjualan \"%(sale)s\" pada pembayaran "
+"\"%(payment)s\" karena ini adalah penjualan yang dibatalkan."
+
+msgctxt "model:ir.message,text:msg_payment_sale_draft"
+msgid ""
+"You cannot use sale \"%(sale)s\" on payment \"%(payment)s\" because it is a "
+"draft sale."
+msgstr ""
+"Anda tidak dapat menggunakan penjualan \"%(sale)s\" pada pembayaran "
+"\"%(payment)s\" karena ini adalah penjualan yang masih dirancang."
+
+msgctxt "model:ir.message,text:msg_sale_cancel_payment"
+msgid "You cannot cancel sale \"%(sale)s\" because it has payments."
+msgstr ""
+"Anda tidak dapat membatalkan penjualan \"%(sale)s\" karena memiliki "
+"pembayaran."
+
+msgctxt "model:ir.message,text:msg_sale_draft_payment"
+msgid "You cannot reset to draft sale \"%(sale)s\" because it has payments."
+msgstr ""
+"Anda tidak dapat mengatur ulang ke konsep penjualan \"%(sale)s\" karena "
+"memiliki pembayaran."
diff --git a/modules/sale_payment/locale/it.po b/modules/sale_payment/locale/it.po
new file mode 100644
index 0000000000..98b3543dc3
--- /dev/null
+++ b/modules/sale_payment/locale/it.po
@@ -0,0 +1,38 @@
+#
+msgid ""
+msgstr "Content-Type: text/plain; charset=utf-8\n"
+
+msgctxt "field:sale.sale,payments:"
+msgid "Payments"
+msgstr "Pagamenti"
+
+#, fuzzy
+msgctxt "model:ir.action,name:act_payments_relate"
+msgid "Payments"
+msgstr "Pagamenti"
+
+msgctxt "model:ir.message,text:msg_payment_sale_cancel"
+msgid ""
+"You cannot use sale \"%(sale)s\" on payment \"%(payment)s\" because it is a "
+"cancelled sale."
+msgstr ""
+"Non è possibile utilizzare la vendita \"%(sale)s\" sul pagamento "
+"\"%(payment)s\" perché è una vendita annullata."
+
+msgctxt "model:ir.message,text:msg_payment_sale_draft"
+msgid ""
+"You cannot use sale \"%(sale)s\" on payment \"%(payment)s\" because it is a "
+"draft sale."
+msgstr ""
+"Non è possibile utilizzare la vendita \"%(sale)s\" sul pagamento "
+"\"%(payment)s\" perché è una bozza di vendita."
+
+msgctxt "model:ir.message,text:msg_sale_cancel_payment"
+msgid "You cannot cancel sale \"%(sale)s\" because it has payments."
+msgstr "Non è possibile annullare la vendita \"%(sale)s\" perché ha pagamenti."
+
+msgctxt "model:ir.message,text:msg_sale_draft_payment"
+msgid "You cannot reset to draft sale \"%(sale)s\" because it has payments."
+msgstr ""
+"Non è possibile annullare la bozza di vendita \"%(sale)s\" perché ha "
+"pagamenti."
diff --git a/modules/sale_payment/locale/lo.po b/modules/sale_payment/locale/lo.po
new file mode 100644
index 0000000000..c51b26bc48
--- /dev/null
+++ b/modules/sale_payment/locale/lo.po
@@ -0,0 +1,31 @@
+#
+msgid ""
+msgstr "Content-Type: text/plain; charset=utf-8\n"
+
+msgctxt "field:sale.sale,payments:"
+msgid "Payments"
+msgstr ""
+
+msgctxt "model:ir.action,name:act_payments_relate"
+msgid "Payments"
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_payment_sale_cancel"
+msgid ""
+"You cannot use sale \"%(sale)s\" on payment \"%(payment)s\" because it is a "
+"cancelled sale."
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_payment_sale_draft"
+msgid ""
+"You cannot use sale \"%(sale)s\" on payment \"%(payment)s\" because it is a "
+"draft sale."
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_sale_cancel_payment"
+msgid "You cannot cancel sale \"%(sale)s\" because it has payments."
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_sale_draft_payment"
+msgid "You cannot reset to draft sale \"%(sale)s\" because it has payments."
+msgstr ""
diff --git a/modules/sale_payment/locale/lt.po b/modules/sale_payment/locale/lt.po
new file mode 100644
index 0000000000..c51b26bc48
--- /dev/null
+++ b/modules/sale_payment/locale/lt.po
@@ -0,0 +1,31 @@
+#
+msgid ""
+msgstr "Content-Type: text/plain; charset=utf-8\n"
+
+msgctxt "field:sale.sale,payments:"
+msgid "Payments"
+msgstr ""
+
+msgctxt "model:ir.action,name:act_payments_relate"
+msgid "Payments"
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_payment_sale_cancel"
+msgid ""
+"You cannot use sale \"%(sale)s\" on payment \"%(payment)s\" because it is a "
+"cancelled sale."
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_payment_sale_draft"
+msgid ""
+"You cannot use sale \"%(sale)s\" on payment \"%(payment)s\" because it is a "
+"draft sale."
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_sale_cancel_payment"
+msgid "You cannot cancel sale \"%(sale)s\" because it has payments."
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_sale_draft_payment"
+msgid "You cannot reset to draft sale \"%(sale)s\" because it has payments."
+msgstr ""
diff --git a/modules/sale_payment/locale/nl.po b/modules/sale_payment/locale/nl.po
new file mode 100644
index 0000000000..d87ebcc328
--- /dev/null
+++ b/modules/sale_payment/locale/nl.po
@@ -0,0 +1,39 @@
+#
+msgid ""
+msgstr "Content-Type: text/plain; charset=utf-8\n"
+
+msgctxt "field:sale.sale,payments:"
+msgid "Payments"
+msgstr "betalingen"
+
+msgctxt "model:ir.action,name:act_payments_relate"
+msgid "Payments"
+msgstr "Betalingen"
+
+msgctxt "model:ir.message,text:msg_payment_sale_cancel"
+msgid ""
+"You cannot use sale \"%(sale)s\" on payment \"%(payment)s\" because it is a "
+"cancelled sale."
+msgstr ""
+"U kunt verkoop \"%(sale)s niet gebruiken bij betaling \"%(payment)s\" omdat "
+"het een geannuleerde verkoop is."
+
+msgctxt "model:ir.message,text:msg_payment_sale_draft"
+msgid ""
+"You cannot use sale \"%(sale)s\" on payment \"%(payment)s\" because it is a "
+"draft sale."
+msgstr ""
+"U kunt verkoop \"%(sale)s niet gebruiken bij betaling \"%(payment)s\" omdat "
+"hij nog in concept status staat."
+
+msgctxt "model:ir.message,text:msg_sale_cancel_payment"
+msgid "You cannot cancel sale \"%(sale)s\" because it has payments."
+msgstr ""
+"U kunt de verkoop \"% (sale)s\" niet annuleren omdat deze een betalingen "
+"heeft."
+
+msgctxt "model:ir.message,text:msg_sale_draft_payment"
+msgid "You cannot reset to draft sale \"%(sale)s\" because it has payments."
+msgstr ""
+"U kunt de verkoop \"%(sale)s\" niet terug zetten naar concept status omdat "
+"deze betalingen heeft."
diff --git a/modules/sale_payment/locale/pl.po b/modules/sale_payment/locale/pl.po
new file mode 100644
index 0000000000..269acdd308
--- /dev/null
+++ b/modules/sale_payment/locale/pl.po
@@ -0,0 +1,32 @@
+#
+msgid ""
+msgstr "Content-Type: text/plain; charset=utf-8\n"
+
+msgctxt "field:sale.sale,payments:"
+msgid "Payments"
+msgstr "Płatności"
+
+#, fuzzy
+msgctxt "model:ir.action,name:act_payments_relate"
+msgid "Payments"
+msgstr "Płatności"
+
+msgctxt "model:ir.message,text:msg_payment_sale_cancel"
+msgid ""
+"You cannot use sale \"%(sale)s\" on payment \"%(payment)s\" because it is a "
+"cancelled sale."
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_payment_sale_draft"
+msgid ""
+"You cannot use sale \"%(sale)s\" on payment \"%(payment)s\" because it is a "
+"draft sale."
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_sale_cancel_payment"
+msgid "You cannot cancel sale \"%(sale)s\" because it has payments."
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_sale_draft_payment"
+msgid "You cannot reset to draft sale \"%(sale)s\" because it has payments."
+msgstr ""
diff --git a/modules/sale_payment/locale/pt.po b/modules/sale_payment/locale/pt.po
new file mode 100644
index 0000000000..4315e682b1
--- /dev/null
+++ b/modules/sale_payment/locale/pt.po
@@ -0,0 +1,32 @@
+#
+msgid ""
+msgstr "Content-Type: text/plain; charset=utf-8\n"
+
+msgctxt "field:sale.sale,payments:"
+msgid "Payments"
+msgstr "Pagamentos"
+
+#, fuzzy
+msgctxt "model:ir.action,name:act_payments_relate"
+msgid "Payments"
+msgstr "Pagamentos"
+
+msgctxt "model:ir.message,text:msg_payment_sale_cancel"
+msgid ""
+"You cannot use sale \"%(sale)s\" on payment \"%(payment)s\" because it is a "
+"cancelled sale."
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_payment_sale_draft"
+msgid ""
+"You cannot use sale \"%(sale)s\" on payment \"%(payment)s\" because it is a "
+"draft sale."
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_sale_cancel_payment"
+msgid "You cannot cancel sale \"%(sale)s\" because it has payments."
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_sale_draft_payment"
+msgid "You cannot reset to draft sale \"%(sale)s\" because it has payments."
+msgstr ""
diff --git a/modules/sale_payment/locale/ro.po b/modules/sale_payment/locale/ro.po
new file mode 100644
index 0000000000..c51b26bc48
--- /dev/null
+++ b/modules/sale_payment/locale/ro.po
@@ -0,0 +1,31 @@
+#
+msgid ""
+msgstr "Content-Type: text/plain; charset=utf-8\n"
+
+msgctxt "field:sale.sale,payments:"
+msgid "Payments"
+msgstr ""
+
+msgctxt "model:ir.action,name:act_payments_relate"
+msgid "Payments"
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_payment_sale_cancel"
+msgid ""
+"You cannot use sale \"%(sale)s\" on payment \"%(payment)s\" because it is a "
+"cancelled sale."
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_payment_sale_draft"
+msgid ""
+"You cannot use sale \"%(sale)s\" on payment \"%(payment)s\" because it is a "
+"draft sale."
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_sale_cancel_payment"
+msgid "You cannot cancel sale \"%(sale)s\" because it has payments."
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_sale_draft_payment"
+msgid "You cannot reset to draft sale \"%(sale)s\" because it has payments."
+msgstr ""
diff --git a/modules/sale_payment/locale/ru.po b/modules/sale_payment/locale/ru.po
new file mode 100644
index 0000000000..c51b26bc48
--- /dev/null
+++ b/modules/sale_payment/locale/ru.po
@@ -0,0 +1,31 @@
+#
+msgid ""
+msgstr "Content-Type: text/plain; charset=utf-8\n"
+
+msgctxt "field:sale.sale,payments:"
+msgid "Payments"
+msgstr ""
+
+msgctxt "model:ir.action,name:act_payments_relate"
+msgid "Payments"
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_payment_sale_cancel"
+msgid ""
+"You cannot use sale \"%(sale)s\" on payment \"%(payment)s\" because it is a "
+"cancelled sale."
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_payment_sale_draft"
+msgid ""
+"You cannot use sale \"%(sale)s\" on payment \"%(payment)s\" because it is a "
+"draft sale."
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_sale_cancel_payment"
+msgid "You cannot cancel sale \"%(sale)s\" because it has payments."
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_sale_draft_payment"
+msgid "You cannot reset to draft sale \"%(sale)s\" because it has payments."
+msgstr ""
diff --git a/modules/sale_payment/locale/sl.po b/modules/sale_payment/locale/sl.po
new file mode 100644
index 0000000000..c51b26bc48
--- /dev/null
+++ b/modules/sale_payment/locale/sl.po
@@ -0,0 +1,31 @@
+#
+msgid ""
+msgstr "Content-Type: text/plain; charset=utf-8\n"
+
+msgctxt "field:sale.sale,payments:"
+msgid "Payments"
+msgstr ""
+
+msgctxt "model:ir.action,name:act_payments_relate"
+msgid "Payments"
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_payment_sale_cancel"
+msgid ""
+"You cannot use sale \"%(sale)s\" on payment \"%(payment)s\" because it is a "
+"cancelled sale."
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_payment_sale_draft"
+msgid ""
+"You cannot use sale \"%(sale)s\" on payment \"%(payment)s\" because it is a "
+"draft sale."
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_sale_cancel_payment"
+msgid "You cannot cancel sale \"%(sale)s\" because it has payments."
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_sale_draft_payment"
+msgid "You cannot reset to draft sale \"%(sale)s\" because it has payments."
+msgstr ""
diff --git a/modules/sale_payment/locale/tr.po b/modules/sale_payment/locale/tr.po
new file mode 100644
index 0000000000..c51b26bc48
--- /dev/null
+++ b/modules/sale_payment/locale/tr.po
@@ -0,0 +1,31 @@
+#
+msgid ""
+msgstr "Content-Type: text/plain; charset=utf-8\n"
+
+msgctxt "field:sale.sale,payments:"
+msgid "Payments"
+msgstr ""
+
+msgctxt "model:ir.action,name:act_payments_relate"
+msgid "Payments"
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_payment_sale_cancel"
+msgid ""
+"You cannot use sale \"%(sale)s\" on payment \"%(payment)s\" because it is a "
+"cancelled sale."
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_payment_sale_draft"
+msgid ""
+"You cannot use sale \"%(sale)s\" on payment \"%(payment)s\" because it is a "
+"draft sale."
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_sale_cancel_payment"
+msgid "You cannot cancel sale \"%(sale)s\" because it has payments."
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_sale_draft_payment"
+msgid "You cannot reset to draft sale \"%(sale)s\" because it has payments."
+msgstr ""
diff --git a/modules/sale_payment/locale/zh_CN.po b/modules/sale_payment/locale/zh_CN.po
new file mode 100644
index 0000000000..c51b26bc48
--- /dev/null
+++ b/modules/sale_payment/locale/zh_CN.po
@@ -0,0 +1,31 @@
+#
+msgid ""
+msgstr "Content-Type: text/plain; charset=utf-8\n"
+
+msgctxt "field:sale.sale,payments:"
+msgid "Payments"
+msgstr ""
+
+msgctxt "model:ir.action,name:act_payments_relate"
+msgid "Payments"
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_payment_sale_cancel"
+msgid ""
+"You cannot use sale \"%(sale)s\" on payment \"%(payment)s\" because it is a "
+"cancelled sale."
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_payment_sale_draft"
+msgid ""
+"You cannot use sale \"%(sale)s\" on payment \"%(payment)s\" because it is a "
+"draft sale."
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_sale_cancel_payment"
+msgid "You cannot cancel sale \"%(sale)s\" because it has payments."
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_sale_draft_payment"
+msgid "You cannot reset to draft sale \"%(sale)s\" because it has payments."
+msgstr ""
diff --git a/modules/sale_payment/message.xml b/modules/sale_payment/message.xml
new file mode 100644
index 0000000000..5080430ffc
--- /dev/null
+++ b/modules/sale_payment/message.xml
@@ -0,0 +1,19 @@
+
+
+
+
+
+ You cannot cancel sale "%(sale)s" because it has payments.
+
+
+ You cannot reset to draft sale "%(sale)s" because it has payments.
+
+
+ You cannot use sale "%(sale)s" on payment "%(payment)s" because it is a draft sale.
+
+
+ You cannot use sale "%(sale)s" on payment "%(payment)s" because it is a cancelled sale.
+
+
+
diff --git a/modules/sale_payment/sale.py b/modules/sale_payment/sale.py
new file mode 100644
index 0000000000..759ee8e6bf
--- /dev/null
+++ b/modules/sale_payment/sale.py
@@ -0,0 +1,78 @@
+# This file is part of Tryton. The COPYRIGHT file at the top level of
+# this repository contains the full copyright notices and license terms.
+import functools
+
+from trytond.i18n import gettext
+from trytond.model import ModelView, Workflow, fields
+from trytond.model.exceptions import AccessError
+from trytond.pool import PoolMeta
+from trytond.pyson import Eval, If, Bool
+
+
+def no_payment(error):
+ def decorator(func):
+ @functools.wraps(func)
+ def wrapper(cls, sales, *args, **kwargs):
+ for sale in sales:
+ if not all((p.state == 'failed' for p in sale.payments)):
+ raise AccessError(gettext(error, sale=sale.rec_name))
+ return func(cls, sales, *args, **kwargs)
+ return wrapper
+ return decorator
+
+
+class Sale(metaclass=PoolMeta):
+ __name__ = 'sale.sale'
+ payments = fields.One2Many(
+ 'account.payment', 'origin', "Payments",
+ domain=[
+ ('company', '=', Eval('company', -1)),
+ If(Eval('total_amount', 0) >= 0,
+ ('kind', '=', 'receivable'),
+ ('kind', '=', 'payable'),
+ ),
+ ('party', '=', If(Bool(Eval('invoice_party')),
+ Eval('invoice_party'), Eval('party'))),
+ ('currency', '=', Eval('currency')),
+ ],
+ states={
+ 'readonly': Eval('state') != 'quotation',
+ },
+ depends=['company', 'total_amount', 'party', 'invoice_party',
+ 'currency', 'state'])
+
+ @classmethod
+ @ModelView.button
+ @Workflow.transition('cancelled')
+ @no_payment('sale_payment.msg_sale_cancel_payment')
+ def cancel(cls, sales):
+ super(Sale, cls).cancel(sales)
+
+ @classmethod
+ @ModelView.button
+ @Workflow.transition('draft')
+ @no_payment('sale_payment.msg_sale_draft_payment')
+ def draft(cls, sales):
+ super(Sale, cls).draft(sales)
+
+ @classmethod
+ def copy(cls, sales, default=None):
+ if default is None:
+ default = {}
+ else:
+ default = default.copy()
+ default.setdefault('payments', None)
+ return super(Sale, cls).copy(sales, default=default)
+
+ @classmethod
+ def payment_confirm(cls, sales):
+ "Confirm the sale based on payment authorization"
+ to_confirm = []
+ for sale in sales:
+ payment_amount = sum(
+ p.amount for p in sale.payments if p.is_authorized)
+ if payment_amount >= sale.total_amount:
+ to_confirm.append(sale)
+ if to_confirm:
+ to_confirm = cls.browse(to_confirm) # optimize cache
+ cls.confirm(to_confirm)
diff --git a/modules/sale_payment/sale.xml b/modules/sale_payment/sale.xml
new file mode 100644
index 0000000000..239934ddcd
--- /dev/null
+++ b/modules/sale_payment/sale.xml
@@ -0,0 +1,23 @@
+
+
+
+
+ sale.sale
+
+ sale_form
+
+
+ Payments
+ account.payment
+
+
+
+ form_relate
+ sale.sale,-1
+
+
+
+
diff --git a/modules/sale_payment/setup.py b/modules/sale_payment/setup.py
new file mode 100755
index 0000000000..dadc6af054
--- /dev/null
+++ b/modules/sale_payment/setup.py
@@ -0,0 +1,151 @@
+#!/usr/bin/env python3
+# This file is part of Tryton. The COPYRIGHT file at the top level of
+# this repository contains the full copyright notices and license terms.
+
+import io
+import os
+import re
+from configparser import ConfigParser
+from setuptools import setup, find_packages
+
+
+def read(fname):
+ return io.open(
+ os.path.join(os.path.dirname(__file__), fname),
+ 'r', encoding='utf-8').read()
+
+
+def get_require_version(name):
+ if minor_version % 2:
+ require = '%s >= %s.%s.dev0, < %s.%s'
+ else:
+ require = '%s >= %s.%s, < %s.%s'
+ require %= (name, major_version, minor_version,
+ major_version, minor_version + 1)
+ return require
+
+
+config = ConfigParser()
+config.read_file(open(os.path.join(os.path.dirname(__file__), 'tryton.cfg')))
+info = dict(config.items('tryton'))
+for key in ('depends', 'extras_depend', 'xml'):
+ if key in info:
+ info[key] = info[key].strip().splitlines()
+version = info.get('version', '0.0.1')
+major_version, minor_version, _ = version.split('.', 2)
+major_version = int(major_version)
+minor_version = int(minor_version)
+name = 'trytond_sale_payment'
+
+download_url = 'http://downloads.tryton.org/%s.%s/' % (
+ major_version, minor_version)
+if minor_version % 2:
+ version = '%s.%s.dev0' % (major_version, minor_version)
+ download_url = (
+ 'hg+http://hg.tryton.org/modules/%s#egg=%s-%s' % (
+ name[8:], name, version))
+local_version = []
+if os.environ.get('CI_JOB_ID'):
+ local_version.append(os.environ['CI_JOB_ID'])
+else:
+ for build in ['CI_BUILD_NUMBER', 'CI_JOB_NUMBER']:
+ if os.environ.get(build):
+ local_version.append(os.environ[build])
+ else:
+ local_version = []
+ break
+if local_version:
+ version += '+' + '.'.join(local_version)
+
+requires = ['python-sql >= 0.4']
+for dep in info.get('depends', []):
+ if not re.match(r'(ir|res)(\W|$)', dep):
+ requires.append(get_require_version('trytond_%s' % dep))
+requires.append(get_require_version('trytond'))
+
+tests_require = [get_require_version('proteus')]
+for dep in ['account_payment_clearing']:
+ tests_require.append(get_require_version('trytond_%s' % dep))
+dependency_links = []
+if minor_version % 2:
+ dependency_links.append(
+ 'https://trydevpi.tryton.org/?local_version='
+ + '.'.join(local_version))
+
+setup(name=name,
+ version=version,
+ description='Tryton module that manage payments on sale',
+ long_description=read('README.rst'),
+ author='Tryton',
+ author_email='bugs@tryton.org',
+ url='http://www.tryton.org/',
+ download_url=download_url,
+ project_urls={
+ "Bug Tracker": 'https://bugs.tryton.org/',
+ "Documentation": 'https://docs.tryton.org/',
+ "Forum": 'https://www.tryton.org/forum',
+ "Source Code": 'https://hg.tryton.org/modules/sale_payment',
+ },
+ keywords='tryton sale payment',
+ package_dir={'trytond.modules.sale_payment': '.'},
+ packages=(
+ ['trytond.modules.sale_payment']
+ + ['trytond.modules.sale_payment.%s' % p for p in find_packages()]
+ ),
+ package_data={
+ 'trytond.modules.sale_payment': (info.get('xml', [])
+ + ['tryton.cfg', 'view/*.xml', 'locale/*.po', '*.fodt',
+ 'icons/*.svg', 'tests/*.rst']),
+ },
+ classifiers=[
+ 'Development Status :: 5 - Production/Stable',
+ 'Environment :: Plugins',
+ 'Framework :: Tryton',
+ 'Intended Audience :: Financial and Insurance Industry',
+ 'Intended Audience :: Legal Industry',
+ 'License :: OSI Approved :: '
+ 'GNU General Public License v3 or later (GPLv3+)',
+ 'Natural Language :: Bulgarian',
+ 'Natural Language :: Catalan',
+ 'Natural Language :: Chinese (Simplified)',
+ 'Natural Language :: Czech',
+ 'Natural Language :: Dutch',
+ 'Natural Language :: English',
+ 'Natural Language :: Finnish',
+ 'Natural Language :: French',
+ 'Natural Language :: German',
+ 'Natural Language :: Hungarian',
+ 'Natural Language :: Indonesian',
+ 'Natural Language :: Italian',
+ 'Natural Language :: Persian',
+ 'Natural Language :: Polish',
+ 'Natural Language :: Portuguese (Brazilian)',
+ 'Natural Language :: Romanian',
+ 'Natural Language :: Russian',
+ 'Natural Language :: Slovenian',
+ 'Natural Language :: Spanish',
+ 'Natural Language :: Turkish',
+ 'Operating System :: OS Independent',
+ 'Programming Language :: Python :: 3',
+ 'Programming Language :: Python :: 3.6',
+ 'Programming Language :: Python :: 3.7',
+ 'Programming Language :: Python :: 3.8',
+ 'Programming Language :: Python :: 3.9',
+ 'Programming Language :: Python :: Implementation :: CPython',
+ 'Programming Language :: Python :: Implementation :: PyPy',
+ 'Topic :: Office/Business',
+ 'Topic :: Office/Business :: Financial :: Accounting',
+ ],
+ license='GPL-3',
+ python_requires='>=3.6',
+ install_requires=requires,
+ dependency_links=dependency_links,
+ zip_safe=False,
+ entry_points="""
+ [trytond.modules]
+ sale_payment = trytond.modules.sale_payment
+ """,
+ test_suite='tests',
+ test_loader='trytond.test_loader:Loader',
+ tests_require=tests_require,
+ )
diff --git a/modules/sale_payment/tests/__init__.py b/modules/sale_payment/tests/__init__.py
new file mode 100644
index 0000000000..966142eee5
--- /dev/null
+++ b/modules/sale_payment/tests/__init__.py
@@ -0,0 +1,9 @@
+# This file is part of Tryton. The COPYRIGHT file at the top level of
+# this repository contains the full copyright notices and license terms.
+
+try:
+ from trytond.modules.sale_payment.tests.test_sale_payment import suite
+except ImportError:
+ from .test_sale_payment import suite
+
+__all__ = ['suite']
diff --git a/modules/sale_payment/tests/scenario_sale_payment.rst b/modules/sale_payment/tests/scenario_sale_payment.rst
new file mode 100644
index 0000000000..7f70015eed
--- /dev/null
+++ b/modules/sale_payment/tests/scenario_sale_payment.rst
@@ -0,0 +1,211 @@
+=====================
+Sale Payment Scenario
+=====================
+
+Imports::
+
+ >>> from decimal import Decimal
+ >>> from proteus import Model, Wizard
+ >>> from trytond.tests.tools import activate_modules
+ >>> from trytond.modules.company.tests.tools import create_company, \
+ ... get_company
+ >>> from trytond.modules.account.tests.tools import create_fiscalyear, \
+ ... create_chart, get_accounts
+ >>> from trytond.modules.account_invoice.tests.tools import \
+ ... set_fiscalyear_invoice_sequences
+
+Activate modules::
+
+ >>> config = activate_modules(['sale_payment', 'account_payment_clearing'])
+
+Create company::
+
+ >>> _ = create_company()
+ >>> company = get_company()
+
+Create fiscal year::
+
+ >>> fiscalyear = set_fiscalyear_invoice_sequences(
+ ... create_fiscalyear(company))
+ >>> fiscalyear.click('create_period')
+
+Create chart of accounts::
+
+ >>> _ = create_chart(company)
+ >>> accounts = get_accounts(company)
+ >>> revenue = accounts['revenue']
+ >>> payable = accounts['payable']
+
+ >>> Account = Model.get('account.account')
+ >>> bank_clearing = Account(parent=payable.parent)
+ >>> bank_clearing.name = 'Bank Clearing'
+ >>> bank_clearing.type = payable.type
+ >>> bank_clearing.reconcile = True
+ >>> bank_clearing.deferral = True
+ >>> bank_clearing.save()
+
+ >>> Journal = Model.get('account.journal')
+ >>> expense, = Journal.find([('code', '=', 'EXP')])
+
+Create payment journal::
+
+ >>> PaymentJournal = Model.get('account.payment.journal')
+ >>> payment_journal = PaymentJournal(name='Manual',
+ ... process_method='manual', clearing_journal=expense,
+ ... clearing_account=bank_clearing)
+ >>> payment_journal.save()
+
+Create parties::
+
+ >>> Party = Model.get('party.party')
+ >>> customer = Party(name='Customer')
+ >>> customer.save()
+
+Default account product::
+
+ >>> AccountConfiguration = Model.get('account.configuration')
+ >>> account_configuration = AccountConfiguration(1)
+ >>> account_configuration.default_category_account_revenue = revenue
+ >>> account_configuration.save()
+
+Create a sale quotation::
+
+ >>> Sale = Model.get('sale.sale')
+ >>> sale = Sale()
+ >>> sale.party = customer
+ >>> sale.invoice_method = 'order'
+ >>> sale_line = sale.lines.new()
+ >>> sale_line.description = "Test"
+ >>> sale_line.quantity = 1.0
+ >>> sale_line.unit_price = Decimal(100)
+ >>> sale.click('quote')
+ >>> sale.total_amount
+ Decimal('100.00')
+ >>> sale.state
+ 'quotation'
+
+Create a partial payment::
+
+ >>> Payment = Model.get('account.payment')
+ >>> payment = Payment()
+ >>> payment.journal = payment_journal
+ >>> payment.kind = 'receivable'
+ >>> payment.party = sale.party
+ >>> payment.origin = sale
+ >>> payment.amount = Decimal('40.00')
+ >>> payment.click('approve')
+ >>> payment.state
+ 'approved'
+
+Attempt to put sale back to draft::
+
+ >>> sale.click('draft') # doctest: +IGNORE_EXCEPTION_DETAIL
+ Traceback (most recent call last):
+ ...
+ AccessError: ...
+ >>> sale.state
+ 'quotation'
+
+Attempt to cancel sale::
+
+ >>> sale.click('cancel') # doctest: +IGNORE_EXCEPTION_DETAIL
+ Traceback (most recent call last):
+ ...
+ AccessError: ...
+ >>> sale.state
+ 'quotation'
+
+Revert sale to draft after failed payment::
+
+ >>> process_payment = Wizard('account.payment.process', [payment])
+ >>> process_payment.execute('process')
+ >>> payment.click('fail')
+ >>> payment.state
+ 'failed'
+ >>> sale.click('draft')
+ >>> sale.state
+ 'draft'
+
+Attempt to add a second payment to draft sale::
+
+ >>> payment = Payment()
+ >>> payment.journal = payment_journal
+ >>> payment.kind = 'receivable'
+ >>> payment.party = sale.party
+ >>> payment.origin = sale
+ >>> payment.amount = Decimal('30.00')
+ >>> payment.save() # doctest: +IGNORE_EXCEPTION_DETAIL
+ Traceback (most recent call last):
+ ...
+ PaymentValidationError: ...
+
+Cancel the sale::
+
+ >>> sale.click('cancel')
+ >>> sale.state
+ 'cancelled'
+
+Attempt to add a second payment to the cancelled sale::
+
+ >>> payment = Payment()
+ >>> payment.journal = payment_journal
+ >>> payment.kind = 'receivable'
+ >>> payment.party = sale.party
+ >>> payment.origin = sale
+ >>> payment.amount = Decimal('30.00')
+ >>> payment.save() # doctest: +IGNORE_EXCEPTION_DETAIL
+ Traceback (most recent call last):
+ ...
+ PaymentValidationError: ...
+
+Revive the sale::
+
+ >>> sale.click('draft')
+ >>> sale.click('quote')
+ >>> sale.state
+ 'quotation'
+
+Change the first payment to succeed::
+
+ >>> payment, = sale.payments
+ >>> payment.click('succeed')
+ >>> sale.state
+ 'quotation'
+
+Create and process a final payment::
+
+ >>> payment = Payment()
+ >>> payment.journal = payment_journal
+ >>> payment.kind = 'receivable'
+ >>> payment.party = sale.party
+ >>> payment.origin = sale
+ >>> payment.amount = Decimal('60.00')
+ >>> payment.click('approve')
+ >>> process_payment = Wizard('account.payment.process', [payment])
+ >>> process_payment.execute('process')
+ >>> payment.click('succeed')
+
+The sale should be processing::
+
+ >>> sale.reload()
+ >>> sale.state
+ 'processing'
+
+Post the invoice and check amount to pay::
+
+ >>> sale.click('process')
+ >>> invoice, = sale.invoices
+ >>> invoice.total_amount
+ Decimal('100.00')
+ >>> invoice.click('post')
+ >>> invoice.amount_to_pay == Decimal(0)
+ True
+ >>> invoice.state
+ 'paid'
+
+Fail one payment and check invoice is no more paid::
+
+ >>> payment.click('fail')
+ >>> invoice.reload()
+ >>> invoice.state
+ 'posted'
diff --git a/modules/sale_payment/tests/test_sale_payment.py b/modules/sale_payment/tests/test_sale_payment.py
new file mode 100644
index 0000000000..ac2361a234
--- /dev/null
+++ b/modules/sale_payment/tests/test_sale_payment.py
@@ -0,0 +1,24 @@
+# This file is part of Tryton. The COPYRIGHT file at the top level of
+# this repository contains the full copyright notices and license terms.
+import unittest
+import doctest
+import trytond.tests.test_tryton
+from trytond.tests.test_tryton import ModuleTestCase
+from trytond.tests.test_tryton import doctest_teardown
+from trytond.tests.test_tryton import doctest_checker
+
+
+class AccountPaymentTestCase(ModuleTestCase):
+ 'Test Sale Payment module'
+ module = 'sale_payment'
+
+
+def suite():
+ suite = trytond.tests.test_tryton.suite()
+ suite.addTests(unittest.TestLoader().loadTestsFromTestCase(
+ AccountPaymentTestCase))
+ suite.addTests(doctest.DocFileSuite('scenario_sale_payment.rst',
+ tearDown=doctest_teardown, encoding='utf-8',
+ checker=doctest_checker,
+ optionflags=doctest.REPORT_ONLY_FIRST_FAILURE))
+ return suite
diff --git a/modules/sale_payment/tox.ini b/modules/sale_payment/tox.ini
new file mode 100644
index 0000000000..197496c0cb
--- /dev/null
+++ b/modules/sale_payment/tox.ini
@@ -0,0 +1,15 @@
+[tox]
+envlist = {py36,py37,py38,py39}-{sqlite,postgresql},pypy3-{sqlite,postgresql}
+
+[testenv]
+commands = {envpython} setup.py test
+deps =
+ {py36,py37,py38,py39}-postgresql: psycopg2 >= 2.5
+ pypy3-postgresql: psycopg2cffi >= 2.5
+ py36-sqlite: sqlitebck
+setenv =
+ sqlite: TRYTOND_DATABASE_URI={env:SQLITE_URI:sqlite://}
+ postgresql: TRYTOND_DATABASE_URI={env:POSTGRESQL_URI:postgresql://}
+ sqlite: DB_NAME={env:SQLITE_NAME::memory:}
+ postgresql: DB_NAME={env:POSTGRESQL_NAME:test}
+install_command = pip install --pre --find-links https://trydevpi.tryton.org/?local_version={env:CI_JOB_ID:{env:CI_BUILD_NUMBER}.{env:CI_JOB_NUMBER}} {opts} {packages}
diff --git a/modules/sale_payment/tryton.cfg b/modules/sale_payment/tryton.cfg
new file mode 100644
index 0000000000..f8d71c4380
--- /dev/null
+++ b/modules/sale_payment/tryton.cfg
@@ -0,0 +1,13 @@
+[tryton]
+version=6.0.3
+depends:
+ account_invoice
+ account_payment
+ ir
+ res
+ sale
+extras_depend:
+ account_payment_clearing
+xml:
+ sale.xml
+ message.xml
diff --git a/modules/sale_payment/view/sale_form.xml b/modules/sale_payment/view/sale_form.xml
new file mode 100644
index 0000000000..48b6053295
--- /dev/null
+++ b/modules/sale_payment/view/sale_form.xml
@@ -0,0 +1,8 @@
+
+
+
+
+
+
+
diff --git a/modules/sale_price_list/.drone.yml b/modules/sale_price_list/.drone.yml
new file mode 100644
index 0000000000..2049d30a49
--- /dev/null
+++ b/modules/sale_price_list/.drone.yml
@@ -0,0 +1,68 @@
+clone:
+ hg:
+ image: plugins/hg
+ environment:
+ - HG_SHARE_POOL=/root/.cache/hg
+ volumes:
+ - cache:/root/.cache
+
+pipeline:
+ tox:
+ image: ${IMAGE}
+ environment:
+ - CFLAGS=-O0
+ - DB_CACHE=/cache
+ - TOX_TESTENV_PASSENV=CFLAGS DB_CACHE CI_BUILD_NUMBER CI_JOB_NUMBER CI_JOB_ID
+ - POSTGRESQL_URI=postgresql://postgres@postgresql:5432/
+ commands:
+ - echo "[extensions]" >> /root/.hgrc
+ - echo "hgext.share =" >> /root/.hgrc
+ - echo "[share]" >> /root/.hgrc
+ - echo "pool = /root/.cache/hg" >> /root/.hgrc
+ - pip install tox
+ - tox -e "${TOXENV}-${DATABASE}"
+ volumes:
+ - cache:/root/.cache
+ check_dist:
+ image: ${IMAGE}
+ commands:
+ - pip install twine
+ - python setup.py sdist
+ - twine check dist/*
+
+services:
+ postgresql:
+ image: postgres
+ environment:
+ - POSTGRES_HOST_AUTH_METHOD=trust
+ command: "-c fsync=off -c synchronous_commit=off -c full_page_writes=off"
+ when:
+ matrix:
+ DATABASE: postgresql
+
+matrix:
+ include:
+ - IMAGE: python:3.6
+ TOXENV: py36
+ DATABASE: sqlite
+ - IMAGE: python:3.6
+ TOXENV: py36
+ DATABASE: postgresql
+ - IMAGE: python:3.7
+ TOXENV: py37
+ DATABASE: sqlite
+ - IMAGE: python:3.7
+ TOXENV: py37
+ DATABASE: postgresql
+ - IMAGE: python:3.8
+ TOXENV: py38
+ DATABASE: sqlite
+ - IMAGE: python:3.8
+ TOXENV: py38
+ DATABASE: postgresql
+ - IMAGE: python:3.9
+ TOXENV: py39
+ DATABASE: sqlite
+ - IMAGE: python:3.9
+ TOXENV: py39
+ DATABASE: postgresql
diff --git a/modules/sale_price_list/.flake8 b/modules/sale_price_list/.flake8
new file mode 100644
index 0000000000..fa6b4f66d1
--- /dev/null
+++ b/modules/sale_price_list/.flake8
@@ -0,0 +1,2 @@
+[flake8]
+ignore=E123,E124,E126,E128,E741,W503
diff --git a/modules/sale_price_list/CHANGELOG b/modules/sale_price_list/CHANGELOG
new file mode 100644
index 0000000000..c989af5f08
--- /dev/null
+++ b/modules/sale_price_list/CHANGELOG
@@ -0,0 +1,79 @@
+Version 6.0.1 - 2021-08-05
+* Bug fixes (see mercurial logs for details)
+
+Version 6.0.0 - 2021-05-03
+* Bug fixes (see mercurial logs for details)
+
+Version 5.8.0 - 2020-11-02
+* Bug fixes (see mercurial logs for details)
+* Remove support for Python 3.5
+
+Version 5.6.0 - 2020-05-04
+* Bug fixes (see mercurial logs for details)
+
+Version 5.4.0 - 2019-11-04
+* Bug fixes (see mercurial logs for details)
+* Add product sale unit to price list
+
+Version 5.2.0 - 2019-05-06
+* Bug fixes (see mercurial logs for details)
+
+Version 5.0.0 - 2018-10-01
+* Bug fixes (see mercurial logs for details)
+* Remove support for Python 2.7
+
+Version 4.8.0 - 2018-04-23
+* Bug fixes (see mercurial logs for details)
+
+Version 4.6.0 - 2017-10-30
+* Bug fixes (see mercurial logs for details)
+* Compute sale price with price list even if there is no customer
+
+Version 4.4.0 - 2017-05-01
+* Bug fixes (see mercurial logs for details)
+
+Version 4.2.0 - 2016-11-28
+* Bug fixes (see mercurial logs for details)
+
+Version 4.0.0 - 2016-05-02
+* Bug fixes (see mercurial logs for details)
+* Add Python3 support
+
+Version 3.8.0 - 2015-11-02
+* Bug fixes (see mercurial logs for details)
+
+Version 3.6.0 - 2015-04-20
+* Bug fixes (see mercurial logs for details)
+* Add support for PyPy
+Version 3.4.0 - 2014-10-20
+* Bug fixes (see mercurial logs for details)
+
+Version 3.2.0 - 2014-04-21
+* Bug fixes (see mercurial logs for details)
+
+Version 3.0.0 - 2013-10-21
+* Bug fixes (see mercurial logs for details)
+
+Version 2.8.0 - 2013-04-22
+* Bug fixes (see mercurial logs for details)
+
+Version 2.6.0 - 2012-10-22
+* Bug fixes (see mercurial logs for details)
+
+Version 2.4.0 - 2012-04-24
+* Bug fixes (see mercurial logs for details)
+
+Version 2.2.0 - 2011-10-25
+* Bug fixes (see mercurial logs for details)
+
+Version 2.0.0 - 2011-04-27
+* Bug fixes (see mercurial logs for details)
+
+Version 1.8.0 - 2010-11-01
+* Bug fixes (see mercurial logs for details)
+
+Version 1.6.0 - 2010-05-13
+* Bug fixes (see mercurial logs for details)
+
+Version 1.4.0 - 2009-10-19
+* Initial release
diff --git a/modules/sale_price_list/COPYRIGHT b/modules/sale_price_list/COPYRIGHT
new file mode 100644
index 0000000000..9bd027b13a
--- /dev/null
+++ b/modules/sale_price_list/COPYRIGHT
@@ -0,0 +1,16 @@
+Copyright (C) 2009-2021 Cédric Krier.
+Copyright (C) 2009-2012 Bertrand Chenal.
+Copyright (C) 2009-2021 B2CK SPRL.
+
+This program is free software: you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation, either version 3 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program. If not, see .
diff --git a/modules/sale_price_list/LICENSE b/modules/sale_price_list/LICENSE
new file mode 100644
index 0000000000..94a9ed024d
--- /dev/null
+++ b/modules/sale_price_list/LICENSE
@@ -0,0 +1,674 @@
+ GNU GENERAL PUBLIC LICENSE
+ Version 3, 29 June 2007
+
+ Copyright (C) 2007 Free Software Foundation, Inc.
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+ Preamble
+
+ The GNU General Public License is a free, copyleft license for
+software and other kinds of works.
+
+ The licenses for most software and other practical works are designed
+to take away your freedom to share and change the works. By contrast,
+the GNU General Public License is intended to guarantee your freedom to
+share and change all versions of a program--to make sure it remains free
+software for all its users. We, the Free Software Foundation, use the
+GNU General Public License for most of our software; it applies also to
+any other work released this way by its authors. You can apply it to
+your programs, too.
+
+ When we speak of free software, we are referring to freedom, not
+price. Our General Public Licenses are designed to make sure that you
+have the freedom to distribute copies of free software (and charge for
+them if you wish), that you receive source code or can get it if you
+want it, that you can change the software or use pieces of it in new
+free programs, and that you know you can do these things.
+
+ To protect your rights, we need to prevent others from denying you
+these rights or asking you to surrender the rights. Therefore, you have
+certain responsibilities if you distribute copies of the software, or if
+you modify it: responsibilities to respect the freedom of others.
+
+ For example, if you distribute copies of such a program, whether
+gratis or for a fee, you must pass on to the recipients the same
+freedoms that you received. You must make sure that they, too, receive
+or can get the source code. And you must show them these terms so they
+know their rights.
+
+ Developers that use the GNU GPL protect your rights with two steps:
+(1) assert copyright on the software, and (2) offer you this License
+giving you legal permission to copy, distribute and/or modify it.
+
+ For the developers' and authors' protection, the GPL clearly explains
+that there is no warranty for this free software. For both users' and
+authors' sake, the GPL requires that modified versions be marked as
+changed, so that their problems will not be attributed erroneously to
+authors of previous versions.
+
+ Some devices are designed to deny users access to install or run
+modified versions of the software inside them, although the manufacturer
+can do so. This is fundamentally incompatible with the aim of
+protecting users' freedom to change the software. The systematic
+pattern of such abuse occurs in the area of products for individuals to
+use, which is precisely where it is most unacceptable. Therefore, we
+have designed this version of the GPL to prohibit the practice for those
+products. If such problems arise substantially in other domains, we
+stand ready to extend this provision to those domains in future versions
+of the GPL, as needed to protect the freedom of users.
+
+ Finally, every program is threatened constantly by software patents.
+States should not allow patents to restrict development and use of
+software on general-purpose computers, but in those that do, we wish to
+avoid the special danger that patents applied to a free program could
+make it effectively proprietary. To prevent this, the GPL assures that
+patents cannot be used to render the program non-free.
+
+ The precise terms and conditions for copying, distribution and
+modification follow.
+
+ TERMS AND CONDITIONS
+
+ 0. Definitions.
+
+ "This License" refers to version 3 of the GNU General Public License.
+
+ "Copyright" also means copyright-like laws that apply to other kinds of
+works, such as semiconductor masks.
+
+ "The Program" refers to any copyrightable work licensed under this
+License. Each licensee is addressed as "you". "Licensees" and
+"recipients" may be individuals or organizations.
+
+ To "modify" a work means to copy from or adapt all or part of the work
+in a fashion requiring copyright permission, other than the making of an
+exact copy. The resulting work is called a "modified version" of the
+earlier work or a work "based on" the earlier work.
+
+ A "covered work" means either the unmodified Program or a work based
+on the Program.
+
+ To "propagate" a work means to do anything with it that, without
+permission, would make you directly or secondarily liable for
+infringement under applicable copyright law, except executing it on a
+computer or modifying a private copy. Propagation includes copying,
+distribution (with or without modification), making available to the
+public, and in some countries other activities as well.
+
+ To "convey" a work means any kind of propagation that enables other
+parties to make or receive copies. Mere interaction with a user through
+a computer network, with no transfer of a copy, is not conveying.
+
+ An interactive user interface displays "Appropriate Legal Notices"
+to the extent that it includes a convenient and prominently visible
+feature that (1) displays an appropriate copyright notice, and (2)
+tells the user that there is no warranty for the work (except to the
+extent that warranties are provided), that licensees may convey the
+work under this License, and how to view a copy of this License. If
+the interface presents a list of user commands or options, such as a
+menu, a prominent item in the list meets this criterion.
+
+ 1. Source Code.
+
+ The "source code" for a work means the preferred form of the work
+for making modifications to it. "Object code" means any non-source
+form of a work.
+
+ A "Standard Interface" means an interface that either is an official
+standard defined by a recognized standards body, or, in the case of
+interfaces specified for a particular programming language, one that
+is widely used among developers working in that language.
+
+ The "System Libraries" of an executable work include anything, other
+than the work as a whole, that (a) is included in the normal form of
+packaging a Major Component, but which is not part of that Major
+Component, and (b) serves only to enable use of the work with that
+Major Component, or to implement a Standard Interface for which an
+implementation is available to the public in source code form. A
+"Major Component", in this context, means a major essential component
+(kernel, window system, and so on) of the specific operating system
+(if any) on which the executable work runs, or a compiler used to
+produce the work, or an object code interpreter used to run it.
+
+ The "Corresponding Source" for a work in object code form means all
+the source code needed to generate, install, and (for an executable
+work) run the object code and to modify the work, including scripts to
+control those activities. However, it does not include the work's
+System Libraries, or general-purpose tools or generally available free
+programs which are used unmodified in performing those activities but
+which are not part of the work. For example, Corresponding Source
+includes interface definition files associated with source files for
+the work, and the source code for shared libraries and dynamically
+linked subprograms that the work is specifically designed to require,
+such as by intimate data communication or control flow between those
+subprograms and other parts of the work.
+
+ The Corresponding Source need not include anything that users
+can regenerate automatically from other parts of the Corresponding
+Source.
+
+ The Corresponding Source for a work in source code form is that
+same work.
+
+ 2. Basic Permissions.
+
+ All rights granted under this License are granted for the term of
+copyright on the Program, and are irrevocable provided the stated
+conditions are met. This License explicitly affirms your unlimited
+permission to run the unmodified Program. The output from running a
+covered work is covered by this License only if the output, given its
+content, constitutes a covered work. This License acknowledges your
+rights of fair use or other equivalent, as provided by copyright law.
+
+ You may make, run and propagate covered works that you do not
+convey, without conditions so long as your license otherwise remains
+in force. You may convey covered works to others for the sole purpose
+of having them make modifications exclusively for you, or provide you
+with facilities for running those works, provided that you comply with
+the terms of this License in conveying all material for which you do
+not control copyright. Those thus making or running the covered works
+for you must do so exclusively on your behalf, under your direction
+and control, on terms that prohibit them from making any copies of
+your copyrighted material outside their relationship with you.
+
+ Conveying under any other circumstances is permitted solely under
+the conditions stated below. Sublicensing is not allowed; section 10
+makes it unnecessary.
+
+ 3. Protecting Users' Legal Rights From Anti-Circumvention Law.
+
+ No covered work shall be deemed part of an effective technological
+measure under any applicable law fulfilling obligations under article
+11 of the WIPO copyright treaty adopted on 20 December 1996, or
+similar laws prohibiting or restricting circumvention of such
+measures.
+
+ When you convey a covered work, you waive any legal power to forbid
+circumvention of technological measures to the extent such circumvention
+is effected by exercising rights under this License with respect to
+the covered work, and you disclaim any intention to limit operation or
+modification of the work as a means of enforcing, against the work's
+users, your or third parties' legal rights to forbid circumvention of
+technological measures.
+
+ 4. Conveying Verbatim Copies.
+
+ You may convey verbatim copies of the Program's source code as you
+receive it, in any medium, provided that you conspicuously and
+appropriately publish on each copy an appropriate copyright notice;
+keep intact all notices stating that this License and any
+non-permissive terms added in accord with section 7 apply to the code;
+keep intact all notices of the absence of any warranty; and give all
+recipients a copy of this License along with the Program.
+
+ You may charge any price or no price for each copy that you convey,
+and you may offer support or warranty protection for a fee.
+
+ 5. Conveying Modified Source Versions.
+
+ You may convey a work based on the Program, or the modifications to
+produce it from the Program, in the form of source code under the
+terms of section 4, provided that you also meet all of these conditions:
+
+ a) The work must carry prominent notices stating that you modified
+ it, and giving a relevant date.
+
+ b) The work must carry prominent notices stating that it is
+ released under this License and any conditions added under section
+ 7. This requirement modifies the requirement in section 4 to
+ "keep intact all notices".
+
+ c) You must license the entire work, as a whole, under this
+ License to anyone who comes into possession of a copy. This
+ License will therefore apply, along with any applicable section 7
+ additional terms, to the whole of the work, and all its parts,
+ regardless of how they are packaged. This License gives no
+ permission to license the work in any other way, but it does not
+ invalidate such permission if you have separately received it.
+
+ d) If the work has interactive user interfaces, each must display
+ Appropriate Legal Notices; however, if the Program has interactive
+ interfaces that do not display Appropriate Legal Notices, your
+ work need not make them do so.
+
+ A compilation of a covered work with other separate and independent
+works, which are not by their nature extensions of the covered work,
+and which are not combined with it such as to form a larger program,
+in or on a volume of a storage or distribution medium, is called an
+"aggregate" if the compilation and its resulting copyright are not
+used to limit the access or legal rights of the compilation's users
+beyond what the individual works permit. Inclusion of a covered work
+in an aggregate does not cause this License to apply to the other
+parts of the aggregate.
+
+ 6. Conveying Non-Source Forms.
+
+ You may convey a covered work in object code form under the terms
+of sections 4 and 5, provided that you also convey the
+machine-readable Corresponding Source under the terms of this License,
+in one of these ways:
+
+ a) Convey the object code in, or embodied in, a physical product
+ (including a physical distribution medium), accompanied by the
+ Corresponding Source fixed on a durable physical medium
+ customarily used for software interchange.
+
+ b) Convey the object code in, or embodied in, a physical product
+ (including a physical distribution medium), accompanied by a
+ written offer, valid for at least three years and valid for as
+ long as you offer spare parts or customer support for that product
+ model, to give anyone who possesses the object code either (1) a
+ copy of the Corresponding Source for all the software in the
+ product that is covered by this License, on a durable physical
+ medium customarily used for software interchange, for a price no
+ more than your reasonable cost of physically performing this
+ conveying of source, or (2) access to copy the
+ Corresponding Source from a network server at no charge.
+
+ c) Convey individual copies of the object code with a copy of the
+ written offer to provide the Corresponding Source. This
+ alternative is allowed only occasionally and noncommercially, and
+ only if you received the object code with such an offer, in accord
+ with subsection 6b.
+
+ d) Convey the object code by offering access from a designated
+ place (gratis or for a charge), and offer equivalent access to the
+ Corresponding Source in the same way through the same place at no
+ further charge. You need not require recipients to copy the
+ Corresponding Source along with the object code. If the place to
+ copy the object code is a network server, the Corresponding Source
+ may be on a different server (operated by you or a third party)
+ that supports equivalent copying facilities, provided you maintain
+ clear directions next to the object code saying where to find the
+ Corresponding Source. Regardless of what server hosts the
+ Corresponding Source, you remain obligated to ensure that it is
+ available for as long as needed to satisfy these requirements.
+
+ e) Convey the object code using peer-to-peer transmission, provided
+ you inform other peers where the object code and Corresponding
+ Source of the work are being offered to the general public at no
+ charge under subsection 6d.
+
+ A separable portion of the object code, whose source code is excluded
+from the Corresponding Source as a System Library, need not be
+included in conveying the object code work.
+
+ A "User Product" is either (1) a "consumer product", which means any
+tangible personal property which is normally used for personal, family,
+or household purposes, or (2) anything designed or sold for incorporation
+into a dwelling. In determining whether a product is a consumer product,
+doubtful cases shall be resolved in favor of coverage. For a particular
+product received by a particular user, "normally used" refers to a
+typical or common use of that class of product, regardless of the status
+of the particular user or of the way in which the particular user
+actually uses, or expects or is expected to use, the product. A product
+is a consumer product regardless of whether the product has substantial
+commercial, industrial or non-consumer uses, unless such uses represent
+the only significant mode of use of the product.
+
+ "Installation Information" for a User Product means any methods,
+procedures, authorization keys, or other information required to install
+and execute modified versions of a covered work in that User Product from
+a modified version of its Corresponding Source. The information must
+suffice to ensure that the continued functioning of the modified object
+code is in no case prevented or interfered with solely because
+modification has been made.
+
+ If you convey an object code work under this section in, or with, or
+specifically for use in, a User Product, and the conveying occurs as
+part of a transaction in which the right of possession and use of the
+User Product is transferred to the recipient in perpetuity or for a
+fixed term (regardless of how the transaction is characterized), the
+Corresponding Source conveyed under this section must be accompanied
+by the Installation Information. But this requirement does not apply
+if neither you nor any third party retains the ability to install
+modified object code on the User Product (for example, the work has
+been installed in ROM).
+
+ The requirement to provide Installation Information does not include a
+requirement to continue to provide support service, warranty, or updates
+for a work that has been modified or installed by the recipient, or for
+the User Product in which it has been modified or installed. Access to a
+network may be denied when the modification itself materially and
+adversely affects the operation of the network or violates the rules and
+protocols for communication across the network.
+
+ Corresponding Source conveyed, and Installation Information provided,
+in accord with this section must be in a format that is publicly
+documented (and with an implementation available to the public in
+source code form), and must require no special password or key for
+unpacking, reading or copying.
+
+ 7. Additional Terms.
+
+ "Additional permissions" are terms that supplement the terms of this
+License by making exceptions from one or more of its conditions.
+Additional permissions that are applicable to the entire Program shall
+be treated as though they were included in this License, to the extent
+that they are valid under applicable law. If additional permissions
+apply only to part of the Program, that part may be used separately
+under those permissions, but the entire Program remains governed by
+this License without regard to the additional permissions.
+
+ When you convey a copy of a covered work, you may at your option
+remove any additional permissions from that copy, or from any part of
+it. (Additional permissions may be written to require their own
+removal in certain cases when you modify the work.) You may place
+additional permissions on material, added by you to a covered work,
+for which you have or can give appropriate copyright permission.
+
+ Notwithstanding any other provision of this License, for material you
+add to a covered work, you may (if authorized by the copyright holders of
+that material) supplement the terms of this License with terms:
+
+ a) Disclaiming warranty or limiting liability differently from the
+ terms of sections 15 and 16 of this License; or
+
+ b) Requiring preservation of specified reasonable legal notices or
+ author attributions in that material or in the Appropriate Legal
+ Notices displayed by works containing it; or
+
+ c) Prohibiting misrepresentation of the origin of that material, or
+ requiring that modified versions of such material be marked in
+ reasonable ways as different from the original version; or
+
+ d) Limiting the use for publicity purposes of names of licensors or
+ authors of the material; or
+
+ e) Declining to grant rights under trademark law for use of some
+ trade names, trademarks, or service marks; or
+
+ f) Requiring indemnification of licensors and authors of that
+ material by anyone who conveys the material (or modified versions of
+ it) with contractual assumptions of liability to the recipient, for
+ any liability that these contractual assumptions directly impose on
+ those licensors and authors.
+
+ All other non-permissive additional terms are considered "further
+restrictions" within the meaning of section 10. If the Program as you
+received it, or any part of it, contains a notice stating that it is
+governed by this License along with a term that is a further
+restriction, you may remove that term. If a license document contains
+a further restriction but permits relicensing or conveying under this
+License, you may add to a covered work material governed by the terms
+of that license document, provided that the further restriction does
+not survive such relicensing or conveying.
+
+ If you add terms to a covered work in accord with this section, you
+must place, in the relevant source files, a statement of the
+additional terms that apply to those files, or a notice indicating
+where to find the applicable terms.
+
+ Additional terms, permissive or non-permissive, may be stated in the
+form of a separately written license, or stated as exceptions;
+the above requirements apply either way.
+
+ 8. Termination.
+
+ You may not propagate or modify a covered work except as expressly
+provided under this License. Any attempt otherwise to propagate or
+modify it is void, and will automatically terminate your rights under
+this License (including any patent licenses granted under the third
+paragraph of section 11).
+
+ However, if you cease all violation of this License, then your
+license from a particular copyright holder is reinstated (a)
+provisionally, unless and until the copyright holder explicitly and
+finally terminates your license, and (b) permanently, if the copyright
+holder fails to notify you of the violation by some reasonable means
+prior to 60 days after the cessation.
+
+ Moreover, your license from a particular copyright holder is
+reinstated permanently if the copyright holder notifies you of the
+violation by some reasonable means, this is the first time you have
+received notice of violation of this License (for any work) from that
+copyright holder, and you cure the violation prior to 30 days after
+your receipt of the notice.
+
+ Termination of your rights under this section does not terminate the
+licenses of parties who have received copies or rights from you under
+this License. If your rights have been terminated and not permanently
+reinstated, you do not qualify to receive new licenses for the same
+material under section 10.
+
+ 9. Acceptance Not Required for Having Copies.
+
+ You are not required to accept this License in order to receive or
+run a copy of the Program. Ancillary propagation of a covered work
+occurring solely as a consequence of using peer-to-peer transmission
+to receive a copy likewise does not require acceptance. However,
+nothing other than this License grants you permission to propagate or
+modify any covered work. These actions infringe copyright if you do
+not accept this License. Therefore, by modifying or propagating a
+covered work, you indicate your acceptance of this License to do so.
+
+ 10. Automatic Licensing of Downstream Recipients.
+
+ Each time you convey a covered work, the recipient automatically
+receives a license from the original licensors, to run, modify and
+propagate that work, subject to this License. You are not responsible
+for enforcing compliance by third parties with this License.
+
+ An "entity transaction" is a transaction transferring control of an
+organization, or substantially all assets of one, or subdividing an
+organization, or merging organizations. If propagation of a covered
+work results from an entity transaction, each party to that
+transaction who receives a copy of the work also receives whatever
+licenses to the work the party's predecessor in interest had or could
+give under the previous paragraph, plus a right to possession of the
+Corresponding Source of the work from the predecessor in interest, if
+the predecessor has it or can get it with reasonable efforts.
+
+ You may not impose any further restrictions on the exercise of the
+rights granted or affirmed under this License. For example, you may
+not impose a license fee, royalty, or other charge for exercise of
+rights granted under this License, and you may not initiate litigation
+(including a cross-claim or counterclaim in a lawsuit) alleging that
+any patent claim is infringed by making, using, selling, offering for
+sale, or importing the Program or any portion of it.
+
+ 11. Patents.
+
+ A "contributor" is a copyright holder who authorizes use under this
+License of the Program or a work on which the Program is based. The
+work thus licensed is called the contributor's "contributor version".
+
+ A contributor's "essential patent claims" are all patent claims
+owned or controlled by the contributor, whether already acquired or
+hereafter acquired, that would be infringed by some manner, permitted
+by this License, of making, using, or selling its contributor version,
+but do not include claims that would be infringed only as a
+consequence of further modification of the contributor version. For
+purposes of this definition, "control" includes the right to grant
+patent sublicenses in a manner consistent with the requirements of
+this License.
+
+ Each contributor grants you a non-exclusive, worldwide, royalty-free
+patent license under the contributor's essential patent claims, to
+make, use, sell, offer for sale, import and otherwise run, modify and
+propagate the contents of its contributor version.
+
+ In the following three paragraphs, a "patent license" is any express
+agreement or commitment, however denominated, not to enforce a patent
+(such as an express permission to practice a patent or covenant not to
+sue for patent infringement). To "grant" such a patent license to a
+party means to make such an agreement or commitment not to enforce a
+patent against the party.
+
+ If you convey a covered work, knowingly relying on a patent license,
+and the Corresponding Source of the work is not available for anyone
+to copy, free of charge and under the terms of this License, through a
+publicly available network server or other readily accessible means,
+then you must either (1) cause the Corresponding Source to be so
+available, or (2) arrange to deprive yourself of the benefit of the
+patent license for this particular work, or (3) arrange, in a manner
+consistent with the requirements of this License, to extend the patent
+license to downstream recipients. "Knowingly relying" means you have
+actual knowledge that, but for the patent license, your conveying the
+covered work in a country, or your recipient's use of the covered work
+in a country, would infringe one or more identifiable patents in that
+country that you have reason to believe are valid.
+
+ If, pursuant to or in connection with a single transaction or
+arrangement, you convey, or propagate by procuring conveyance of, a
+covered work, and grant a patent license to some of the parties
+receiving the covered work authorizing them to use, propagate, modify
+or convey a specific copy of the covered work, then the patent license
+you grant is automatically extended to all recipients of the covered
+work and works based on it.
+
+ A patent license is "discriminatory" if it does not include within
+the scope of its coverage, prohibits the exercise of, or is
+conditioned on the non-exercise of one or more of the rights that are
+specifically granted under this License. You may not convey a covered
+work if you are a party to an arrangement with a third party that is
+in the business of distributing software, under which you make payment
+to the third party based on the extent of your activity of conveying
+the work, and under which the third party grants, to any of the
+parties who would receive the covered work from you, a discriminatory
+patent license (a) in connection with copies of the covered work
+conveyed by you (or copies made from those copies), or (b) primarily
+for and in connection with specific products or compilations that
+contain the covered work, unless you entered into that arrangement,
+or that patent license was granted, prior to 28 March 2007.
+
+ Nothing in this License shall be construed as excluding or limiting
+any implied license or other defenses to infringement that may
+otherwise be available to you under applicable patent law.
+
+ 12. No Surrender of Others' Freedom.
+
+ If conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License. If you cannot convey a
+covered work so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you may
+not convey it at all. For example, if you agree to terms that obligate you
+to collect a royalty for further conveying from those to whom you convey
+the Program, the only way you could satisfy both those terms and this
+License would be to refrain entirely from conveying the Program.
+
+ 13. Use with the GNU Affero General Public License.
+
+ Notwithstanding any other provision of this License, you have
+permission to link or combine any covered work with a work licensed
+under version 3 of the GNU Affero General Public License into a single
+combined work, and to convey the resulting work. The terms of this
+License will continue to apply to the part which is the covered work,
+but the special requirements of the GNU Affero General Public License,
+section 13, concerning interaction through a network will apply to the
+combination as such.
+
+ 14. Revised Versions of this License.
+
+ The Free Software Foundation may publish revised and/or new versions of
+the GNU General Public License from time to time. Such new versions will
+be similar in spirit to the present version, but may differ in detail to
+address new problems or concerns.
+
+ Each version is given a distinguishing version number. If the
+Program specifies that a certain numbered version of the GNU General
+Public License "or any later version" applies to it, you have the
+option of following the terms and conditions either of that numbered
+version or of any later version published by the Free Software
+Foundation. If the Program does not specify a version number of the
+GNU General Public License, you may choose any version ever published
+by the Free Software Foundation.
+
+ If the Program specifies that a proxy can decide which future
+versions of the GNU General Public License can be used, that proxy's
+public statement of acceptance of a version permanently authorizes you
+to choose that version for the Program.
+
+ Later license versions may give you additional or different
+permissions. However, no additional obligations are imposed on any
+author or copyright holder as a result of your choosing to follow a
+later version.
+
+ 15. Disclaimer of Warranty.
+
+ THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY
+APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT
+HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY
+OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO,
+THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM
+IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF
+ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
+
+ 16. Limitation of Liability.
+
+ IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS
+THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY
+GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE
+USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF
+DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD
+PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS),
+EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF
+SUCH DAMAGES.
+
+ 17. Interpretation of Sections 15 and 16.
+
+ If the disclaimer of warranty and limitation of liability provided
+above cannot be given local legal effect according to their terms,
+reviewing courts shall apply local law that most closely approximates
+an absolute waiver of all civil liability in connection with the
+Program, unless a warranty or assumption of liability accompanies a
+copy of the Program in return for a fee.
+
+ END OF TERMS AND CONDITIONS
+
+ How to Apply These Terms to Your New Programs
+
+ If you develop a new program, and you want it to be of the greatest
+possible use to the public, the best way to achieve this is to make it
+free software which everyone can redistribute and change under these terms.
+
+ To do so, attach the following notices to the program. It is safest
+to attach them to the start of each source file to most effectively
+state the exclusion of warranty; and each file should have at least
+the "copyright" line and a pointer to where the full notice is found.
+
+
+ Copyright (C)
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see .
+
+Also add information on how to contact you by electronic and paper mail.
+
+ If the program does terminal interaction, make it output a short
+notice like this when it starts in an interactive mode:
+
+ Copyright (C)
+ This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
+ This is free software, and you are welcome to redistribute it
+ under certain conditions; type `show c' for details.
+
+The hypothetical commands `show w' and `show c' should show the appropriate
+parts of the General Public License. Of course, your program's commands
+might be different; for a GUI interface, you would use an "about box".
+
+ You should also get your employer (if you work as a programmer) or school,
+if any, to sign a "copyright disclaimer" for the program, if necessary.
+For more information on this, and how to apply and follow the GNU GPL, see
+.
+
+ The GNU General Public License does not permit incorporating your program
+into proprietary programs. If your program is a subroutine library, you
+may consider it more useful to permit linking proprietary applications with
+the library. If this is what you want to do, use the GNU Lesser General
+Public License instead of this License. But first, please read
+.
diff --git a/modules/sale_price_list/MANIFEST.in b/modules/sale_price_list/MANIFEST.in
new file mode 100644
index 0000000000..e88b2348a3
--- /dev/null
+++ b/modules/sale_price_list/MANIFEST.in
@@ -0,0 +1,5 @@
+include CHANGELOG
+include COPYRIGHT
+include LICENSE
+include README.rst
+include doc/*
diff --git a/modules/sale_price_list/README.rst b/modules/sale_price_list/README.rst
new file mode 120000
index 0000000000..176d9c2695
--- /dev/null
+++ b/modules/sale_price_list/README.rst
@@ -0,0 +1 @@
+doc/index.rst
\ No newline at end of file
diff --git a/modules/sale_price_list/__init__.py b/modules/sale_price_list/__init__.py
new file mode 100644
index 0000000000..c1d528ea1c
--- /dev/null
+++ b/modules/sale_price_list/__init__.py
@@ -0,0 +1,22 @@
+# This file is part of Tryton. The COPYRIGHT file at the top level of
+# this repository contains the full copyright notices and license terms.
+
+from trytond.pool import Pool
+from . import party
+from . import sale
+from . import product
+from . import configuration
+
+
+def register():
+ Pool.register(
+ party.Party,
+ party.PartySalePriceList,
+ sale.Sale,
+ sale.Line,
+ product.Product,
+ product.PriceList,
+ product.SaleContext,
+ configuration.Configuration,
+ configuration.ConfigurationSalePriceList,
+ module='sale_price_list', type_='model')
diff --git a/modules/sale_price_list/configuration.py b/modules/sale_price_list/configuration.py
new file mode 100644
index 0000000000..69914058ce
--- /dev/null
+++ b/modules/sale_price_list/configuration.py
@@ -0,0 +1,31 @@
+# This file is part of Tryton. The COPYRIGHT file at the top level of
+# this repository contains the full copyright notices and license terms.
+from trytond.model import ModelSQL, fields
+from trytond.pyson import Eval
+from trytond.pool import PoolMeta
+from trytond.modules.company.model import (
+ CompanyMultiValueMixin, CompanyValueMixin)
+
+
+class Configuration(CompanyMultiValueMixin, metaclass=PoolMeta):
+ __name__ = 'sale.configuration'
+ sale_price_list = fields.MultiValue(fields.Many2One(
+ 'product.price_list', "Sale Price List",
+ help="The default price list for new parties.",
+ domain=[
+ ('company', '=', Eval('context', {}).get('company', -1)),
+ ],
+ states={
+ 'invisible': ~Eval('context', {}).get('company'),
+ }))
+
+
+class ConfigurationSalePriceList(ModelSQL, CompanyValueMixin):
+ "Sale Configuration Sale PriceList"
+ __name__ = 'sale.configuration.sale_price_list'
+ sale_price_list = fields.Many2One(
+ 'product.price_list', "Sale Price List",
+ domain=[
+ ('company', '=', Eval('company', -1)),
+ ],
+ depends=['company'])
diff --git a/modules/sale_price_list/configuration.xml b/modules/sale_price_list/configuration.xml
new file mode 100644
index 0000000000..1be072a305
--- /dev/null
+++ b/modules/sale_price_list/configuration.xml
@@ -0,0 +1,12 @@
+
+
+
+
+
+ sale.configuration
+
+ configuration_form
+
+
+
diff --git a/modules/sale_price_list/doc/index.rst b/modules/sale_price_list/doc/index.rst
new file mode 100644
index 0000000000..3ff18d66bf
--- /dev/null
+++ b/modules/sale_price_list/doc/index.rst
@@ -0,0 +1,5 @@
+Sale Price List Module
+######################
+
+The sale price list module adds support for price list on sale.
+A price list can be set per party or as default.
diff --git a/modules/sale_price_list/locale/bg.po b/modules/sale_price_list/locale/bg.po
new file mode 100644
index 0000000000..9f512e6e1d
--- /dev/null
+++ b/modules/sale_price_list/locale/bg.po
@@ -0,0 +1,72 @@
+#
+msgid ""
+msgstr "Content-Type: text/plain; charset=utf-8\n"
+
+msgctxt "field:party.party,sale_price_list:"
+msgid "Sale Price List"
+msgstr "Ценова листа при продажба"
+
+#, fuzzy
+msgctxt "field:party.party,sale_price_lists:"
+msgid "Sale Price Lists"
+msgstr "Ценова листа при продажба"
+
+msgctxt "field:party.party.sale_price_list,company:"
+msgid "Company"
+msgstr ""
+
+msgctxt "field:party.party.sale_price_list,party:"
+msgid "Party"
+msgstr ""
+
+#, fuzzy
+msgctxt "field:party.party.sale_price_list,sale_price_list:"
+msgid "Sale Price List"
+msgstr "Ценова листа при продажба"
+
+#, fuzzy
+msgctxt "field:product.sale.context,price_list:"
+msgid "Price List"
+msgstr "Ценова листа"
+
+#, fuzzy
+msgctxt "field:sale.configuration,sale_price_list:"
+msgid "Sale Price List"
+msgstr "Ценова листа при продажба"
+
+msgctxt "field:sale.configuration.sale_price_list,company:"
+msgid "Company"
+msgstr ""
+
+#, fuzzy
+msgctxt "field:sale.configuration.sale_price_list,sale_price_list:"
+msgid "Sale Price List"
+msgstr "Ценова листа при продажба"
+
+msgctxt "field:sale.sale,price_list:"
+msgid "Price List"
+msgstr "Ценова листа"
+
+msgctxt "help:party.party,sale_price_list:"
+msgid "The default price list for new sales."
+msgstr ""
+
+msgctxt "help:sale.configuration,sale_price_list:"
+msgid "The default price list for new parties."
+msgstr ""
+
+msgctxt "help:sale.sale,price_list:"
+msgid "Use to compute the unit price of lines."
+msgstr ""
+
+msgctxt "model:party.party.sale_price_list,name:"
+msgid "Party Sale Price List"
+msgstr ""
+
+msgctxt "model:sale.configuration.sale_price_list,name:"
+msgid "Sale Configuration Sale PriceList"
+msgstr ""
+
+msgctxt "selection:product.price_list,unit:"
+msgid "Product Sale"
+msgstr ""
diff --git a/modules/sale_price_list/locale/ca.po b/modules/sale_price_list/locale/ca.po
new file mode 100644
index 0000000000..62043b2ffb
--- /dev/null
+++ b/modules/sale_price_list/locale/ca.po
@@ -0,0 +1,67 @@
+#
+msgid ""
+msgstr "Content-Type: text/plain; charset=utf-8\n"
+
+msgctxt "field:party.party,sale_price_list:"
+msgid "Sale Price List"
+msgstr "Tarifa de venda"
+
+msgctxt "field:party.party,sale_price_lists:"
+msgid "Sale Price Lists"
+msgstr "Tarifes de venda"
+
+msgctxt "field:party.party.sale_price_list,company:"
+msgid "Company"
+msgstr "Empresa"
+
+msgctxt "field:party.party.sale_price_list,party:"
+msgid "Party"
+msgstr "Tercer"
+
+msgctxt "field:party.party.sale_price_list,sale_price_list:"
+msgid "Sale Price List"
+msgstr "Tarifa de venda"
+
+msgctxt "field:product.sale.context,price_list:"
+msgid "Price List"
+msgstr "Tarifa"
+
+msgctxt "field:sale.configuration,sale_price_list:"
+msgid "Sale Price List"
+msgstr "Tarifa de venda"
+
+msgctxt "field:sale.configuration.sale_price_list,company:"
+msgid "Company"
+msgstr "Empresa"
+
+msgctxt "field:sale.configuration.sale_price_list,sale_price_list:"
+msgid "Sale Price List"
+msgstr "Tarifa de venda"
+
+msgctxt "field:sale.sale,price_list:"
+msgid "Price List"
+msgstr "Tarifa"
+
+msgctxt "help:party.party,sale_price_list:"
+msgid "The default price list for new sales."
+msgstr "La tarifa per defecte per les noves vendes."
+
+msgctxt "help:sale.configuration,sale_price_list:"
+msgid "The default price list for new parties."
+msgstr "La tarifa per defecte per als nous tercers."
+
+msgctxt "help:sale.sale,price_list:"
+msgid "Use to compute the unit price of lines."
+msgstr "Utilitza per calcular el preu unitari de les línies."
+
+msgctxt "model:party.party.sale_price_list,name:"
+msgid "Party Sale Price List"
+msgstr "Tarifa de venda per tercer"
+
+msgctxt "model:sale.configuration.sale_price_list,name:"
+msgid "Sale Configuration Sale PriceList"
+msgstr "Configuració de la tarifa de venda"
+
+msgctxt "selection:product.price_list,unit:"
+msgid "Product Sale"
+msgstr "Venda del producte"
diff --git a/modules/sale_price_list/locale/cs.po b/modules/sale_price_list/locale/cs.po
new file mode 100644
index 0000000000..eb38526039
--- /dev/null
+++ b/modules/sale_price_list/locale/cs.po
@@ -0,0 +1,67 @@
+#
+msgid ""
+msgstr "Content-Type: text/plain; charset=utf-8\n"
+
+msgctxt "field:party.party,sale_price_list:"
+msgid "Sale Price List"
+msgstr ""
+
+msgctxt "field:party.party,sale_price_lists:"
+msgid "Sale Price Lists"
+msgstr ""
+
+msgctxt "field:party.party.sale_price_list,company:"
+msgid "Company"
+msgstr ""
+
+msgctxt "field:party.party.sale_price_list,party:"
+msgid "Party"
+msgstr ""
+
+msgctxt "field:party.party.sale_price_list,sale_price_list:"
+msgid "Sale Price List"
+msgstr ""
+
+msgctxt "field:product.sale.context,price_list:"
+msgid "Price List"
+msgstr ""
+
+msgctxt "field:sale.configuration,sale_price_list:"
+msgid "Sale Price List"
+msgstr ""
+
+msgctxt "field:sale.configuration.sale_price_list,company:"
+msgid "Company"
+msgstr ""
+
+msgctxt "field:sale.configuration.sale_price_list,sale_price_list:"
+msgid "Sale Price List"
+msgstr ""
+
+msgctxt "field:sale.sale,price_list:"
+msgid "Price List"
+msgstr ""
+
+msgctxt "help:party.party,sale_price_list:"
+msgid "The default price list for new sales."
+msgstr ""
+
+msgctxt "help:sale.configuration,sale_price_list:"
+msgid "The default price list for new parties."
+msgstr ""
+
+msgctxt "help:sale.sale,price_list:"
+msgid "Use to compute the unit price of lines."
+msgstr ""
+
+msgctxt "model:party.party.sale_price_list,name:"
+msgid "Party Sale Price List"
+msgstr ""
+
+msgctxt "model:sale.configuration.sale_price_list,name:"
+msgid "Sale Configuration Sale PriceList"
+msgstr ""
+
+msgctxt "selection:product.price_list,unit:"
+msgid "Product Sale"
+msgstr ""
diff --git a/modules/sale_price_list/locale/de.po b/modules/sale_price_list/locale/de.po
new file mode 100644
index 0000000000..22cc020998
--- /dev/null
+++ b/modules/sale_price_list/locale/de.po
@@ -0,0 +1,67 @@
+#
+msgid ""
+msgstr "Content-Type: text/plain; charset=utf-8\n"
+
+msgctxt "field:party.party,sale_price_list:"
+msgid "Sale Price List"
+msgstr "Preisliste Verkauf"
+
+msgctxt "field:party.party,sale_price_lists:"
+msgid "Sale Price Lists"
+msgstr "Preisliste Verkauf"
+
+msgctxt "field:party.party.sale_price_list,company:"
+msgid "Company"
+msgstr "Unternehmen"
+
+msgctxt "field:party.party.sale_price_list,party:"
+msgid "Party"
+msgstr "Partei"
+
+msgctxt "field:party.party.sale_price_list,sale_price_list:"
+msgid "Sale Price List"
+msgstr "Preisliste Verkauf"
+
+msgctxt "field:product.sale.context,price_list:"
+msgid "Price List"
+msgstr "Preisliste"
+
+msgctxt "field:sale.configuration,sale_price_list:"
+msgid "Sale Price List"
+msgstr "Preisliste Verkauf"
+
+msgctxt "field:sale.configuration.sale_price_list,company:"
+msgid "Company"
+msgstr "Unternehmen"
+
+msgctxt "field:sale.configuration.sale_price_list,sale_price_list:"
+msgid "Sale Price List"
+msgstr "Preisliste Verkauf"
+
+msgctxt "field:sale.sale,price_list:"
+msgid "Price List"
+msgstr "Preisliste"
+
+msgctxt "help:party.party,sale_price_list:"
+msgid "The default price list for new sales."
+msgstr "Die Standard-Preisliste für neue Verkäufe."
+
+msgctxt "help:sale.configuration,sale_price_list:"
+msgid "The default price list for new parties."
+msgstr "Die Standard-Preisliste für neue Parteien."
+
+msgctxt "help:sale.sale,price_list:"
+msgid "Use to compute the unit price of lines."
+msgstr "Wird für die Berechnung des Einheits-Preises für Positionen genutzt."
+
+msgctxt "model:party.party.sale_price_list,name:"
+msgid "Party Sale Price List"
+msgstr "Preisliste Verkauf für Partei"
+
+msgctxt "model:sale.configuration.sale_price_list,name:"
+msgid "Sale Configuration Sale PriceList"
+msgstr "Einstellungen Verkauf Preisliste"
+
+msgctxt "selection:product.price_list,unit:"
+msgid "Product Sale"
+msgstr "Artikel Verkauf"
diff --git a/modules/sale_price_list/locale/es.po b/modules/sale_price_list/locale/es.po
new file mode 100644
index 0000000000..a57d63f4bd
--- /dev/null
+++ b/modules/sale_price_list/locale/es.po
@@ -0,0 +1,67 @@
+#
+msgid ""
+msgstr "Content-Type: text/plain; charset=utf-8\n"
+
+msgctxt "field:party.party,sale_price_list:"
+msgid "Sale Price List"
+msgstr "Tarifa de venta"
+
+msgctxt "field:party.party,sale_price_lists:"
+msgid "Sale Price Lists"
+msgstr "Tarifas de venta"
+
+msgctxt "field:party.party.sale_price_list,company:"
+msgid "Company"
+msgstr "Empresa"
+
+msgctxt "field:party.party.sale_price_list,party:"
+msgid "Party"
+msgstr "Tercero"
+
+msgctxt "field:party.party.sale_price_list,sale_price_list:"
+msgid "Sale Price List"
+msgstr "Tarifa de venta"
+
+msgctxt "field:product.sale.context,price_list:"
+msgid "Price List"
+msgstr "Tarifa"
+
+msgctxt "field:sale.configuration,sale_price_list:"
+msgid "Sale Price List"
+msgstr "Tarifa de venta"
+
+msgctxt "field:sale.configuration.sale_price_list,company:"
+msgid "Company"
+msgstr "Empresa"
+
+msgctxt "field:sale.configuration.sale_price_list,sale_price_list:"
+msgid "Sale Price List"
+msgstr "Tarifa de venta"
+
+msgctxt "field:sale.sale,price_list:"
+msgid "Price List"
+msgstr "Tarifa"
+
+msgctxt "help:party.party,sale_price_list:"
+msgid "The default price list for new sales."
+msgstr "La tarifa por defecto de las nuevas ventas."
+
+msgctxt "help:sale.configuration,sale_price_list:"
+msgid "The default price list for new parties."
+msgstr "La tarifa por defecto para los nuevos terceros."
+
+msgctxt "help:sale.sale,price_list:"
+msgid "Use to compute the unit price of lines."
+msgstr "Utiliza para calcular el precio unitario de la líneas."
+
+msgctxt "model:party.party.sale_price_list,name:"
+msgid "Party Sale Price List"
+msgstr "Tarifa de venta del tercero"
+
+msgctxt "model:sale.configuration.sale_price_list,name:"
+msgid "Sale Configuration Sale PriceList"
+msgstr "Configuración de la tarifa de venta"
+
+msgctxt "selection:product.price_list,unit:"
+msgid "Product Sale"
+msgstr "Venta del producto"
diff --git a/modules/sale_price_list/locale/es_419.po b/modules/sale_price_list/locale/es_419.po
new file mode 100644
index 0000000000..ed9d06d1c4
--- /dev/null
+++ b/modules/sale_price_list/locale/es_419.po
@@ -0,0 +1,71 @@
+#
+msgid ""
+msgstr "Content-Type: text/plain; charset=utf-8\n"
+
+msgctxt "field:party.party,sale_price_list:"
+msgid "Sale Price List"
+msgstr "Lista de precio de venta"
+
+#, fuzzy
+msgctxt "field:party.party,sale_price_lists:"
+msgid "Sale Price Lists"
+msgstr "Lista de precio de venta"
+
+msgctxt "field:party.party.sale_price_list,company:"
+msgid "Company"
+msgstr ""
+
+msgctxt "field:party.party.sale_price_list,party:"
+msgid "Party"
+msgstr ""
+
+#, fuzzy
+msgctxt "field:party.party.sale_price_list,sale_price_list:"
+msgid "Sale Price List"
+msgstr "Lista de precio de venta"
+
+#, fuzzy
+msgctxt "field:product.sale.context,price_list:"
+msgid "Price List"
+msgstr "Lista de precios"
+
+msgctxt "field:sale.configuration,sale_price_list:"
+msgid "Sale Price List"
+msgstr "Lista de precio de venta"
+
+msgctxt "field:sale.configuration.sale_price_list,company:"
+msgid "Company"
+msgstr ""
+
+#, fuzzy
+msgctxt "field:sale.configuration.sale_price_list,sale_price_list:"
+msgid "Sale Price List"
+msgstr "Lista de precio de venta"
+
+msgctxt "field:sale.sale,price_list:"
+msgid "Price List"
+msgstr "Lista de precios"
+
+msgctxt "help:party.party,sale_price_list:"
+msgid "The default price list for new sales."
+msgstr ""
+
+msgctxt "help:sale.configuration,sale_price_list:"
+msgid "The default price list for new parties."
+msgstr ""
+
+msgctxt "help:sale.sale,price_list:"
+msgid "Use to compute the unit price of lines."
+msgstr ""
+
+msgctxt "model:party.party.sale_price_list,name:"
+msgid "Party Sale Price List"
+msgstr ""
+
+msgctxt "model:sale.configuration.sale_price_list,name:"
+msgid "Sale Configuration Sale PriceList"
+msgstr ""
+
+msgctxt "selection:product.price_list,unit:"
+msgid "Product Sale"
+msgstr ""
diff --git a/modules/sale_price_list/locale/et.po b/modules/sale_price_list/locale/et.po
new file mode 100644
index 0000000000..14ae993183
--- /dev/null
+++ b/modules/sale_price_list/locale/et.po
@@ -0,0 +1,68 @@
+#
+msgid ""
+msgstr "Content-Type: text/plain; charset=utf-8\n"
+
+msgctxt "field:party.party,sale_price_list:"
+msgid "Sale Price List"
+msgstr "Müügi hinnakiri"
+
+msgctxt "field:party.party,sale_price_lists:"
+msgid "Sale Price Lists"
+msgstr "Müügi hinnakirjad"
+
+msgctxt "field:party.party.sale_price_list,company:"
+msgid "Company"
+msgstr "Ettevõte"
+
+msgctxt "field:party.party.sale_price_list,party:"
+msgid "Party"
+msgstr "Osapool"
+
+msgctxt "field:party.party.sale_price_list,sale_price_list:"
+msgid "Sale Price List"
+msgstr "Müügi hinnakiri"
+
+#, fuzzy
+msgctxt "field:product.sale.context,price_list:"
+msgid "Price List"
+msgstr "Hinnakiri"
+
+msgctxt "field:sale.configuration,sale_price_list:"
+msgid "Sale Price List"
+msgstr "Müügi hinnakiri"
+
+msgctxt "field:sale.configuration.sale_price_list,company:"
+msgid "Company"
+msgstr "Ettevõte"
+
+msgctxt "field:sale.configuration.sale_price_list,sale_price_list:"
+msgid "Sale Price List"
+msgstr "Müügi hinnakiri"
+
+msgctxt "field:sale.sale,price_list:"
+msgid "Price List"
+msgstr "Hinnakiri"
+
+msgctxt "help:party.party,sale_price_list:"
+msgid "The default price list for new sales."
+msgstr "Vaikimisi hinnakiri uutele müükidele."
+
+msgctxt "help:sale.configuration,sale_price_list:"
+msgid "The default price list for new parties."
+msgstr "Vaikimisi hinnakiri uutele osapooltele."
+
+msgctxt "help:sale.sale,price_list:"
+msgid "Use to compute the unit price of lines."
+msgstr "Kasuta, et arvestada ridade ühiku hind."
+
+msgctxt "model:party.party.sale_price_list,name:"
+msgid "Party Sale Price List"
+msgstr "Osapoole müügi hinnakiri"
+
+msgctxt "model:sale.configuration.sale_price_list,name:"
+msgid "Sale Configuration Sale PriceList"
+msgstr "Müügi seadistamine müügi hinnakiri"
+
+msgctxt "selection:product.price_list,unit:"
+msgid "Product Sale"
+msgstr ""
diff --git a/modules/sale_price_list/locale/fa.po b/modules/sale_price_list/locale/fa.po
new file mode 100644
index 0000000000..f51a115a1c
--- /dev/null
+++ b/modules/sale_price_list/locale/fa.po
@@ -0,0 +1,68 @@
+#
+msgid ""
+msgstr "Content-Type: text/plain; charset=utf-8\n"
+
+msgctxt "field:party.party,sale_price_list:"
+msgid "Sale Price List"
+msgstr "لیست قیمت فروش"
+
+msgctxt "field:party.party,sale_price_lists:"
+msgid "Sale Price Lists"
+msgstr "لیست های قیمت فروش"
+
+msgctxt "field:party.party.sale_price_list,company:"
+msgid "Company"
+msgstr "شرکت"
+
+msgctxt "field:party.party.sale_price_list,party:"
+msgid "Party"
+msgstr "نهاد/سازمان"
+
+msgctxt "field:party.party.sale_price_list,sale_price_list:"
+msgid "Sale Price List"
+msgstr "لیست قیمت فروش"
+
+#, fuzzy
+msgctxt "field:product.sale.context,price_list:"
+msgid "Price List"
+msgstr "لیست قیمت"
+
+msgctxt "field:sale.configuration,sale_price_list:"
+msgid "Sale Price List"
+msgstr "لیست قیمت فروش"
+
+msgctxt "field:sale.configuration.sale_price_list,company:"
+msgid "Company"
+msgstr "شرکت"
+
+msgctxt "field:sale.configuration.sale_price_list,sale_price_list:"
+msgid "Sale Price List"
+msgstr "لیست قیمت فروش"
+
+msgctxt "field:sale.sale,price_list:"
+msgid "Price List"
+msgstr "لیست قیمت"
+
+msgctxt "help:party.party,sale_price_list:"
+msgid "The default price list for new sales."
+msgstr "لیست قیمت پیش فرض برای فروش های جدید."
+
+msgctxt "help:sale.configuration,sale_price_list:"
+msgid "The default price list for new parties."
+msgstr "لیست قیمت پیش فرض برای نهادها/سازمان های جدید."
+
+msgctxt "help:sale.sale,price_list:"
+msgid "Use to compute the unit price of lines."
+msgstr "برای محاسبه واحد قیمت سطرها استفاده کنید."
+
+msgctxt "model:party.party.sale_price_list,name:"
+msgid "Party Sale Price List"
+msgstr "لیست قیمت فروش نهاد/سازمان"
+
+msgctxt "model:sale.configuration.sale_price_list,name:"
+msgid "Sale Configuration Sale PriceList"
+msgstr "پیکربندی فروش ؛ لیست قیمت فروش"
+
+msgctxt "selection:product.price_list,unit:"
+msgid "Product Sale"
+msgstr ""
diff --git a/modules/sale_price_list/locale/fi.po b/modules/sale_price_list/locale/fi.po
new file mode 100644
index 0000000000..eb38526039
--- /dev/null
+++ b/modules/sale_price_list/locale/fi.po
@@ -0,0 +1,67 @@
+#
+msgid ""
+msgstr "Content-Type: text/plain; charset=utf-8\n"
+
+msgctxt "field:party.party,sale_price_list:"
+msgid "Sale Price List"
+msgstr ""
+
+msgctxt "field:party.party,sale_price_lists:"
+msgid "Sale Price Lists"
+msgstr ""
+
+msgctxt "field:party.party.sale_price_list,company:"
+msgid "Company"
+msgstr ""
+
+msgctxt "field:party.party.sale_price_list,party:"
+msgid "Party"
+msgstr ""
+
+msgctxt "field:party.party.sale_price_list,sale_price_list:"
+msgid "Sale Price List"
+msgstr ""
+
+msgctxt "field:product.sale.context,price_list:"
+msgid "Price List"
+msgstr ""
+
+msgctxt "field:sale.configuration,sale_price_list:"
+msgid "Sale Price List"
+msgstr ""
+
+msgctxt "field:sale.configuration.sale_price_list,company:"
+msgid "Company"
+msgstr ""
+
+msgctxt "field:sale.configuration.sale_price_list,sale_price_list:"
+msgid "Sale Price List"
+msgstr ""
+
+msgctxt "field:sale.sale,price_list:"
+msgid "Price List"
+msgstr ""
+
+msgctxt "help:party.party,sale_price_list:"
+msgid "The default price list for new sales."
+msgstr ""
+
+msgctxt "help:sale.configuration,sale_price_list:"
+msgid "The default price list for new parties."
+msgstr ""
+
+msgctxt "help:sale.sale,price_list:"
+msgid "Use to compute the unit price of lines."
+msgstr ""
+
+msgctxt "model:party.party.sale_price_list,name:"
+msgid "Party Sale Price List"
+msgstr ""
+
+msgctxt "model:sale.configuration.sale_price_list,name:"
+msgid "Sale Configuration Sale PriceList"
+msgstr ""
+
+msgctxt "selection:product.price_list,unit:"
+msgid "Product Sale"
+msgstr ""
diff --git a/modules/sale_price_list/locale/fr.po b/modules/sale_price_list/locale/fr.po
new file mode 100644
index 0000000000..f5adb9d8ec
--- /dev/null
+++ b/modules/sale_price_list/locale/fr.po
@@ -0,0 +1,67 @@
+#
+msgid ""
+msgstr "Content-Type: text/plain; charset=utf-8\n"
+
+msgctxt "field:party.party,sale_price_list:"
+msgid "Sale Price List"
+msgstr "Liste de prix de vente"
+
+msgctxt "field:party.party,sale_price_lists:"
+msgid "Sale Price Lists"
+msgstr "Listes de prix de vente"
+
+msgctxt "field:party.party.sale_price_list,company:"
+msgid "Company"
+msgstr "Société"
+
+msgctxt "field:party.party.sale_price_list,party:"
+msgid "Party"
+msgstr "Tiers"
+
+msgctxt "field:party.party.sale_price_list,sale_price_list:"
+msgid "Sale Price List"
+msgstr "Liste de prix de vente"
+
+msgctxt "field:product.sale.context,price_list:"
+msgid "Price List"
+msgstr "Liste de prix"
+
+msgctxt "field:sale.configuration,sale_price_list:"
+msgid "Sale Price List"
+msgstr "Liste de prix de vente"
+
+msgctxt "field:sale.configuration.sale_price_list,company:"
+msgid "Company"
+msgstr "Société"
+
+msgctxt "field:sale.configuration.sale_price_list,sale_price_list:"
+msgid "Sale Price List"
+msgstr "Liste de prix de vente"
+
+msgctxt "field:sale.sale,price_list:"
+msgid "Price List"
+msgstr "Liste de prix"
+
+msgctxt "help:party.party,sale_price_list:"
+msgid "The default price list for new sales."
+msgstr "La liste de prix par défaut pour les nouvelles ventes."
+
+msgctxt "help:sale.configuration,sale_price_list:"
+msgid "The default price list for new parties."
+msgstr "La liste de prix par défaut pour les nouveaux tiers."
+
+msgctxt "help:sale.sale,price_list:"
+msgid "Use to compute the unit price of lines."
+msgstr "Utiliser pour calculer le prix unitaire des lignes."
+
+msgctxt "model:party.party.sale_price_list,name:"
+msgid "Party Sale Price List"
+msgstr "Liste de prix de vente tiers"
+
+msgctxt "model:sale.configuration.sale_price_list,name:"
+msgid "Sale Configuration Sale PriceList"
+msgstr "Configuration de vente liste de prix de vente"
+
+msgctxt "selection:product.price_list,unit:"
+msgid "Product Sale"
+msgstr "Produit de vente"
diff --git a/modules/sale_price_list/locale/hu.po b/modules/sale_price_list/locale/hu.po
new file mode 100644
index 0000000000..21945a905b
--- /dev/null
+++ b/modules/sale_price_list/locale/hu.po
@@ -0,0 +1,67 @@
+#
+msgid ""
+msgstr "Content-Type: text/plain; charset=utf-8\n"
+
+msgctxt "field:party.party,sale_price_list:"
+msgid "Sale Price List"
+msgstr "Értékesítési árlista"
+
+msgctxt "field:party.party,sale_price_lists:"
+msgid "Sale Price Lists"
+msgstr "Értékesítési árlisták"
+
+msgctxt "field:party.party.sale_price_list,company:"
+msgid "Company"
+msgstr "Cég"
+
+msgctxt "field:party.party.sale_price_list,party:"
+msgid "Party"
+msgstr "Ügyfél"
+
+msgctxt "field:party.party.sale_price_list,sale_price_list:"
+msgid "Sale Price List"
+msgstr "Értékesítési árlista"
+
+msgctxt "field:product.sale.context,price_list:"
+msgid "Price List"
+msgstr "Árlista"
+
+msgctxt "field:sale.configuration,sale_price_list:"
+msgid "Sale Price List"
+msgstr "Értékesítési árlista"
+
+msgctxt "field:sale.configuration.sale_price_list,company:"
+msgid "Company"
+msgstr "Cég"
+
+msgctxt "field:sale.configuration.sale_price_list,sale_price_list:"
+msgid "Sale Price List"
+msgstr "Értékesítési árlista"
+
+msgctxt "field:sale.sale,price_list:"
+msgid "Price List"
+msgstr "Árlista"
+
+msgctxt "help:party.party,sale_price_list:"
+msgid "The default price list for new sales."
+msgstr "A vevői rendeléseknél használt alapértelmezett árlista."
+
+msgctxt "help:sale.configuration,sale_price_list:"
+msgid "The default price list for new parties."
+msgstr ""
+
+msgctxt "help:sale.sale,price_list:"
+msgid "Use to compute the unit price of lines."
+msgstr "A rendelési sorok egységárának számításához használja a rendszer."
+
+msgctxt "model:party.party.sale_price_list,name:"
+msgid "Party Sale Price List"
+msgstr ""
+
+msgctxt "model:sale.configuration.sale_price_list,name:"
+msgid "Sale Configuration Sale PriceList"
+msgstr ""
+
+msgctxt "selection:product.price_list,unit:"
+msgid "Product Sale"
+msgstr "a termék értékesítése ME-e"
diff --git a/modules/sale_price_list/locale/id.po b/modules/sale_price_list/locale/id.po
new file mode 100644
index 0000000000..9257dcfb6a
--- /dev/null
+++ b/modules/sale_price_list/locale/id.po
@@ -0,0 +1,67 @@
+#
+msgid ""
+msgstr "Content-Type: text/plain; charset=utf-8\n"
+
+msgctxt "field:party.party,sale_price_list:"
+msgid "Sale Price List"
+msgstr ""
+
+msgctxt "field:party.party,sale_price_lists:"
+msgid "Sale Price Lists"
+msgstr ""
+
+msgctxt "field:party.party.sale_price_list,company:"
+msgid "Company"
+msgstr "Perusahaan"
+
+msgctxt "field:party.party.sale_price_list,party:"
+msgid "Party"
+msgstr "Pihak"
+
+msgctxt "field:party.party.sale_price_list,sale_price_list:"
+msgid "Sale Price List"
+msgstr ""
+
+msgctxt "field:product.sale.context,price_list:"
+msgid "Price List"
+msgstr ""
+
+msgctxt "field:sale.configuration,sale_price_list:"
+msgid "Sale Price List"
+msgstr ""
+
+msgctxt "field:sale.configuration.sale_price_list,company:"
+msgid "Company"
+msgstr "Perusahaan"
+
+msgctxt "field:sale.configuration.sale_price_list,sale_price_list:"
+msgid "Sale Price List"
+msgstr ""
+
+msgctxt "field:sale.sale,price_list:"
+msgid "Price List"
+msgstr ""
+
+msgctxt "help:party.party,sale_price_list:"
+msgid "The default price list for new sales."
+msgstr ""
+
+msgctxt "help:sale.configuration,sale_price_list:"
+msgid "The default price list for new parties."
+msgstr ""
+
+msgctxt "help:sale.sale,price_list:"
+msgid "Use to compute the unit price of lines."
+msgstr ""
+
+msgctxt "model:party.party.sale_price_list,name:"
+msgid "Party Sale Price List"
+msgstr ""
+
+msgctxt "model:sale.configuration.sale_price_list,name:"
+msgid "Sale Configuration Sale PriceList"
+msgstr ""
+
+msgctxt "selection:product.price_list,unit:"
+msgid "Product Sale"
+msgstr ""
diff --git a/modules/sale_price_list/locale/it.po b/modules/sale_price_list/locale/it.po
new file mode 100644
index 0000000000..731875617d
--- /dev/null
+++ b/modules/sale_price_list/locale/it.po
@@ -0,0 +1,72 @@
+#
+msgid ""
+msgstr "Content-Type: text/plain; charset=utf-8\n"
+
+msgctxt "field:party.party,sale_price_list:"
+msgid "Sale Price List"
+msgstr "Listino di vendita"
+
+#, fuzzy
+msgctxt "field:party.party,sale_price_lists:"
+msgid "Sale Price Lists"
+msgstr "Listino di vendita"
+
+msgctxt "field:party.party.sale_price_list,company:"
+msgid "Company"
+msgstr "Azienda"
+
+msgctxt "field:party.party.sale_price_list,party:"
+msgid "Party"
+msgstr "Controparte"
+
+#, fuzzy
+msgctxt "field:party.party.sale_price_list,sale_price_list:"
+msgid "Sale Price List"
+msgstr "Listino di vendita"
+
+#, fuzzy
+msgctxt "field:product.sale.context,price_list:"
+msgid "Price List"
+msgstr "Listino"
+
+msgctxt "field:sale.configuration,sale_price_list:"
+msgid "Sale Price List"
+msgstr "Listino di vendita"
+
+msgctxt "field:sale.configuration.sale_price_list,company:"
+msgid "Company"
+msgstr "Azienda"
+
+#, fuzzy
+msgctxt "field:sale.configuration.sale_price_list,sale_price_list:"
+msgid "Sale Price List"
+msgstr "Listino di vendita"
+
+msgctxt "field:sale.sale,price_list:"
+msgid "Price List"
+msgstr "Listino"
+
+msgctxt "help:party.party,sale_price_list:"
+msgid "The default price list for new sales."
+msgstr "Il listino prezzi predefinito per le nuove vendite."
+
+msgctxt "help:sale.configuration,sale_price_list:"
+msgid "The default price list for new parties."
+msgstr "Il listino prezzi predefinito per le nuove controparti."
+
+msgctxt "help:sale.sale,price_list:"
+msgid "Use to compute the unit price of lines."
+msgstr "Utilizzare per calcolare il prezzo unitario delle righe."
+
+msgctxt "model:party.party.sale_price_list,name:"
+msgid "Party Sale Price List"
+msgstr "Listino prezzi vendita della controparte"
+
+#, fuzzy
+msgctxt "model:sale.configuration.sale_price_list,name:"
+msgid "Sale Configuration Sale PriceList"
+msgstr "Configurazione vendita listino di vendita"
+
+msgctxt "selection:product.price_list,unit:"
+msgid "Product Sale"
+msgstr ""
diff --git a/modules/sale_price_list/locale/lo.po b/modules/sale_price_list/locale/lo.po
new file mode 100644
index 0000000000..04289953ec
--- /dev/null
+++ b/modules/sale_price_list/locale/lo.po
@@ -0,0 +1,71 @@
+#
+msgid ""
+msgstr "Content-Type: text/plain; charset=utf-8\n"
+
+msgctxt "field:party.party,sale_price_list:"
+msgid "Sale Price List"
+msgstr "ລາຍການລາຄາຂາຍ"
+
+#, fuzzy
+msgctxt "field:party.party,sale_price_lists:"
+msgid "Sale Price Lists"
+msgstr "ລາຍການລາຄາຂາຍ"
+
+msgctxt "field:party.party.sale_price_list,company:"
+msgid "Company"
+msgstr ""
+
+msgctxt "field:party.party.sale_price_list,party:"
+msgid "Party"
+msgstr ""
+
+#, fuzzy
+msgctxt "field:party.party.sale_price_list,sale_price_list:"
+msgid "Sale Price List"
+msgstr "ລາຍການລາຄາຂາຍ"
+
+#, fuzzy
+msgctxt "field:product.sale.context,price_list:"
+msgid "Price List"
+msgstr "ລາຍການລາຄາ"
+
+msgctxt "field:sale.configuration,sale_price_list:"
+msgid "Sale Price List"
+msgstr "ລາຍການລາຄາຂາຍ"
+
+msgctxt "field:sale.configuration.sale_price_list,company:"
+msgid "Company"
+msgstr ""
+
+#, fuzzy
+msgctxt "field:sale.configuration.sale_price_list,sale_price_list:"
+msgid "Sale Price List"
+msgstr "ລາຍການລາຄາຂາຍ"
+
+msgctxt "field:sale.sale,price_list:"
+msgid "Price List"
+msgstr "ລາຍການລາຄາ"
+
+msgctxt "help:party.party,sale_price_list:"
+msgid "The default price list for new sales."
+msgstr ""
+
+msgctxt "help:sale.configuration,sale_price_list:"
+msgid "The default price list for new parties."
+msgstr ""
+
+msgctxt "help:sale.sale,price_list:"
+msgid "Use to compute the unit price of lines."
+msgstr ""
+
+msgctxt "model:party.party.sale_price_list,name:"
+msgid "Party Sale Price List"
+msgstr ""
+
+msgctxt "model:sale.configuration.sale_price_list,name:"
+msgid "Sale Configuration Sale PriceList"
+msgstr ""
+
+msgctxt "selection:product.price_list,unit:"
+msgid "Product Sale"
+msgstr ""
diff --git a/modules/sale_price_list/locale/lt.po b/modules/sale_price_list/locale/lt.po
new file mode 100644
index 0000000000..c19f82ef61
--- /dev/null
+++ b/modules/sale_price_list/locale/lt.po
@@ -0,0 +1,68 @@
+#
+msgid ""
+msgstr "Content-Type: text/plain; charset=utf-8\n"
+
+msgctxt "field:party.party,sale_price_list:"
+msgid "Sale Price List"
+msgstr ""
+
+msgctxt "field:party.party,sale_price_lists:"
+msgid "Sale Price Lists"
+msgstr ""
+
+msgctxt "field:party.party.sale_price_list,company:"
+msgid "Company"
+msgstr "Organizacija"
+
+msgctxt "field:party.party.sale_price_list,party:"
+msgid "Party"
+msgstr "Kontrahentas"
+
+msgctxt "field:party.party.sale_price_list,sale_price_list:"
+msgid "Sale Price List"
+msgstr ""
+
+#, fuzzy
+msgctxt "field:product.sale.context,price_list:"
+msgid "Price List"
+msgstr "Kontrahento kainoraštis perkant"
+
+msgctxt "field:sale.configuration,sale_price_list:"
+msgid "Sale Price List"
+msgstr ""
+
+msgctxt "field:sale.configuration.sale_price_list,company:"
+msgid "Company"
+msgstr "Organizacija"
+
+msgctxt "field:sale.configuration.sale_price_list,sale_price_list:"
+msgid "Sale Price List"
+msgstr ""
+
+msgctxt "field:sale.sale,price_list:"
+msgid "Price List"
+msgstr ""
+
+msgctxt "help:party.party,sale_price_list:"
+msgid "The default price list for new sales."
+msgstr ""
+
+msgctxt "help:sale.configuration,sale_price_list:"
+msgid "The default price list for new parties."
+msgstr ""
+
+msgctxt "help:sale.sale,price_list:"
+msgid "Use to compute the unit price of lines."
+msgstr ""
+
+msgctxt "model:party.party.sale_price_list,name:"
+msgid "Party Sale Price List"
+msgstr "Kontrahento kainoraštis perkant"
+
+msgctxt "model:sale.configuration.sale_price_list,name:"
+msgid "Sale Configuration Sale PriceList"
+msgstr ""
+
+msgctxt "selection:product.price_list,unit:"
+msgid "Product Sale"
+msgstr ""
diff --git a/modules/sale_price_list/locale/nl.po b/modules/sale_price_list/locale/nl.po
new file mode 100644
index 0000000000..5587bc657b
--- /dev/null
+++ b/modules/sale_price_list/locale/nl.po
@@ -0,0 +1,67 @@
+#
+msgid ""
+msgstr "Content-Type: text/plain; charset=utf-8\n"
+
+msgctxt "field:party.party,sale_price_list:"
+msgid "Sale Price List"
+msgstr "Verkoopprijslijst"
+
+msgctxt "field:party.party,sale_price_lists:"
+msgid "Sale Price Lists"
+msgstr "Verkoopprijslijsten"
+
+msgctxt "field:party.party.sale_price_list,company:"
+msgid "Company"
+msgstr "Bedrijf"
+
+msgctxt "field:party.party.sale_price_list,party:"
+msgid "Party"
+msgstr "Relatie"
+
+msgctxt "field:party.party.sale_price_list,sale_price_list:"
+msgid "Sale Price List"
+msgstr "Verkoopprijslijst"
+
+msgctxt "field:product.sale.context,price_list:"
+msgid "Price List"
+msgstr "Prijslijst"
+
+msgctxt "field:sale.configuration,sale_price_list:"
+msgid "Sale Price List"
+msgstr "Verkoopprijslijst"
+
+msgctxt "field:sale.configuration.sale_price_list,company:"
+msgid "Company"
+msgstr "Bedrijf"
+
+msgctxt "field:sale.configuration.sale_price_list,sale_price_list:"
+msgid "Sale Price List"
+msgstr "Verkoopprijslijst"
+
+msgctxt "field:sale.sale,price_list:"
+msgid "Price List"
+msgstr "Prijslijst"
+
+msgctxt "help:party.party,sale_price_list:"
+msgid "The default price list for new sales."
+msgstr "De standaard prijslijst voor nieuwe verkopen."
+
+msgctxt "help:sale.configuration,sale_price_list:"
+msgid "The default price list for new parties."
+msgstr "De standaard prijslijst voor nieuwe relaties."
+
+msgctxt "help:sale.sale,price_list:"
+msgid "Use to compute the unit price of lines."
+msgstr "Gebruik om de eenheidsprijs van lijnen te berekenen."
+
+msgctxt "model:party.party.sale_price_list,name:"
+msgid "Party Sale Price List"
+msgstr "Relatie verkoop prijslijst"
+
+msgctxt "model:sale.configuration.sale_price_list,name:"
+msgid "Sale Configuration Sale PriceList"
+msgstr "Verkoopconfiguratie Verkoopprijslijst"
+
+msgctxt "selection:product.price_list,unit:"
+msgid "Product Sale"
+msgstr "Product verkoop"
diff --git a/modules/sale_price_list/locale/pl.po b/modules/sale_price_list/locale/pl.po
new file mode 100644
index 0000000000..078f94f8e6
--- /dev/null
+++ b/modules/sale_price_list/locale/pl.po
@@ -0,0 +1,68 @@
+#
+msgid ""
+msgstr "Content-Type: text/plain; charset=utf-8\n"
+
+msgctxt "field:party.party,sale_price_list:"
+msgid "Sale Price List"
+msgstr "Cennik sprzedaży"
+
+msgctxt "field:party.party,sale_price_lists:"
+msgid "Sale Price Lists"
+msgstr "Cenniki sprzedaży"
+
+msgctxt "field:party.party.sale_price_list,company:"
+msgid "Company"
+msgstr "Firma"
+
+msgctxt "field:party.party.sale_price_list,party:"
+msgid "Party"
+msgstr "Strona"
+
+msgctxt "field:party.party.sale_price_list,sale_price_list:"
+msgid "Sale Price List"
+msgstr "Cennik sprzedaży"
+
+#, fuzzy
+msgctxt "field:product.sale.context,price_list:"
+msgid "Price List"
+msgstr "Cennik"
+
+msgctxt "field:sale.configuration,sale_price_list:"
+msgid "Sale Price List"
+msgstr "Cennik sprzedaży"
+
+msgctxt "field:sale.configuration.sale_price_list,company:"
+msgid "Company"
+msgstr "Firma"
+
+msgctxt "field:sale.configuration.sale_price_list,sale_price_list:"
+msgid "Sale Price List"
+msgstr "Cennik sprzedaży"
+
+msgctxt "field:sale.sale,price_list:"
+msgid "Price List"
+msgstr "Cennik"
+
+msgctxt "help:party.party,sale_price_list:"
+msgid "The default price list for new sales."
+msgstr "Domyślny cennik dla nowych sprzedaży."
+
+msgctxt "help:sale.configuration,sale_price_list:"
+msgid "The default price list for new parties."
+msgstr "Domyślny cennika dla nowych stron."
+
+msgctxt "help:sale.sale,price_list:"
+msgid "Use to compute the unit price of lines."
+msgstr "Użyj, aby wyliczyć cenę jednostkową wierszy."
+
+msgctxt "model:party.party.sale_price_list,name:"
+msgid "Party Sale Price List"
+msgstr "Cennik sprzedaży strony"
+
+msgctxt "model:sale.configuration.sale_price_list,name:"
+msgid "Sale Configuration Sale PriceList"
+msgstr ""
+
+msgctxt "selection:product.price_list,unit:"
+msgid "Product Sale"
+msgstr ""
diff --git a/modules/sale_price_list/locale/pt.po b/modules/sale_price_list/locale/pt.po
new file mode 100644
index 0000000000..7ccbb466ca
--- /dev/null
+++ b/modules/sale_price_list/locale/pt.po
@@ -0,0 +1,68 @@
+#
+msgid ""
+msgstr "Content-Type: text/plain; charset=utf-8\n"
+
+msgctxt "field:party.party,sale_price_list:"
+msgid "Sale Price List"
+msgstr "Lista de Preço de Venda"
+
+msgctxt "field:party.party,sale_price_lists:"
+msgid "Sale Price Lists"
+msgstr "Lista de Preço de Venda"
+
+msgctxt "field:party.party.sale_price_list,company:"
+msgid "Company"
+msgstr "Empresa"
+
+msgctxt "field:party.party.sale_price_list,party:"
+msgid "Party"
+msgstr "Pessoa"
+
+msgctxt "field:party.party.sale_price_list,sale_price_list:"
+msgid "Sale Price List"
+msgstr "Lista de Preço de Venda"
+
+#, fuzzy
+msgctxt "field:product.sale.context,price_list:"
+msgid "Price List"
+msgstr "Lista de Preços"
+
+msgctxt "field:sale.configuration,sale_price_list:"
+msgid "Sale Price List"
+msgstr "Lista de Preço de Venda"
+
+msgctxt "field:sale.configuration.sale_price_list,company:"
+msgid "Company"
+msgstr "Empresa"
+
+msgctxt "field:sale.configuration.sale_price_list,sale_price_list:"
+msgid "Sale Price List"
+msgstr "Lista de Preço de Venda"
+
+msgctxt "field:sale.sale,price_list:"
+msgid "Price List"
+msgstr "Lista de Preços"
+
+msgctxt "help:party.party,sale_price_list:"
+msgid "The default price list for new sales."
+msgstr "A lista de preços padrão para novas vendas."
+
+msgctxt "help:sale.configuration,sale_price_list:"
+msgid "The default price list for new parties."
+msgstr "A lista de preços padrão para novas pessoas."
+
+msgctxt "help:sale.sale,price_list:"
+msgid "Use to compute the unit price of lines."
+msgstr "usado para computar o preço unitários das linhas."
+
+msgctxt "model:party.party.sale_price_list,name:"
+msgid "Party Sale Price List"
+msgstr "Lista de Preço de Venda da Pessoa"
+
+msgctxt "model:sale.configuration.sale_price_list,name:"
+msgid "Sale Configuration Sale PriceList"
+msgstr "Configurações de Venda Lista de Preço de Venda"
+
+msgctxt "selection:product.price_list,unit:"
+msgid "Product Sale"
+msgstr ""
diff --git a/modules/sale_price_list/locale/ro.po b/modules/sale_price_list/locale/ro.po
new file mode 100644
index 0000000000..169ba64613
--- /dev/null
+++ b/modules/sale_price_list/locale/ro.po
@@ -0,0 +1,67 @@
+#
+msgid ""
+msgstr "Content-Type: text/plain; charset=utf-8\n"
+
+msgctxt "field:party.party,sale_price_list:"
+msgid "Sale Price List"
+msgstr ""
+
+msgctxt "field:party.party,sale_price_lists:"
+msgid "Sale Price Lists"
+msgstr ""
+
+msgctxt "field:party.party.sale_price_list,company:"
+msgid "Company"
+msgstr "Companie"
+
+msgctxt "field:party.party.sale_price_list,party:"
+msgid "Party"
+msgstr "Parte"
+
+msgctxt "field:party.party.sale_price_list,sale_price_list:"
+msgid "Sale Price List"
+msgstr ""
+
+msgctxt "field:product.sale.context,price_list:"
+msgid "Price List"
+msgstr "Listă de prețuri"
+
+msgctxt "field:sale.configuration,sale_price_list:"
+msgid "Sale Price List"
+msgstr ""
+
+msgctxt "field:sale.configuration.sale_price_list,company:"
+msgid "Company"
+msgstr "Companie"
+
+msgctxt "field:sale.configuration.sale_price_list,sale_price_list:"
+msgid "Sale Price List"
+msgstr ""
+
+msgctxt "field:sale.sale,price_list:"
+msgid "Price List"
+msgstr "Listă de prețuri"
+
+msgctxt "help:party.party,sale_price_list:"
+msgid "The default price list for new sales."
+msgstr ""
+
+msgctxt "help:sale.configuration,sale_price_list:"
+msgid "The default price list for new parties."
+msgstr ""
+
+msgctxt "help:sale.sale,price_list:"
+msgid "Use to compute the unit price of lines."
+msgstr ""
+
+msgctxt "model:party.party.sale_price_list,name:"
+msgid "Party Sale Price List"
+msgstr ""
+
+msgctxt "model:sale.configuration.sale_price_list,name:"
+msgid "Sale Configuration Sale PriceList"
+msgstr ""
+
+msgctxt "selection:product.price_list,unit:"
+msgid "Product Sale"
+msgstr ""
diff --git a/modules/sale_price_list/locale/ru.po b/modules/sale_price_list/locale/ru.po
new file mode 100644
index 0000000000..eb38526039
--- /dev/null
+++ b/modules/sale_price_list/locale/ru.po
@@ -0,0 +1,67 @@
+#
+msgid ""
+msgstr "Content-Type: text/plain; charset=utf-8\n"
+
+msgctxt "field:party.party,sale_price_list:"
+msgid "Sale Price List"
+msgstr ""
+
+msgctxt "field:party.party,sale_price_lists:"
+msgid "Sale Price Lists"
+msgstr ""
+
+msgctxt "field:party.party.sale_price_list,company:"
+msgid "Company"
+msgstr ""
+
+msgctxt "field:party.party.sale_price_list,party:"
+msgid "Party"
+msgstr ""
+
+msgctxt "field:party.party.sale_price_list,sale_price_list:"
+msgid "Sale Price List"
+msgstr ""
+
+msgctxt "field:product.sale.context,price_list:"
+msgid "Price List"
+msgstr ""
+
+msgctxt "field:sale.configuration,sale_price_list:"
+msgid "Sale Price List"
+msgstr ""
+
+msgctxt "field:sale.configuration.sale_price_list,company:"
+msgid "Company"
+msgstr ""
+
+msgctxt "field:sale.configuration.sale_price_list,sale_price_list:"
+msgid "Sale Price List"
+msgstr ""
+
+msgctxt "field:sale.sale,price_list:"
+msgid "Price List"
+msgstr ""
+
+msgctxt "help:party.party,sale_price_list:"
+msgid "The default price list for new sales."
+msgstr ""
+
+msgctxt "help:sale.configuration,sale_price_list:"
+msgid "The default price list for new parties."
+msgstr ""
+
+msgctxt "help:sale.sale,price_list:"
+msgid "Use to compute the unit price of lines."
+msgstr ""
+
+msgctxt "model:party.party.sale_price_list,name:"
+msgid "Party Sale Price List"
+msgstr ""
+
+msgctxt "model:sale.configuration.sale_price_list,name:"
+msgid "Sale Configuration Sale PriceList"
+msgstr ""
+
+msgctxt "selection:product.price_list,unit:"
+msgid "Product Sale"
+msgstr ""
diff --git a/modules/sale_price_list/locale/sl.po b/modules/sale_price_list/locale/sl.po
new file mode 100644
index 0000000000..2829f85d68
--- /dev/null
+++ b/modules/sale_price_list/locale/sl.po
@@ -0,0 +1,68 @@
+#
+msgid ""
+msgstr "Content-Type: text/plain; charset=utf-8\n"
+
+msgctxt "field:party.party,sale_price_list:"
+msgid "Sale Price List"
+msgstr "Prodajni cenik"
+
+msgctxt "field:party.party,sale_price_lists:"
+msgid "Sale Price Lists"
+msgstr "Prodajni ceniki"
+
+msgctxt "field:party.party.sale_price_list,company:"
+msgid "Company"
+msgstr "Družba"
+
+msgctxt "field:party.party.sale_price_list,party:"
+msgid "Party"
+msgstr "Partner"
+
+msgctxt "field:party.party.sale_price_list,sale_price_list:"
+msgid "Sale Price List"
+msgstr "Prodajni cenik"
+
+#, fuzzy
+msgctxt "field:product.sale.context,price_list:"
+msgid "Price List"
+msgstr "Cenik"
+
+msgctxt "field:sale.configuration,sale_price_list:"
+msgid "Sale Price List"
+msgstr "Prodajni cenik"
+
+msgctxt "field:sale.configuration.sale_price_list,company:"
+msgid "Company"
+msgstr "Družba"
+
+msgctxt "field:sale.configuration.sale_price_list,sale_price_list:"
+msgid "Sale Price List"
+msgstr "Prodajni cenik"
+
+msgctxt "field:sale.sale,price_list:"
+msgid "Price List"
+msgstr "Cenik"
+
+msgctxt "help:party.party,sale_price_list:"
+msgid "The default price list for new sales."
+msgstr ""
+
+msgctxt "help:sale.configuration,sale_price_list:"
+msgid "The default price list for new parties."
+msgstr ""
+
+msgctxt "help:sale.sale,price_list:"
+msgid "Use to compute the unit price of lines."
+msgstr ""
+
+msgctxt "model:party.party.sale_price_list,name:"
+msgid "Party Sale Price List"
+msgstr "Prodajni cenik partnerja"
+
+msgctxt "model:sale.configuration.sale_price_list,name:"
+msgid "Sale Configuration Sale PriceList"
+msgstr "Konfiguracija prodajnega cenika"
+
+msgctxt "selection:product.price_list,unit:"
+msgid "Product Sale"
+msgstr ""
diff --git a/modules/sale_price_list/locale/tr.po b/modules/sale_price_list/locale/tr.po
new file mode 100644
index 0000000000..eb38526039
--- /dev/null
+++ b/modules/sale_price_list/locale/tr.po
@@ -0,0 +1,67 @@
+#
+msgid ""
+msgstr "Content-Type: text/plain; charset=utf-8\n"
+
+msgctxt "field:party.party,sale_price_list:"
+msgid "Sale Price List"
+msgstr ""
+
+msgctxt "field:party.party,sale_price_lists:"
+msgid "Sale Price Lists"
+msgstr ""
+
+msgctxt "field:party.party.sale_price_list,company:"
+msgid "Company"
+msgstr ""
+
+msgctxt "field:party.party.sale_price_list,party:"
+msgid "Party"
+msgstr ""
+
+msgctxt "field:party.party.sale_price_list,sale_price_list:"
+msgid "Sale Price List"
+msgstr ""
+
+msgctxt "field:product.sale.context,price_list:"
+msgid "Price List"
+msgstr ""
+
+msgctxt "field:sale.configuration,sale_price_list:"
+msgid "Sale Price List"
+msgstr ""
+
+msgctxt "field:sale.configuration.sale_price_list,company:"
+msgid "Company"
+msgstr ""
+
+msgctxt "field:sale.configuration.sale_price_list,sale_price_list:"
+msgid "Sale Price List"
+msgstr ""
+
+msgctxt "field:sale.sale,price_list:"
+msgid "Price List"
+msgstr ""
+
+msgctxt "help:party.party,sale_price_list:"
+msgid "The default price list for new sales."
+msgstr ""
+
+msgctxt "help:sale.configuration,sale_price_list:"
+msgid "The default price list for new parties."
+msgstr ""
+
+msgctxt "help:sale.sale,price_list:"
+msgid "Use to compute the unit price of lines."
+msgstr ""
+
+msgctxt "model:party.party.sale_price_list,name:"
+msgid "Party Sale Price List"
+msgstr ""
+
+msgctxt "model:sale.configuration.sale_price_list,name:"
+msgid "Sale Configuration Sale PriceList"
+msgstr ""
+
+msgctxt "selection:product.price_list,unit:"
+msgid "Product Sale"
+msgstr ""
diff --git a/modules/sale_price_list/locale/zh_CN.po b/modules/sale_price_list/locale/zh_CN.po
new file mode 100644
index 0000000000..eb38526039
--- /dev/null
+++ b/modules/sale_price_list/locale/zh_CN.po
@@ -0,0 +1,67 @@
+#
+msgid ""
+msgstr "Content-Type: text/plain; charset=utf-8\n"
+
+msgctxt "field:party.party,sale_price_list:"
+msgid "Sale Price List"
+msgstr ""
+
+msgctxt "field:party.party,sale_price_lists:"
+msgid "Sale Price Lists"
+msgstr ""
+
+msgctxt "field:party.party.sale_price_list,company:"
+msgid "Company"
+msgstr ""
+
+msgctxt "field:party.party.sale_price_list,party:"
+msgid "Party"
+msgstr ""
+
+msgctxt "field:party.party.sale_price_list,sale_price_list:"
+msgid "Sale Price List"
+msgstr ""
+
+msgctxt "field:product.sale.context,price_list:"
+msgid "Price List"
+msgstr ""
+
+msgctxt "field:sale.configuration,sale_price_list:"
+msgid "Sale Price List"
+msgstr ""
+
+msgctxt "field:sale.configuration.sale_price_list,company:"
+msgid "Company"
+msgstr ""
+
+msgctxt "field:sale.configuration.sale_price_list,sale_price_list:"
+msgid "Sale Price List"
+msgstr ""
+
+msgctxt "field:sale.sale,price_list:"
+msgid "Price List"
+msgstr ""
+
+msgctxt "help:party.party,sale_price_list:"
+msgid "The default price list for new sales."
+msgstr ""
+
+msgctxt "help:sale.configuration,sale_price_list:"
+msgid "The default price list for new parties."
+msgstr ""
+
+msgctxt "help:sale.sale,price_list:"
+msgid "Use to compute the unit price of lines."
+msgstr ""
+
+msgctxt "model:party.party.sale_price_list,name:"
+msgid "Party Sale Price List"
+msgstr ""
+
+msgctxt "model:sale.configuration.sale_price_list,name:"
+msgid "Sale Configuration Sale PriceList"
+msgstr ""
+
+msgctxt "selection:product.price_list,unit:"
+msgid "Product Sale"
+msgstr ""
diff --git a/modules/sale_price_list/party.py b/modules/sale_price_list/party.py
new file mode 100644
index 0000000000..ad92a09c12
--- /dev/null
+++ b/modules/sale_price_list/party.py
@@ -0,0 +1,67 @@
+# This file is part of Tryton. The COPYRIGHT file at the top level of
+# this repository contains the full copyright notices and license terms.
+from trytond import backend
+from trytond.model import ModelSQL, fields
+from trytond.pyson import Eval
+from trytond.pool import PoolMeta, Pool
+from trytond.tools.multivalue import migrate_property
+from trytond.modules.company.model import (
+ CompanyMultiValueMixin, CompanyValueMixin)
+
+
+class Party(CompanyMultiValueMixin, metaclass=PoolMeta):
+ __name__ = 'party.party'
+ sale_price_list = fields.MultiValue(fields.Many2One(
+ 'product.price_list', "Sale Price List",
+ help="The default price list for new sales.",
+ domain=[
+ ('company', '=', Eval('context', {}).get('company', -1)),
+ ],
+ states={
+ 'invisible': ~Eval('context', {}).get('company'),
+ }))
+ sale_price_lists = fields.One2Many(
+ 'party.party.sale_price_list', 'party', "Sale Price Lists")
+
+ @classmethod
+ def default_sale_price_list(cls, **pattern):
+ pool = Pool()
+ Configuration = pool.get('sale.configuration')
+ config = Configuration(1)
+ price_list = config.get_multivalue('sale_price_list', **pattern)
+ return price_list.id if price_list else None
+
+
+class PartySalePriceList(ModelSQL, CompanyValueMixin):
+ "Party Sale Price List"
+ __name__ = 'party.party.sale_price_list'
+ party = fields.Many2One(
+ 'party.party', "Party", ondelete='CASCADE', select=True,
+ context={
+ 'company': Eval('company', -1),
+ },
+ depends=['company'])
+ sale_price_list = fields.Many2One(
+ 'product.price_list', "Sale Price List",
+ domain=[
+ ('company', '=', Eval('company', -1)),
+ ],
+ depends=['company'])
+
+ @classmethod
+ def __register__(cls, module_name):
+ exist = backend.TableHandler.table_exist(cls._table)
+
+ super(PartySalePriceList, cls).__register__(module_name)
+
+ if not exist:
+ cls._migrate_property([], [], [])
+
+ @classmethod
+ def _migrate_property(cls, field_names, value_names, fields):
+ field_names.append('sale_price_list')
+ value_names.append('sale_price_list')
+ fields.append('company')
+ migrate_property(
+ 'party.party', field_names, cls, value_names,
+ parent='party', fields=fields)
diff --git a/modules/sale_price_list/party.xml b/modules/sale_price_list/party.xml
new file mode 100644
index 0000000000..dd6f1fd0c2
--- /dev/null
+++ b/modules/sale_price_list/party.xml
@@ -0,0 +1,14 @@
+
+
+
+
+
+
+ party.party
+
+ party_form
+
+
+
+
diff --git a/modules/sale_price_list/product.py b/modules/sale_price_list/product.py
new file mode 100644
index 0000000000..edb0f67d8d
--- /dev/null
+++ b/modules/sale_price_list/product.py
@@ -0,0 +1,92 @@
+# This file is part of Tryton. The COPYRIGHT file at the top level of
+# this repository contains the full copyright notices and license terms.
+from trytond.model import fields
+from trytond.transaction import Transaction
+from trytond.pool import Pool, PoolMeta
+
+
+class Product(metaclass=PoolMeta):
+ __name__ = 'product.product'
+
+ def _get_sale_unit_price(self, quantity=0):
+ pool = Pool()
+ PriceList = pool.get('product.price_list')
+ Party = pool.get('party.party')
+ Uom = pool.get('product.uom')
+ Tax = pool.get('account.tax')
+ User = pool.get('res.user')
+ context = Transaction().context
+
+ unit_price = super()._get_sale_unit_price(quantity=quantity)
+
+ if context.get('price_list'):
+ price_list = PriceList(context['price_list'])
+ assert price_list.company == User(Transaction().user).company
+ if context.get('customer'):
+ customer = Party(context['customer'])
+ else:
+ customer = None
+ context_uom = None
+ if context.get('uom'):
+ context_uom = Uom(context['uom'])
+ taxes = None
+ if context.get('taxes'):
+ taxes = Tax.browse(context.get('taxes'))
+ uom = context_uom or self.sale_uom
+ if uom.category != self.sale_uom.category:
+ uom = self.sale_uom
+ unit_price = price_list.compute(
+ customer, self, unit_price, quantity, uom)
+ if price_list.tax_included and taxes:
+ unit_price = Tax.reverse_compute(unit_price, taxes)
+ return unit_price
+
+
+class PriceList(metaclass=PoolMeta):
+ __name__ = 'product.price_list'
+
+ @classmethod
+ def __setup__(cls):
+ super().__setup__()
+ cls.unit.selection.append(('product_sale', "Product Sale"))
+
+ def get_uom(self, product):
+ uom = super().get_uom(product)
+ if self.unit == 'product_sale' and product.sale_uom:
+ uom = product.sale_uom
+ return uom
+
+
+class SaleContext(metaclass=PoolMeta):
+ __name__ = 'product.sale.context'
+
+ price_list = fields.Many2One('product.price_list', "Price List")
+
+ @classmethod
+ def default_price_list(cls, **pattern):
+ pool = Pool()
+ Configuration = pool.get('sale.configuration')
+ config = Configuration(1)
+ price_list = config.get_multivalue('sale_price_list', **pattern)
+ if price_list:
+ return price_list.id
+
+ @fields.depends(methods=['on_change_customer'])
+ def on_change_company(self):
+ try:
+ super().on_change_company()
+ except AttributeError:
+ pass
+ self.on_change_customer()
+
+ @fields.depends('customer', 'company')
+ def on_change_customer(self):
+ try:
+ super().on_change_customer()
+ except AttributeError:
+ pass
+ if self.customer and self.customer.sale_price_list:
+ self.price_list = self.customer.sale_price_list
+ else:
+ self.price_list = self.default_price_list(
+ company=self.company.id if self.company else None)
diff --git a/modules/sale_price_list/product.xml b/modules/sale_price_list/product.xml
new file mode 100644
index 0000000000..90ec9164dc
--- /dev/null
+++ b/modules/sale_price_list/product.xml
@@ -0,0 +1,12 @@
+
+
+
+
+
+ product.sale.context
+
+ product_sale_context_form
+
+
+
diff --git a/modules/sale_price_list/sale.py b/modules/sale_price_list/sale.py
new file mode 100644
index 0000000000..6ba5e17451
--- /dev/null
+++ b/modules/sale_price_list/sale.py
@@ -0,0 +1,73 @@
+# This file is part of Tryton. The COPYRIGHT file at the top level of
+# this repository contains the full copyright notices and license terms.
+from trytond.model import fields
+from trytond.pyson import Eval, Not, Equal, Or, Bool
+from trytond.pool import PoolMeta, Pool
+
+
+class Sale(metaclass=PoolMeta):
+ __name__ = 'sale.sale'
+ price_list = fields.Many2One('product.price_list', 'Price List',
+ help="Use to compute the unit price of lines.",
+ domain=[('company', '=', Eval('company'))],
+ states={
+ 'readonly': Or(Not(Equal(Eval('state'), 'draft')),
+ Bool(Eval('lines', [0]))),
+ },
+ depends=['state', 'company'])
+
+ @classmethod
+ def __setup__(cls):
+ super(Sale, cls).__setup__()
+ cls.party.states['readonly'] = (cls.party.states['readonly']
+ | Eval('lines', [0]))
+ cls.lines.states['readonly'] = (cls.lines.states['readonly']
+ | ~Eval('party') | ~Eval('company'))
+ if 'party' not in cls.lines.depends:
+ cls.lines.depends.append('party')
+ if 'company' not in cls.lines.depends:
+ cls.lines.depends.append('company')
+
+ @fields.depends('company')
+ def on_change_party(self):
+ pool = Pool()
+ Configuration = pool.get('sale.configuration')
+ super(Sale, self).on_change_party()
+ if self.party and self.party.sale_price_list:
+ self.price_list = self.party.sale_price_list
+ else:
+ config = Configuration(1)
+ self.price_list = config.get_multivalue(
+ 'sale_price_list',
+ company=self.company.id if self.company else None)
+
+ @fields.depends('party')
+ def on_change_company(self):
+ pool = Pool()
+ Configuration = pool.get('sale.configuration')
+ super().on_change_company()
+ if self.party and self.party.sale_price_list:
+ self.price_list = self.party.sale_price_list
+ else:
+ config = Configuration(1)
+ self.price_list = config.get_multivalue(
+ 'sale_price_list',
+ company=self.company.id if self.company else None)
+
+
+class Line(metaclass=PoolMeta):
+ __name__ = 'sale.line'
+
+ @classmethod
+ def __setup__(cls):
+ super().__setup__()
+ cls.product.context['price_list'] = Eval(
+ '_parent_sale', {}).get('price_list')
+
+ @fields.depends('sale', '_parent_sale.price_list')
+ def _get_context_sale_price(self):
+ context = super()._get_context_sale_price()
+ if self.sale:
+ if getattr(self.sale, 'price_list', None):
+ context['price_list'] = self.sale.price_list.id
+ return context
diff --git a/modules/sale_price_list/sale.xml b/modules/sale_price_list/sale.xml
new file mode 100644
index 0000000000..b2a802c36b
--- /dev/null
+++ b/modules/sale_price_list/sale.xml
@@ -0,0 +1,14 @@
+
+
+
+
+
+
+ sale.sale
+
+ sale_form
+
+
+
+
diff --git a/modules/sale_price_list/setup.py b/modules/sale_price_list/setup.py
new file mode 100755
index 0000000000..9f61b67ac6
--- /dev/null
+++ b/modules/sale_price_list/setup.py
@@ -0,0 +1,148 @@
+#!/usr/bin/env python3
+# This file is part of Tryton. The COPYRIGHT file at the top level of
+# this repository contains the full copyright notices and license terms.
+
+import io
+import os
+import re
+from configparser import ConfigParser
+from setuptools import setup, find_packages
+
+
+def read(fname):
+ return io.open(
+ os.path.join(os.path.dirname(__file__), fname),
+ 'r', encoding='utf-8').read()
+
+
+def get_require_version(name):
+ if minor_version % 2:
+ require = '%s >= %s.%s.dev0, < %s.%s'
+ else:
+ require = '%s >= %s.%s, < %s.%s'
+ require %= (name, major_version, minor_version,
+ major_version, minor_version + 1)
+ return require
+
+
+config = ConfigParser()
+config.read_file(open(os.path.join(os.path.dirname(__file__), 'tryton.cfg')))
+info = dict(config.items('tryton'))
+for key in ('depends', 'extras_depend', 'xml'):
+ if key in info:
+ info[key] = info[key].strip().splitlines()
+version = info.get('version', '0.0.1')
+major_version, minor_version, _ = version.split('.', 2)
+major_version = int(major_version)
+minor_version = int(minor_version)
+name = 'trytond_sale_price_list'
+
+download_url = 'http://downloads.tryton.org/%s.%s/' % (
+ major_version, minor_version)
+if minor_version % 2:
+ version = '%s.%s.dev0' % (major_version, minor_version)
+ download_url = (
+ 'hg+http://hg.tryton.org/modules/%s#egg=%s-%s' % (
+ name[8:], name, version))
+local_version = []
+if os.environ.get('CI_JOB_ID'):
+ local_version.append(os.environ['CI_JOB_ID'])
+else:
+ for build in ['CI_BUILD_NUMBER', 'CI_JOB_NUMBER']:
+ if os.environ.get(build):
+ local_version.append(os.environ[build])
+ else:
+ local_version = []
+ break
+if local_version:
+ version += '+' + '.'.join(local_version)
+
+requires = []
+for dep in info.get('depends', []):
+ if not re.match(r'(ir|res)(\W|$)', dep):
+ requires.append(get_require_version('trytond_%s' % dep))
+requires.append(get_require_version('trytond'))
+tests_require = [get_require_version('proteus')]
+dependency_links = []
+if minor_version % 2:
+ dependency_links.append(
+ 'https://trydevpi.tryton.org/?local_version='
+ + '.'.join(local_version))
+
+setup(name=name,
+ version=version,
+ description='Tryton module to add price list on sale',
+ long_description=read('README.rst'),
+ author='Tryton',
+ author_email='bugs@tryton.org',
+ url='http://www.tryton.org/',
+ download_url=download_url,
+ project_urls={
+ "Bug Tracker": 'https://bugs.tryton.org/',
+ "Documentation": 'https://docs.tryton.org/',
+ "Forum": 'https://www.tryton.org/forum',
+ "Source Code": 'https://hg.tryton.org/modules/sale_price_list',
+ },
+ keywords='tryton sale price list',
+ package_dir={'trytond.modules.sale_price_list': '.'},
+ packages=(
+ ['trytond.modules.sale_price_list']
+ + ['trytond.modules.sale_price_list.%s' % p for p in find_packages()]
+ ),
+ package_data={
+ 'trytond.modules.sale_price_list': (info.get('xml', [])
+ + ['tryton.cfg', 'view/*.xml', 'locale/*.po', 'tests/*.rst']),
+ },
+ classifiers=[
+ 'Development Status :: 5 - Production/Stable',
+ 'Environment :: Plugins',
+ 'Framework :: Tryton',
+ 'Intended Audience :: Developers',
+ 'Intended Audience :: Financial and Insurance Industry',
+ 'Intended Audience :: Legal Industry',
+ 'License :: OSI Approved :: '
+ 'GNU General Public License v3 or later (GPLv3+)',
+ 'Natural Language :: Bulgarian',
+ 'Natural Language :: Catalan',
+ 'Natural Language :: Chinese (Simplified)',
+ 'Natural Language :: Czech',
+ 'Natural Language :: Dutch',
+ 'Natural Language :: English',
+ 'Natural Language :: Finnish',
+ 'Natural Language :: French',
+ 'Natural Language :: German',
+ 'Natural Language :: Hungarian',
+ 'Natural Language :: Indonesian',
+ 'Natural Language :: Italian',
+ 'Natural Language :: Persian',
+ 'Natural Language :: Polish',
+ 'Natural Language :: Portuguese (Brazilian)',
+ 'Natural Language :: Romanian',
+ 'Natural Language :: Russian',
+ 'Natural Language :: Slovenian',
+ 'Natural Language :: Spanish',
+ 'Natural Language :: Turkish',
+ 'Operating System :: OS Independent',
+ 'Programming Language :: Python :: 3',
+ 'Programming Language :: Python :: 3.6',
+ 'Programming Language :: Python :: 3.7',
+ 'Programming Language :: Python :: 3.8',
+ 'Programming Language :: Python :: 3.9',
+ 'Programming Language :: Python :: Implementation :: CPython',
+ 'Programming Language :: Python :: Implementation :: PyPy',
+ 'Topic :: Office/Business',
+ 'Topic :: Office/Business :: Financial :: Accounting',
+ ],
+ license='GPL-3',
+ python_requires='>=3.6',
+ install_requires=requires,
+ dependency_links=dependency_links,
+ zip_safe=False,
+ entry_points="""
+ [trytond.modules]
+ sale_price_list = trytond.modules.sale_price_list
+ """,
+ test_suite='tests',
+ test_loader='trytond.test_loader:Loader',
+ tests_require=tests_require,
+ )
diff --git a/modules/sale_price_list/tests/__init__.py b/modules/sale_price_list/tests/__init__.py
new file mode 100644
index 0000000000..600fb32a83
--- /dev/null
+++ b/modules/sale_price_list/tests/__init__.py
@@ -0,0 +1,9 @@
+# This file is part of Tryton. The COPYRIGHT file at the top level of
+# this repository contains the full copyright notices and license terms.
+
+try:
+ from trytond.modules.sale_price_list.tests.test_sale_price_list import suite # noqa: E501
+except ImportError:
+ from .test_sale_price_list import suite
+
+__all__ = ['suite']
diff --git a/modules/sale_price_list/tests/scenario_sale_price_list.rst b/modules/sale_price_list/tests/scenario_sale_price_list.rst
new file mode 100644
index 0000000000..a2585f0a64
--- /dev/null
+++ b/modules/sale_price_list/tests/scenario_sale_price_list.rst
@@ -0,0 +1,167 @@
+========================
+Sale Price List Scenario
+========================
+
+Imports::
+
+ >>> import datetime
+ >>> from decimal import Decimal
+ >>> from proteus import Model, Wizard
+ >>> from trytond.tests.tools import activate_modules, set_user
+ >>> from trytond.modules.company.tests.tools import create_company, \
+ ... get_company
+ >>> from trytond.modules.account.tests.tools import create_fiscalyear, \
+ ... create_chart, get_accounts
+ >>> from trytond.modules.account_invoice.tests.tools import \
+ ... set_fiscalyear_invoice_sequences, create_payment_term
+
+Activate modules::
+
+ >>> config = activate_modules('sale_price_list')
+
+Create company::
+
+ >>> _ = create_company()
+ >>> company = get_company()
+
+Create sale user::
+
+ >>> User = Model.get('res.user')
+ >>> Group = Model.get('res.group')
+ >>> sale_user = User()
+ >>> sale_user.name = 'Sale'
+ >>> sale_user.login = 'sale'
+ >>> sale_group, = Group.find([('name', '=', 'Sales')])
+ >>> sale_user.groups.append(sale_group)
+ >>> sale_user.save()
+
+ >>> sale_admin = User()
+ >>> sale_admin.name = 'Sale Admin'
+ >>> sale_admin.login = 'sale_admin'
+ >>> sale_admin_group, = Group.find([('name', '=', 'Sales Administrator')])
+ >>> sale_admin.groups.append(sale_admin_group)
+ >>> product_admin_group, = Group.find(
+ ... [('name', '=', 'Product Administration')])
+ >>> sale_admin.groups.append(product_admin_group)
+ >>> sale_admin.save()
+
+Create fiscal year::
+
+ >>> fiscalyear = set_fiscalyear_invoice_sequences(
+ ... create_fiscalyear(company))
+ >>> fiscalyear.click('create_period')
+
+Create chart of accounts::
+
+ >>> _ = create_chart(company)
+ >>> accounts = get_accounts(company)
+ >>> revenue = accounts['revenue']
+ >>> expense = accounts['expense']
+
+Create parties::
+
+ >>> Party = Model.get('party.party')
+ >>> customer = Party(name='Customer')
+ >>> customer.save()
+ >>> customer_without_price_list = Party(name='Customer without price list')
+ >>> customer_without_price_list.save()
+
+Create account category::
+
+ >>> ProductCategory = Model.get('product.category')
+ >>> account_category = ProductCategory(name="Account Category")
+ >>> account_category.accounting = True
+ >>> account_category.account_expense = expense
+ >>> account_category.account_revenue = revenue
+ >>> account_category.save()
+
+Create product::
+
+ >>> ProductUom = Model.get('product.uom')
+ >>> unit, = ProductUom.find([('name', '=', 'Unit')])
+ >>> ProductTemplate = Model.get('product.template')
+
+ >>> template = ProductTemplate()
+ >>> template.name = 'product'
+ >>> template.default_uom = unit
+ >>> template.type = 'goods'
+ >>> template.salable = True
+ >>> template.list_price = Decimal('10')
+ >>> template.account_category = account_category
+ >>> template.save()
+ >>> product, = template.products
+
+ >>> template = ProductTemplate()
+ >>> template.name = 'service'
+ >>> template.default_uom = unit
+ >>> template.type = 'service'
+ >>> template.salable = True
+ >>> template.list_price = Decimal('30')
+ >>> template.account_category = account_category
+ >>> template.save()
+ >>> service, = template.products
+
+Create payment term::
+
+ >>> payment_term = create_payment_term()
+ >>> payment_term.save()
+
+Create a price List and assign it to customer::
+
+ >>> PriceList = Model.get('product.price_list')
+ >>> price_list = PriceList(name='Retail')
+ >>> price_list_line = price_list.lines.new()
+ >>> price_list_line.quantity = 10.0
+ >>> price_list_line.product = product
+ >>> price_list_line.formula = 'unit_price * 0.7'
+ >>> price_list_line = price_list.lines.new()
+ >>> price_list_line.product = product
+ >>> price_list_line.formula = 'unit_price * 0.8'
+ >>> price_list_line = price_list.lines.new()
+ >>> price_list_line.formula = 'unit_price * 0.5'
+ >>> price_list.save()
+ >>> customer.sale_price_list = price_list
+ >>> customer.save()
+
+Use the price list on sale::
+
+ >>> set_user(sale_user)
+ >>> Sale = Model.get('sale.sale')
+ >>> sale = Sale()
+ >>> sale.party = customer
+ >>> sale.price_list == price_list
+ True
+ >>> sale.payment_term = payment_term
+ >>> sale_line = sale.lines.new()
+ >>> sale_line.product = product
+ >>> sale_line.unit_price
+ Decimal('8.0000')
+ >>> sale_line.quantity = 12.0
+ >>> sale_line.unit_price
+ Decimal('7.0000')
+ >>> sale_line = sale.lines.new()
+ >>> sale_line.product = service
+ >>> sale_line.unit_price
+ Decimal('15.0000')
+ >>> sale_line.quantity = 2.0
+ >>> sale_line.unit_price
+ Decimal('15.0000')
+
+Create a sale price List and assign to configuration::
+
+ >>> set_user(sale_admin)
+ >>> sale_price_list = PriceList(name='Sale price List')
+ >>> sale_price_list_line = sale_price_list.lines.new()
+ >>> sale_price_list_line.formula = 'unit_price * 0.5'
+ >>> sale_price_list.save()
+ >>> Configuration = Model.get('sale.configuration')
+ >>> config = Configuration()
+ >>> config.sale_price_list = sale_price_list
+ >>> config.save()
+
+Use the sale price list on sale::
+
+ >>> set_user(sale_user)
+ >>> sale.party = customer_without_price_list
+ >>> sale.price_list == sale_price_list
+ True
diff --git a/modules/sale_price_list/tests/test_sale_price_list.py b/modules/sale_price_list/tests/test_sale_price_list.py
new file mode 100644
index 0000000000..e23af6465e
--- /dev/null
+++ b/modules/sale_price_list/tests/test_sale_price_list.py
@@ -0,0 +1,26 @@
+# This file is part of Tryton. The COPYRIGHT file at the top level of
+# this repository contains the full copyright notices and license terms.
+import unittest
+import doctest
+import trytond.tests.test_tryton
+from trytond.tests.test_tryton import ModuleTestCase
+from trytond.tests.test_tryton import doctest_teardown
+from trytond.tests.test_tryton import doctest_checker
+
+from trytond.modules.company.tests import CompanyTestMixin
+
+
+class SalePriceListTestCase(CompanyTestMixin, ModuleTestCase):
+ 'Test SalePriceList module'
+ module = 'sale_price_list'
+
+
+def suite():
+ suite = trytond.tests.test_tryton.suite()
+ suite.addTests(unittest.TestLoader().loadTestsFromTestCase(
+ SalePriceListTestCase))
+ suite.addTests(doctest.DocFileSuite('scenario_sale_price_list.rst',
+ tearDown=doctest_teardown, encoding='utf-8',
+ checker=doctest_checker,
+ optionflags=doctest.REPORT_ONLY_FIRST_FAILURE))
+ return suite
diff --git a/modules/sale_price_list/tox.ini b/modules/sale_price_list/tox.ini
new file mode 100644
index 0000000000..197496c0cb
--- /dev/null
+++ b/modules/sale_price_list/tox.ini
@@ -0,0 +1,15 @@
+[tox]
+envlist = {py36,py37,py38,py39}-{sqlite,postgresql},pypy3-{sqlite,postgresql}
+
+[testenv]
+commands = {envpython} setup.py test
+deps =
+ {py36,py37,py38,py39}-postgresql: psycopg2 >= 2.5
+ pypy3-postgresql: psycopg2cffi >= 2.5
+ py36-sqlite: sqlitebck
+setenv =
+ sqlite: TRYTOND_DATABASE_URI={env:SQLITE_URI:sqlite://}
+ postgresql: TRYTOND_DATABASE_URI={env:POSTGRESQL_URI:postgresql://}
+ sqlite: DB_NAME={env:SQLITE_NAME::memory:}
+ postgresql: DB_NAME={env:POSTGRESQL_NAME:test}
+install_command = pip install --pre --find-links https://trydevpi.tryton.org/?local_version={env:CI_JOB_ID:{env:CI_BUILD_NUMBER}.{env:CI_JOB_NUMBER}} {opts} {packages}
diff --git a/modules/sale_price_list/tryton.cfg b/modules/sale_price_list/tryton.cfg
new file mode 100644
index 0000000000..f856099bc0
--- /dev/null
+++ b/modules/sale_price_list/tryton.cfg
@@ -0,0 +1,13 @@
+[tryton]
+version=6.0.2
+depends:
+ company
+ ir
+ party
+ product_price_list
+ sale
+xml:
+ party.xml
+ sale.xml
+ configuration.xml
+ product.xml
diff --git a/modules/sale_price_list/view/configuration_form.xml b/modules/sale_price_list/view/configuration_form.xml
new file mode 100644
index 0000000000..1f5f205819
--- /dev/null
+++ b/modules/sale_price_list/view/configuration_form.xml
@@ -0,0 +1,9 @@
+
+
+
+
+
+
+
+
diff --git a/modules/sale_price_list/view/party_form.xml b/modules/sale_price_list/view/party_form.xml
new file mode 100644
index 0000000000..5a4a99a616
--- /dev/null
+++ b/modules/sale_price_list/view/party_form.xml
@@ -0,0 +1,10 @@
+
+
+
+
+
+
+
+
+
diff --git a/modules/sale_price_list/view/product_sale_context_form.xml b/modules/sale_price_list/view/product_sale_context_form.xml
new file mode 100644
index 0000000000..4335e62bbe
--- /dev/null
+++ b/modules/sale_price_list/view/product_sale_context_form.xml
@@ -0,0 +1,9 @@
+
+
+
+
+
+
+
+
diff --git a/modules/sale_price_list/view/sale_form.xml b/modules/sale_price_list/view/sale_form.xml
new file mode 100644
index 0000000000..82ef30961e
--- /dev/null
+++ b/modules/sale_price_list/view/sale_form.xml
@@ -0,0 +1,10 @@
+
+
+
+
+
+
+
+
diff --git a/modules/sale_product_customer/.drone.yml b/modules/sale_product_customer/.drone.yml
new file mode 100644
index 0000000000..2049d30a49
--- /dev/null
+++ b/modules/sale_product_customer/.drone.yml
@@ -0,0 +1,68 @@
+clone:
+ hg:
+ image: plugins/hg
+ environment:
+ - HG_SHARE_POOL=/root/.cache/hg
+ volumes:
+ - cache:/root/.cache
+
+pipeline:
+ tox:
+ image: ${IMAGE}
+ environment:
+ - CFLAGS=-O0
+ - DB_CACHE=/cache
+ - TOX_TESTENV_PASSENV=CFLAGS DB_CACHE CI_BUILD_NUMBER CI_JOB_NUMBER CI_JOB_ID
+ - POSTGRESQL_URI=postgresql://postgres@postgresql:5432/
+ commands:
+ - echo "[extensions]" >> /root/.hgrc
+ - echo "hgext.share =" >> /root/.hgrc
+ - echo "[share]" >> /root/.hgrc
+ - echo "pool = /root/.cache/hg" >> /root/.hgrc
+ - pip install tox
+ - tox -e "${TOXENV}-${DATABASE}"
+ volumes:
+ - cache:/root/.cache
+ check_dist:
+ image: ${IMAGE}
+ commands:
+ - pip install twine
+ - python setup.py sdist
+ - twine check dist/*
+
+services:
+ postgresql:
+ image: postgres
+ environment:
+ - POSTGRES_HOST_AUTH_METHOD=trust
+ command: "-c fsync=off -c synchronous_commit=off -c full_page_writes=off"
+ when:
+ matrix:
+ DATABASE: postgresql
+
+matrix:
+ include:
+ - IMAGE: python:3.6
+ TOXENV: py36
+ DATABASE: sqlite
+ - IMAGE: python:3.6
+ TOXENV: py36
+ DATABASE: postgresql
+ - IMAGE: python:3.7
+ TOXENV: py37
+ DATABASE: sqlite
+ - IMAGE: python:3.7
+ TOXENV: py37
+ DATABASE: postgresql
+ - IMAGE: python:3.8
+ TOXENV: py38
+ DATABASE: sqlite
+ - IMAGE: python:3.8
+ TOXENV: py38
+ DATABASE: postgresql
+ - IMAGE: python:3.9
+ TOXENV: py39
+ DATABASE: sqlite
+ - IMAGE: python:3.9
+ TOXENV: py39
+ DATABASE: postgresql
diff --git a/modules/sale_product_customer/.flake8 b/modules/sale_product_customer/.flake8
new file mode 100644
index 0000000000..fa6b4f66d1
--- /dev/null
+++ b/modules/sale_product_customer/.flake8
@@ -0,0 +1,2 @@
+[flake8]
+ignore=E123,E124,E126,E128,E741,W503
diff --git a/modules/sale_product_customer/CHANGELOG b/modules/sale_product_customer/CHANGELOG
new file mode 100644
index 0000000000..bdf2c62a92
--- /dev/null
+++ b/modules/sale_product_customer/CHANGELOG
@@ -0,0 +1,25 @@
+Version 6.0.3 - 2022-08-03
+* Bug fixes (see mercurial logs for details)
+
+Version 6.0.2 - 2022-06-15
+* Bug fixes (see mercurial logs for details)
+
+Version 6.0.1 - 2022-02-16
+* Bug fixes (see mercurial logs for details)
+
+Version 6.0.0 - 2021-05-03
+* Bug fixes (see mercurial logs for details)
+* Allow product customer to be deactivated
+
+Version 5.8.0 - 2020-11-02
+* Bug fixes (see mercurial logs for details)
+* Remove support for Python 3.5
+
+Version 5.6.0 - 2020-05-04
+* Bug fixes (see mercurial logs for details)
+
+Version 5.4.0 - 2019-11-04
+* Bug fixes (see mercurial logs for details)
+
+Version 5.2.0 - 2019-05-06
+* Initial release
diff --git a/modules/sale_product_customer/COPYRIGHT b/modules/sale_product_customer/COPYRIGHT
new file mode 100644
index 0000000000..a98b1f252f
--- /dev/null
+++ b/modules/sale_product_customer/COPYRIGHT
@@ -0,0 +1,16 @@
+Copyright (C) 2019-2022 Maxime Richez
+Copyright (C) 2019 Thierry Bruyere
+Copyright (C) 2019-2022 SALUC SA
+
+This program is free software: you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation, either version 3 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program. If not, see .
diff --git a/modules/sale_product_customer/LICENSE b/modules/sale_product_customer/LICENSE
new file mode 100644
index 0000000000..94a9ed024d
--- /dev/null
+++ b/modules/sale_product_customer/LICENSE
@@ -0,0 +1,674 @@
+ GNU GENERAL PUBLIC LICENSE
+ Version 3, 29 June 2007
+
+ Copyright (C) 2007 Free Software Foundation, Inc.
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+ Preamble
+
+ The GNU General Public License is a free, copyleft license for
+software and other kinds of works.
+
+ The licenses for most software and other practical works are designed
+to take away your freedom to share and change the works. By contrast,
+the GNU General Public License is intended to guarantee your freedom to
+share and change all versions of a program--to make sure it remains free
+software for all its users. We, the Free Software Foundation, use the
+GNU General Public License for most of our software; it applies also to
+any other work released this way by its authors. You can apply it to
+your programs, too.
+
+ When we speak of free software, we are referring to freedom, not
+price. Our General Public Licenses are designed to make sure that you
+have the freedom to distribute copies of free software (and charge for
+them if you wish), that you receive source code or can get it if you
+want it, that you can change the software or use pieces of it in new
+free programs, and that you know you can do these things.
+
+ To protect your rights, we need to prevent others from denying you
+these rights or asking you to surrender the rights. Therefore, you have
+certain responsibilities if you distribute copies of the software, or if
+you modify it: responsibilities to respect the freedom of others.
+
+ For example, if you distribute copies of such a program, whether
+gratis or for a fee, you must pass on to the recipients the same
+freedoms that you received. You must make sure that they, too, receive
+or can get the source code. And you must show them these terms so they
+know their rights.
+
+ Developers that use the GNU GPL protect your rights with two steps:
+(1) assert copyright on the software, and (2) offer you this License
+giving you legal permission to copy, distribute and/or modify it.
+
+ For the developers' and authors' protection, the GPL clearly explains
+that there is no warranty for this free software. For both users' and
+authors' sake, the GPL requires that modified versions be marked as
+changed, so that their problems will not be attributed erroneously to
+authors of previous versions.
+
+ Some devices are designed to deny users access to install or run
+modified versions of the software inside them, although the manufacturer
+can do so. This is fundamentally incompatible with the aim of
+protecting users' freedom to change the software. The systematic
+pattern of such abuse occurs in the area of products for individuals to
+use, which is precisely where it is most unacceptable. Therefore, we
+have designed this version of the GPL to prohibit the practice for those
+products. If such problems arise substantially in other domains, we
+stand ready to extend this provision to those domains in future versions
+of the GPL, as needed to protect the freedom of users.
+
+ Finally, every program is threatened constantly by software patents.
+States should not allow patents to restrict development and use of
+software on general-purpose computers, but in those that do, we wish to
+avoid the special danger that patents applied to a free program could
+make it effectively proprietary. To prevent this, the GPL assures that
+patents cannot be used to render the program non-free.
+
+ The precise terms and conditions for copying, distribution and
+modification follow.
+
+ TERMS AND CONDITIONS
+
+ 0. Definitions.
+
+ "This License" refers to version 3 of the GNU General Public License.
+
+ "Copyright" also means copyright-like laws that apply to other kinds of
+works, such as semiconductor masks.
+
+ "The Program" refers to any copyrightable work licensed under this
+License. Each licensee is addressed as "you". "Licensees" and
+"recipients" may be individuals or organizations.
+
+ To "modify" a work means to copy from or adapt all or part of the work
+in a fashion requiring copyright permission, other than the making of an
+exact copy. The resulting work is called a "modified version" of the
+earlier work or a work "based on" the earlier work.
+
+ A "covered work" means either the unmodified Program or a work based
+on the Program.
+
+ To "propagate" a work means to do anything with it that, without
+permission, would make you directly or secondarily liable for
+infringement under applicable copyright law, except executing it on a
+computer or modifying a private copy. Propagation includes copying,
+distribution (with or without modification), making available to the
+public, and in some countries other activities as well.
+
+ To "convey" a work means any kind of propagation that enables other
+parties to make or receive copies. Mere interaction with a user through
+a computer network, with no transfer of a copy, is not conveying.
+
+ An interactive user interface displays "Appropriate Legal Notices"
+to the extent that it includes a convenient and prominently visible
+feature that (1) displays an appropriate copyright notice, and (2)
+tells the user that there is no warranty for the work (except to the
+extent that warranties are provided), that licensees may convey the
+work under this License, and how to view a copy of this License. If
+the interface presents a list of user commands or options, such as a
+menu, a prominent item in the list meets this criterion.
+
+ 1. Source Code.
+
+ The "source code" for a work means the preferred form of the work
+for making modifications to it. "Object code" means any non-source
+form of a work.
+
+ A "Standard Interface" means an interface that either is an official
+standard defined by a recognized standards body, or, in the case of
+interfaces specified for a particular programming language, one that
+is widely used among developers working in that language.
+
+ The "System Libraries" of an executable work include anything, other
+than the work as a whole, that (a) is included in the normal form of
+packaging a Major Component, but which is not part of that Major
+Component, and (b) serves only to enable use of the work with that
+Major Component, or to implement a Standard Interface for which an
+implementation is available to the public in source code form. A
+"Major Component", in this context, means a major essential component
+(kernel, window system, and so on) of the specific operating system
+(if any) on which the executable work runs, or a compiler used to
+produce the work, or an object code interpreter used to run it.
+
+ The "Corresponding Source" for a work in object code form means all
+the source code needed to generate, install, and (for an executable
+work) run the object code and to modify the work, including scripts to
+control those activities. However, it does not include the work's
+System Libraries, or general-purpose tools or generally available free
+programs which are used unmodified in performing those activities but
+which are not part of the work. For example, Corresponding Source
+includes interface definition files associated with source files for
+the work, and the source code for shared libraries and dynamically
+linked subprograms that the work is specifically designed to require,
+such as by intimate data communication or control flow between those
+subprograms and other parts of the work.
+
+ The Corresponding Source need not include anything that users
+can regenerate automatically from other parts of the Corresponding
+Source.
+
+ The Corresponding Source for a work in source code form is that
+same work.
+
+ 2. Basic Permissions.
+
+ All rights granted under this License are granted for the term of
+copyright on the Program, and are irrevocable provided the stated
+conditions are met. This License explicitly affirms your unlimited
+permission to run the unmodified Program. The output from running a
+covered work is covered by this License only if the output, given its
+content, constitutes a covered work. This License acknowledges your
+rights of fair use or other equivalent, as provided by copyright law.
+
+ You may make, run and propagate covered works that you do not
+convey, without conditions so long as your license otherwise remains
+in force. You may convey covered works to others for the sole purpose
+of having them make modifications exclusively for you, or provide you
+with facilities for running those works, provided that you comply with
+the terms of this License in conveying all material for which you do
+not control copyright. Those thus making or running the covered works
+for you must do so exclusively on your behalf, under your direction
+and control, on terms that prohibit them from making any copies of
+your copyrighted material outside their relationship with you.
+
+ Conveying under any other circumstances is permitted solely under
+the conditions stated below. Sublicensing is not allowed; section 10
+makes it unnecessary.
+
+ 3. Protecting Users' Legal Rights From Anti-Circumvention Law.
+
+ No covered work shall be deemed part of an effective technological
+measure under any applicable law fulfilling obligations under article
+11 of the WIPO copyright treaty adopted on 20 December 1996, or
+similar laws prohibiting or restricting circumvention of such
+measures.
+
+ When you convey a covered work, you waive any legal power to forbid
+circumvention of technological measures to the extent such circumvention
+is effected by exercising rights under this License with respect to
+the covered work, and you disclaim any intention to limit operation or
+modification of the work as a means of enforcing, against the work's
+users, your or third parties' legal rights to forbid circumvention of
+technological measures.
+
+ 4. Conveying Verbatim Copies.
+
+ You may convey verbatim copies of the Program's source code as you
+receive it, in any medium, provided that you conspicuously and
+appropriately publish on each copy an appropriate copyright notice;
+keep intact all notices stating that this License and any
+non-permissive terms added in accord with section 7 apply to the code;
+keep intact all notices of the absence of any warranty; and give all
+recipients a copy of this License along with the Program.
+
+ You may charge any price or no price for each copy that you convey,
+and you may offer support or warranty protection for a fee.
+
+ 5. Conveying Modified Source Versions.
+
+ You may convey a work based on the Program, or the modifications to
+produce it from the Program, in the form of source code under the
+terms of section 4, provided that you also meet all of these conditions:
+
+ a) The work must carry prominent notices stating that you modified
+ it, and giving a relevant date.
+
+ b) The work must carry prominent notices stating that it is
+ released under this License and any conditions added under section
+ 7. This requirement modifies the requirement in section 4 to
+ "keep intact all notices".
+
+ c) You must license the entire work, as a whole, under this
+ License to anyone who comes into possession of a copy. This
+ License will therefore apply, along with any applicable section 7
+ additional terms, to the whole of the work, and all its parts,
+ regardless of how they are packaged. This License gives no
+ permission to license the work in any other way, but it does not
+ invalidate such permission if you have separately received it.
+
+ d) If the work has interactive user interfaces, each must display
+ Appropriate Legal Notices; however, if the Program has interactive
+ interfaces that do not display Appropriate Legal Notices, your
+ work need not make them do so.
+
+ A compilation of a covered work with other separate and independent
+works, which are not by their nature extensions of the covered work,
+and which are not combined with it such as to form a larger program,
+in or on a volume of a storage or distribution medium, is called an
+"aggregate" if the compilation and its resulting copyright are not
+used to limit the access or legal rights of the compilation's users
+beyond what the individual works permit. Inclusion of a covered work
+in an aggregate does not cause this License to apply to the other
+parts of the aggregate.
+
+ 6. Conveying Non-Source Forms.
+
+ You may convey a covered work in object code form under the terms
+of sections 4 and 5, provided that you also convey the
+machine-readable Corresponding Source under the terms of this License,
+in one of these ways:
+
+ a) Convey the object code in, or embodied in, a physical product
+ (including a physical distribution medium), accompanied by the
+ Corresponding Source fixed on a durable physical medium
+ customarily used for software interchange.
+
+ b) Convey the object code in, or embodied in, a physical product
+ (including a physical distribution medium), accompanied by a
+ written offer, valid for at least three years and valid for as
+ long as you offer spare parts or customer support for that product
+ model, to give anyone who possesses the object code either (1) a
+ copy of the Corresponding Source for all the software in the
+ product that is covered by this License, on a durable physical
+ medium customarily used for software interchange, for a price no
+ more than your reasonable cost of physically performing this
+ conveying of source, or (2) access to copy the
+ Corresponding Source from a network server at no charge.
+
+ c) Convey individual copies of the object code with a copy of the
+ written offer to provide the Corresponding Source. This
+ alternative is allowed only occasionally and noncommercially, and
+ only if you received the object code with such an offer, in accord
+ with subsection 6b.
+
+ d) Convey the object code by offering access from a designated
+ place (gratis or for a charge), and offer equivalent access to the
+ Corresponding Source in the same way through the same place at no
+ further charge. You need not require recipients to copy the
+ Corresponding Source along with the object code. If the place to
+ copy the object code is a network server, the Corresponding Source
+ may be on a different server (operated by you or a third party)
+ that supports equivalent copying facilities, provided you maintain
+ clear directions next to the object code saying where to find the
+ Corresponding Source. Regardless of what server hosts the
+ Corresponding Source, you remain obligated to ensure that it is
+ available for as long as needed to satisfy these requirements.
+
+ e) Convey the object code using peer-to-peer transmission, provided
+ you inform other peers where the object code and Corresponding
+ Source of the work are being offered to the general public at no
+ charge under subsection 6d.
+
+ A separable portion of the object code, whose source code is excluded
+from the Corresponding Source as a System Library, need not be
+included in conveying the object code work.
+
+ A "User Product" is either (1) a "consumer product", which means any
+tangible personal property which is normally used for personal, family,
+or household purposes, or (2) anything designed or sold for incorporation
+into a dwelling. In determining whether a product is a consumer product,
+doubtful cases shall be resolved in favor of coverage. For a particular
+product received by a particular user, "normally used" refers to a
+typical or common use of that class of product, regardless of the status
+of the particular user or of the way in which the particular user
+actually uses, or expects or is expected to use, the product. A product
+is a consumer product regardless of whether the product has substantial
+commercial, industrial or non-consumer uses, unless such uses represent
+the only significant mode of use of the product.
+
+ "Installation Information" for a User Product means any methods,
+procedures, authorization keys, or other information required to install
+and execute modified versions of a covered work in that User Product from
+a modified version of its Corresponding Source. The information must
+suffice to ensure that the continued functioning of the modified object
+code is in no case prevented or interfered with solely because
+modification has been made.
+
+ If you convey an object code work under this section in, or with, or
+specifically for use in, a User Product, and the conveying occurs as
+part of a transaction in which the right of possession and use of the
+User Product is transferred to the recipient in perpetuity or for a
+fixed term (regardless of how the transaction is characterized), the
+Corresponding Source conveyed under this section must be accompanied
+by the Installation Information. But this requirement does not apply
+if neither you nor any third party retains the ability to install
+modified object code on the User Product (for example, the work has
+been installed in ROM).
+
+ The requirement to provide Installation Information does not include a
+requirement to continue to provide support service, warranty, or updates
+for a work that has been modified or installed by the recipient, or for
+the User Product in which it has been modified or installed. Access to a
+network may be denied when the modification itself materially and
+adversely affects the operation of the network or violates the rules and
+protocols for communication across the network.
+
+ Corresponding Source conveyed, and Installation Information provided,
+in accord with this section must be in a format that is publicly
+documented (and with an implementation available to the public in
+source code form), and must require no special password or key for
+unpacking, reading or copying.
+
+ 7. Additional Terms.
+
+ "Additional permissions" are terms that supplement the terms of this
+License by making exceptions from one or more of its conditions.
+Additional permissions that are applicable to the entire Program shall
+be treated as though they were included in this License, to the extent
+that they are valid under applicable law. If additional permissions
+apply only to part of the Program, that part may be used separately
+under those permissions, but the entire Program remains governed by
+this License without regard to the additional permissions.
+
+ When you convey a copy of a covered work, you may at your option
+remove any additional permissions from that copy, or from any part of
+it. (Additional permissions may be written to require their own
+removal in certain cases when you modify the work.) You may place
+additional permissions on material, added by you to a covered work,
+for which you have or can give appropriate copyright permission.
+
+ Notwithstanding any other provision of this License, for material you
+add to a covered work, you may (if authorized by the copyright holders of
+that material) supplement the terms of this License with terms:
+
+ a) Disclaiming warranty or limiting liability differently from the
+ terms of sections 15 and 16 of this License; or
+
+ b) Requiring preservation of specified reasonable legal notices or
+ author attributions in that material or in the Appropriate Legal
+ Notices displayed by works containing it; or
+
+ c) Prohibiting misrepresentation of the origin of that material, or
+ requiring that modified versions of such material be marked in
+ reasonable ways as different from the original version; or
+
+ d) Limiting the use for publicity purposes of names of licensors or
+ authors of the material; or
+
+ e) Declining to grant rights under trademark law for use of some
+ trade names, trademarks, or service marks; or
+
+ f) Requiring indemnification of licensors and authors of that
+ material by anyone who conveys the material (or modified versions of
+ it) with contractual assumptions of liability to the recipient, for
+ any liability that these contractual assumptions directly impose on
+ those licensors and authors.
+
+ All other non-permissive additional terms are considered "further
+restrictions" within the meaning of section 10. If the Program as you
+received it, or any part of it, contains a notice stating that it is
+governed by this License along with a term that is a further
+restriction, you may remove that term. If a license document contains
+a further restriction but permits relicensing or conveying under this
+License, you may add to a covered work material governed by the terms
+of that license document, provided that the further restriction does
+not survive such relicensing or conveying.
+
+ If you add terms to a covered work in accord with this section, you
+must place, in the relevant source files, a statement of the
+additional terms that apply to those files, or a notice indicating
+where to find the applicable terms.
+
+ Additional terms, permissive or non-permissive, may be stated in the
+form of a separately written license, or stated as exceptions;
+the above requirements apply either way.
+
+ 8. Termination.
+
+ You may not propagate or modify a covered work except as expressly
+provided under this License. Any attempt otherwise to propagate or
+modify it is void, and will automatically terminate your rights under
+this License (including any patent licenses granted under the third
+paragraph of section 11).
+
+ However, if you cease all violation of this License, then your
+license from a particular copyright holder is reinstated (a)
+provisionally, unless and until the copyright holder explicitly and
+finally terminates your license, and (b) permanently, if the copyright
+holder fails to notify you of the violation by some reasonable means
+prior to 60 days after the cessation.
+
+ Moreover, your license from a particular copyright holder is
+reinstated permanently if the copyright holder notifies you of the
+violation by some reasonable means, this is the first time you have
+received notice of violation of this License (for any work) from that
+copyright holder, and you cure the violation prior to 30 days after
+your receipt of the notice.
+
+ Termination of your rights under this section does not terminate the
+licenses of parties who have received copies or rights from you under
+this License. If your rights have been terminated and not permanently
+reinstated, you do not qualify to receive new licenses for the same
+material under section 10.
+
+ 9. Acceptance Not Required for Having Copies.
+
+ You are not required to accept this License in order to receive or
+run a copy of the Program. Ancillary propagation of a covered work
+occurring solely as a consequence of using peer-to-peer transmission
+to receive a copy likewise does not require acceptance. However,
+nothing other than this License grants you permission to propagate or
+modify any covered work. These actions infringe copyright if you do
+not accept this License. Therefore, by modifying or propagating a
+covered work, you indicate your acceptance of this License to do so.
+
+ 10. Automatic Licensing of Downstream Recipients.
+
+ Each time you convey a covered work, the recipient automatically
+receives a license from the original licensors, to run, modify and
+propagate that work, subject to this License. You are not responsible
+for enforcing compliance by third parties with this License.
+
+ An "entity transaction" is a transaction transferring control of an
+organization, or substantially all assets of one, or subdividing an
+organization, or merging organizations. If propagation of a covered
+work results from an entity transaction, each party to that
+transaction who receives a copy of the work also receives whatever
+licenses to the work the party's predecessor in interest had or could
+give under the previous paragraph, plus a right to possession of the
+Corresponding Source of the work from the predecessor in interest, if
+the predecessor has it or can get it with reasonable efforts.
+
+ You may not impose any further restrictions on the exercise of the
+rights granted or affirmed under this License. For example, you may
+not impose a license fee, royalty, or other charge for exercise of
+rights granted under this License, and you may not initiate litigation
+(including a cross-claim or counterclaim in a lawsuit) alleging that
+any patent claim is infringed by making, using, selling, offering for
+sale, or importing the Program or any portion of it.
+
+ 11. Patents.
+
+ A "contributor" is a copyright holder who authorizes use under this
+License of the Program or a work on which the Program is based. The
+work thus licensed is called the contributor's "contributor version".
+
+ A contributor's "essential patent claims" are all patent claims
+owned or controlled by the contributor, whether already acquired or
+hereafter acquired, that would be infringed by some manner, permitted
+by this License, of making, using, or selling its contributor version,
+but do not include claims that would be infringed only as a
+consequence of further modification of the contributor version. For
+purposes of this definition, "control" includes the right to grant
+patent sublicenses in a manner consistent with the requirements of
+this License.
+
+ Each contributor grants you a non-exclusive, worldwide, royalty-free
+patent license under the contributor's essential patent claims, to
+make, use, sell, offer for sale, import and otherwise run, modify and
+propagate the contents of its contributor version.
+
+ In the following three paragraphs, a "patent license" is any express
+agreement or commitment, however denominated, not to enforce a patent
+(such as an express permission to practice a patent or covenant not to
+sue for patent infringement). To "grant" such a patent license to a
+party means to make such an agreement or commitment not to enforce a
+patent against the party.
+
+ If you convey a covered work, knowingly relying on a patent license,
+and the Corresponding Source of the work is not available for anyone
+to copy, free of charge and under the terms of this License, through a
+publicly available network server or other readily accessible means,
+then you must either (1) cause the Corresponding Source to be so
+available, or (2) arrange to deprive yourself of the benefit of the
+patent license for this particular work, or (3) arrange, in a manner
+consistent with the requirements of this License, to extend the patent
+license to downstream recipients. "Knowingly relying" means you have
+actual knowledge that, but for the patent license, your conveying the
+covered work in a country, or your recipient's use of the covered work
+in a country, would infringe one or more identifiable patents in that
+country that you have reason to believe are valid.
+
+ If, pursuant to or in connection with a single transaction or
+arrangement, you convey, or propagate by procuring conveyance of, a
+covered work, and grant a patent license to some of the parties
+receiving the covered work authorizing them to use, propagate, modify
+or convey a specific copy of the covered work, then the patent license
+you grant is automatically extended to all recipients of the covered
+work and works based on it.
+
+ A patent license is "discriminatory" if it does not include within
+the scope of its coverage, prohibits the exercise of, or is
+conditioned on the non-exercise of one or more of the rights that are
+specifically granted under this License. You may not convey a covered
+work if you are a party to an arrangement with a third party that is
+in the business of distributing software, under which you make payment
+to the third party based on the extent of your activity of conveying
+the work, and under which the third party grants, to any of the
+parties who would receive the covered work from you, a discriminatory
+patent license (a) in connection with copies of the covered work
+conveyed by you (or copies made from those copies), or (b) primarily
+for and in connection with specific products or compilations that
+contain the covered work, unless you entered into that arrangement,
+or that patent license was granted, prior to 28 March 2007.
+
+ Nothing in this License shall be construed as excluding or limiting
+any implied license or other defenses to infringement that may
+otherwise be available to you under applicable patent law.
+
+ 12. No Surrender of Others' Freedom.
+
+ If conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License. If you cannot convey a
+covered work so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you may
+not convey it at all. For example, if you agree to terms that obligate you
+to collect a royalty for further conveying from those to whom you convey
+the Program, the only way you could satisfy both those terms and this
+License would be to refrain entirely from conveying the Program.
+
+ 13. Use with the GNU Affero General Public License.
+
+ Notwithstanding any other provision of this License, you have
+permission to link or combine any covered work with a work licensed
+under version 3 of the GNU Affero General Public License into a single
+combined work, and to convey the resulting work. The terms of this
+License will continue to apply to the part which is the covered work,
+but the special requirements of the GNU Affero General Public License,
+section 13, concerning interaction through a network will apply to the
+combination as such.
+
+ 14. Revised Versions of this License.
+
+ The Free Software Foundation may publish revised and/or new versions of
+the GNU General Public License from time to time. Such new versions will
+be similar in spirit to the present version, but may differ in detail to
+address new problems or concerns.
+
+ Each version is given a distinguishing version number. If the
+Program specifies that a certain numbered version of the GNU General
+Public License "or any later version" applies to it, you have the
+option of following the terms and conditions either of that numbered
+version or of any later version published by the Free Software
+Foundation. If the Program does not specify a version number of the
+GNU General Public License, you may choose any version ever published
+by the Free Software Foundation.
+
+ If the Program specifies that a proxy can decide which future
+versions of the GNU General Public License can be used, that proxy's
+public statement of acceptance of a version permanently authorizes you
+to choose that version for the Program.
+
+ Later license versions may give you additional or different
+permissions. However, no additional obligations are imposed on any
+author or copyright holder as a result of your choosing to follow a
+later version.
+
+ 15. Disclaimer of Warranty.
+
+ THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY
+APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT
+HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY
+OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO,
+THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM
+IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF
+ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
+
+ 16. Limitation of Liability.
+
+ IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS
+THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY
+GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE
+USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF
+DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD
+PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS),
+EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF
+SUCH DAMAGES.
+
+ 17. Interpretation of Sections 15 and 16.
+
+ If the disclaimer of warranty and limitation of liability provided
+above cannot be given local legal effect according to their terms,
+reviewing courts shall apply local law that most closely approximates
+an absolute waiver of all civil liability in connection with the
+Program, unless a warranty or assumption of liability accompanies a
+copy of the Program in return for a fee.
+
+ END OF TERMS AND CONDITIONS
+
+ How to Apply These Terms to Your New Programs
+
+ If you develop a new program, and you want it to be of the greatest
+possible use to the public, the best way to achieve this is to make it
+free software which everyone can redistribute and change under these terms.
+
+ To do so, attach the following notices to the program. It is safest
+to attach them to the start of each source file to most effectively
+state the exclusion of warranty; and each file should have at least
+the "copyright" line and a pointer to where the full notice is found.
+
+
+ Copyright (C)
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see .
+
+Also add information on how to contact you by electronic and paper mail.
+
+ If the program does terminal interaction, make it output a short
+notice like this when it starts in an interactive mode:
+
+ Copyright (C)
+ This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
+ This is free software, and you are welcome to redistribute it
+ under certain conditions; type `show c' for details.
+
+The hypothetical commands `show w' and `show c' should show the appropriate
+parts of the General Public License. Of course, your program's commands
+might be different; for a GUI interface, you would use an "about box".
+
+ You should also get your employer (if you work as a programmer) or school,
+if any, to sign a "copyright disclaimer" for the program, if necessary.
+For more information on this, and how to apply and follow the GNU GPL, see
+.
+
+ The GNU General Public License does not permit incorporating your program
+into proprietary programs. If your program is a subroutine library, you
+may consider it more useful to permit linking proprietary applications with
+the library. If this is what you want to do, use the GNU Lesser General
+Public License instead of this License. But first, please read
+.
diff --git a/modules/sale_product_customer/MANIFEST.in b/modules/sale_product_customer/MANIFEST.in
new file mode 100644
index 0000000000..e88b2348a3
--- /dev/null
+++ b/modules/sale_product_customer/MANIFEST.in
@@ -0,0 +1,5 @@
+include CHANGELOG
+include COPYRIGHT
+include LICENSE
+include README.rst
+include doc/*
diff --git a/modules/sale_product_customer/README.rst b/modules/sale_product_customer/README.rst
new file mode 120000
index 0000000000..176d9c2695
--- /dev/null
+++ b/modules/sale_product_customer/README.rst
@@ -0,0 +1 @@
+doc/index.rst
\ No newline at end of file
diff --git a/modules/sale_product_customer/__init__.py b/modules/sale_product_customer/__init__.py
new file mode 100644
index 0000000000..97c6958b44
--- /dev/null
+++ b/modules/sale_product_customer/__init__.py
@@ -0,0 +1,25 @@
+# This file is part of Tryton. The COPYRIGHT file at the top level of
+# this repository contains the full copyright notices and license terms.
+
+from trytond.pool import Pool
+from . import product
+from . import sale
+
+__all__ = ['register']
+
+
+def register():
+ Pool.register(
+ product.Template,
+ product.Product,
+ product.ProductCustomer,
+ sale.Line,
+ module='sale_product_customer', type_='model')
+ Pool.register(
+ sale.AmendmentLine,
+ module='sale_product_customer', type_='model',
+ depends=['sale_amendment'])
+ Pool.register(
+ module='sale_product_customer', type_='wizard')
+ Pool.register(
+ module='sale_product_customer', type_='report')
diff --git a/modules/sale_product_customer/doc/index.rst b/modules/sale_product_customer/doc/index.rst
new file mode 100644
index 0000000000..ab405ada04
--- /dev/null
+++ b/modules/sale_product_customer/doc/index.rst
@@ -0,0 +1,14 @@
+Sale Product Customer Module
+############################
+
+The sale_product_customer module defines customer's names and
+codes for products and/or variants.
+
+A reference to the customer's product is added to the sale line.
+
+Product Customer
+****************
+
+- Party: The customer.
+- Name: The customer's product name.
+- Code: The customer's product code.
diff --git a/modules/sale_product_customer/locale/bg.po b/modules/sale_product_customer/locale/bg.po
new file mode 100644
index 0000000000..160ff60a6b
--- /dev/null
+++ b/modules/sale_product_customer/locale/bg.po
@@ -0,0 +1,51 @@
+#
+msgid ""
+msgstr "Content-Type: text/plain; charset=utf-8\n"
+
+msgctxt "field:product.product,product_customers:"
+msgid "Customers"
+msgstr ""
+
+msgctxt "field:product.template,product_customers:"
+msgid "Customers"
+msgstr ""
+
+msgctxt "field:sale.amendment.line,product_customer:"
+msgid "Customer's Product"
+msgstr ""
+
+msgctxt "field:sale.line,product_customer:"
+msgid "Customer's Product"
+msgstr ""
+
+msgctxt "field:sale.product_customer,code:"
+msgid "Code"
+msgstr ""
+
+msgctxt "field:sale.product_customer,name:"
+msgid "Name"
+msgstr ""
+
+msgctxt "field:sale.product_customer,party:"
+msgid "Customer"
+msgstr ""
+
+msgctxt "field:sale.product_customer,product:"
+msgid "Variant"
+msgstr ""
+
+msgctxt "field:sale.product_customer,template:"
+msgid "Product"
+msgstr ""
+
+msgctxt "model:ir.action,name:act_product_customer_form"
+msgid "Customers"
+msgstr ""
+
+msgctxt "model:ir.ui.menu,name:menu_product_customer"
+msgid "Customers"
+msgstr ""
+
+msgctxt "model:sale.product_customer,name:"
+msgid "Product Customer"
+msgstr ""
diff --git a/modules/sale_product_customer/locale/ca.po b/modules/sale_product_customer/locale/ca.po
new file mode 100644
index 0000000000..f2eac84aeb
--- /dev/null
+++ b/modules/sale_product_customer/locale/ca.po
@@ -0,0 +1,51 @@
+#
+msgid ""
+msgstr "Content-Type: text/plain; charset=utf-8\n"
+
+msgctxt "field:product.product,product_customers:"
+msgid "Customers"
+msgstr "Clients"
+
+msgctxt "field:product.template,product_customers:"
+msgid "Customers"
+msgstr "Clients"
+
+msgctxt "field:sale.amendment.line,product_customer:"
+msgid "Customer's Product"
+msgstr "Producte del client"
+
+msgctxt "field:sale.line,product_customer:"
+msgid "Customer's Product"
+msgstr "Producte del client"
+
+msgctxt "field:sale.product_customer,code:"
+msgid "Code"
+msgstr "Codi"
+
+msgctxt "field:sale.product_customer,name:"
+msgid "Name"
+msgstr "Nom"
+
+msgctxt "field:sale.product_customer,party:"
+msgid "Customer"
+msgstr "Client"
+
+msgctxt "field:sale.product_customer,product:"
+msgid "Variant"
+msgstr "Variant"
+
+msgctxt "field:sale.product_customer,template:"
+msgid "Product"
+msgstr "Producte"
+
+msgctxt "model:ir.action,name:act_product_customer_form"
+msgid "Customers"
+msgstr "Clients"
+
+msgctxt "model:ir.ui.menu,name:menu_product_customer"
+msgid "Customers"
+msgstr "Clients"
+
+msgctxt "model:sale.product_customer,name:"
+msgid "Product Customer"
+msgstr "Producte del client"
diff --git a/modules/sale_product_customer/locale/cs.po b/modules/sale_product_customer/locale/cs.po
new file mode 100644
index 0000000000..160ff60a6b
--- /dev/null
+++ b/modules/sale_product_customer/locale/cs.po
@@ -0,0 +1,51 @@
+#
+msgid ""
+msgstr "Content-Type: text/plain; charset=utf-8\n"
+
+msgctxt "field:product.product,product_customers:"
+msgid "Customers"
+msgstr ""
+
+msgctxt "field:product.template,product_customers:"
+msgid "Customers"
+msgstr ""
+
+msgctxt "field:sale.amendment.line,product_customer:"
+msgid "Customer's Product"
+msgstr ""
+
+msgctxt "field:sale.line,product_customer:"
+msgid "Customer's Product"
+msgstr ""
+
+msgctxt "field:sale.product_customer,code:"
+msgid "Code"
+msgstr ""
+
+msgctxt "field:sale.product_customer,name:"
+msgid "Name"
+msgstr ""
+
+msgctxt "field:sale.product_customer,party:"
+msgid "Customer"
+msgstr ""
+
+msgctxt "field:sale.product_customer,product:"
+msgid "Variant"
+msgstr ""
+
+msgctxt "field:sale.product_customer,template:"
+msgid "Product"
+msgstr ""
+
+msgctxt "model:ir.action,name:act_product_customer_form"
+msgid "Customers"
+msgstr ""
+
+msgctxt "model:ir.ui.menu,name:menu_product_customer"
+msgid "Customers"
+msgstr ""
+
+msgctxt "model:sale.product_customer,name:"
+msgid "Product Customer"
+msgstr ""
diff --git a/modules/sale_product_customer/locale/de.po b/modules/sale_product_customer/locale/de.po
new file mode 100644
index 0000000000..c4f4b26a66
--- /dev/null
+++ b/modules/sale_product_customer/locale/de.po
@@ -0,0 +1,51 @@
+#
+msgid ""
+msgstr "Content-Type: text/plain; charset=utf-8\n"
+
+msgctxt "field:product.product,product_customers:"
+msgid "Customers"
+msgstr "Kunden"
+
+msgctxt "field:product.template,product_customers:"
+msgid "Customers"
+msgstr "Kunden"
+
+msgctxt "field:sale.amendment.line,product_customer:"
+msgid "Customer's Product"
+msgstr "Kundenartikel"
+
+msgctxt "field:sale.line,product_customer:"
+msgid "Customer's Product"
+msgstr "Kundenartikel"
+
+msgctxt "field:sale.product_customer,code:"
+msgid "Code"
+msgstr "Code"
+
+msgctxt "field:sale.product_customer,name:"
+msgid "Name"
+msgstr "Name"
+
+msgctxt "field:sale.product_customer,party:"
+msgid "Customer"
+msgstr "Kunde"
+
+msgctxt "field:sale.product_customer,product:"
+msgid "Variant"
+msgstr "Variante"
+
+msgctxt "field:sale.product_customer,template:"
+msgid "Product"
+msgstr "Artikel"
+
+msgctxt "model:ir.action,name:act_product_customer_form"
+msgid "Customers"
+msgstr "Kunden"
+
+msgctxt "model:ir.ui.menu,name:menu_product_customer"
+msgid "Customers"
+msgstr "Kunden"
+
+msgctxt "model:sale.product_customer,name:"
+msgid "Product Customer"
+msgstr "Kundenartikel"
diff --git a/modules/sale_product_customer/locale/es.po b/modules/sale_product_customer/locale/es.po
new file mode 100644
index 0000000000..36296f4abd
--- /dev/null
+++ b/modules/sale_product_customer/locale/es.po
@@ -0,0 +1,51 @@
+#
+msgid ""
+msgstr "Content-Type: text/plain; charset=utf-8\n"
+
+msgctxt "field:product.product,product_customers:"
+msgid "Customers"
+msgstr "Clientes"
+
+msgctxt "field:product.template,product_customers:"
+msgid "Customers"
+msgstr "Clientes"
+
+msgctxt "field:sale.amendment.line,product_customer:"
+msgid "Customer's Product"
+msgstr "Producto del cliente"
+
+msgctxt "field:sale.line,product_customer:"
+msgid "Customer's Product"
+msgstr "Producto del cliente"
+
+msgctxt "field:sale.product_customer,code:"
+msgid "Code"
+msgstr "Código"
+
+msgctxt "field:sale.product_customer,name:"
+msgid "Name"
+msgstr "Nombre"
+
+msgctxt "field:sale.product_customer,party:"
+msgid "Customer"
+msgstr "Cliente"
+
+msgctxt "field:sale.product_customer,product:"
+msgid "Variant"
+msgstr "Variante"
+
+msgctxt "field:sale.product_customer,template:"
+msgid "Product"
+msgstr "Producto"
+
+msgctxt "model:ir.action,name:act_product_customer_form"
+msgid "Customers"
+msgstr "Clientes"
+
+msgctxt "model:ir.ui.menu,name:menu_product_customer"
+msgid "Customers"
+msgstr "Clientes"
+
+msgctxt "model:sale.product_customer,name:"
+msgid "Product Customer"
+msgstr "Producto del cliente"
diff --git a/modules/sale_product_customer/locale/es_419.po b/modules/sale_product_customer/locale/es_419.po
new file mode 100644
index 0000000000..160ff60a6b
--- /dev/null
+++ b/modules/sale_product_customer/locale/es_419.po
@@ -0,0 +1,51 @@
+#
+msgid ""
+msgstr "Content-Type: text/plain; charset=utf-8\n"
+
+msgctxt "field:product.product,product_customers:"
+msgid "Customers"
+msgstr ""
+
+msgctxt "field:product.template,product_customers:"
+msgid "Customers"
+msgstr ""
+
+msgctxt "field:sale.amendment.line,product_customer:"
+msgid "Customer's Product"
+msgstr ""
+
+msgctxt "field:sale.line,product_customer:"
+msgid "Customer's Product"
+msgstr ""
+
+msgctxt "field:sale.product_customer,code:"
+msgid "Code"
+msgstr ""
+
+msgctxt "field:sale.product_customer,name:"
+msgid "Name"
+msgstr ""
+
+msgctxt "field:sale.product_customer,party:"
+msgid "Customer"
+msgstr ""
+
+msgctxt "field:sale.product_customer,product:"
+msgid "Variant"
+msgstr ""
+
+msgctxt "field:sale.product_customer,template:"
+msgid "Product"
+msgstr ""
+
+msgctxt "model:ir.action,name:act_product_customer_form"
+msgid "Customers"
+msgstr ""
+
+msgctxt "model:ir.ui.menu,name:menu_product_customer"
+msgid "Customers"
+msgstr ""
+
+msgctxt "model:sale.product_customer,name:"
+msgid "Product Customer"
+msgstr ""
diff --git a/modules/sale_product_customer/locale/et.po b/modules/sale_product_customer/locale/et.po
new file mode 100644
index 0000000000..d534088260
--- /dev/null
+++ b/modules/sale_product_customer/locale/et.po
@@ -0,0 +1,54 @@
+#
+msgid ""
+msgstr "Content-Type: text/plain; charset=utf-8\n"
+
+msgctxt "field:product.product,product_customers:"
+msgid "Customers"
+msgstr "Kliendid"
+
+msgctxt "field:product.template,product_customers:"
+msgid "Customers"
+msgstr "Kliendid"
+
+#, fuzzy
+msgctxt "field:sale.amendment.line,product_customer:"
+msgid "Customer's Product"
+msgstr "Kliendi toode"
+
+msgctxt "field:sale.line,product_customer:"
+msgid "Customer's Product"
+msgstr "Kliendi toode"
+
+msgctxt "field:sale.product_customer,code:"
+msgid "Code"
+msgstr "Kood"
+
+msgctxt "field:sale.product_customer,name:"
+msgid "Name"
+msgstr "Nimi"
+
+msgctxt "field:sale.product_customer,party:"
+msgid "Customer"
+msgstr "Klient"
+
+msgctxt "field:sale.product_customer,product:"
+msgid "Variant"
+msgstr "Variant"
+
+msgctxt "field:sale.product_customer,template:"
+msgid "Product"
+msgstr "Toode"
+
+#, fuzzy
+msgctxt "model:ir.action,name:act_product_customer_form"
+msgid "Customers"
+msgstr "Kliendid"
+
+#, fuzzy
+msgctxt "model:ir.ui.menu,name:menu_product_customer"
+msgid "Customers"
+msgstr "Kliendid"
+
+msgctxt "model:sale.product_customer,name:"
+msgid "Product Customer"
+msgstr "Toote klient"
diff --git a/modules/sale_product_customer/locale/fa.po b/modules/sale_product_customer/locale/fa.po
new file mode 100644
index 0000000000..160ff60a6b
--- /dev/null
+++ b/modules/sale_product_customer/locale/fa.po
@@ -0,0 +1,51 @@
+#
+msgid ""
+msgstr "Content-Type: text/plain; charset=utf-8\n"
+
+msgctxt "field:product.product,product_customers:"
+msgid "Customers"
+msgstr ""
+
+msgctxt "field:product.template,product_customers:"
+msgid "Customers"
+msgstr ""
+
+msgctxt "field:sale.amendment.line,product_customer:"
+msgid "Customer's Product"
+msgstr ""
+
+msgctxt "field:sale.line,product_customer:"
+msgid "Customer's Product"
+msgstr ""
+
+msgctxt "field:sale.product_customer,code:"
+msgid "Code"
+msgstr ""
+
+msgctxt "field:sale.product_customer,name:"
+msgid "Name"
+msgstr ""
+
+msgctxt "field:sale.product_customer,party:"
+msgid "Customer"
+msgstr ""
+
+msgctxt "field:sale.product_customer,product:"
+msgid "Variant"
+msgstr ""
+
+msgctxt "field:sale.product_customer,template:"
+msgid "Product"
+msgstr ""
+
+msgctxt "model:ir.action,name:act_product_customer_form"
+msgid "Customers"
+msgstr ""
+
+msgctxt "model:ir.ui.menu,name:menu_product_customer"
+msgid "Customers"
+msgstr ""
+
+msgctxt "model:sale.product_customer,name:"
+msgid "Product Customer"
+msgstr ""
diff --git a/modules/sale_product_customer/locale/fi.po b/modules/sale_product_customer/locale/fi.po
new file mode 100644
index 0000000000..160ff60a6b
--- /dev/null
+++ b/modules/sale_product_customer/locale/fi.po
@@ -0,0 +1,51 @@
+#
+msgid ""
+msgstr "Content-Type: text/plain; charset=utf-8\n"
+
+msgctxt "field:product.product,product_customers:"
+msgid "Customers"
+msgstr ""
+
+msgctxt "field:product.template,product_customers:"
+msgid "Customers"
+msgstr ""
+
+msgctxt "field:sale.amendment.line,product_customer:"
+msgid "Customer's Product"
+msgstr ""
+
+msgctxt "field:sale.line,product_customer:"
+msgid "Customer's Product"
+msgstr ""
+
+msgctxt "field:sale.product_customer,code:"
+msgid "Code"
+msgstr ""
+
+msgctxt "field:sale.product_customer,name:"
+msgid "Name"
+msgstr ""
+
+msgctxt "field:sale.product_customer,party:"
+msgid "Customer"
+msgstr ""
+
+msgctxt "field:sale.product_customer,product:"
+msgid "Variant"
+msgstr ""
+
+msgctxt "field:sale.product_customer,template:"
+msgid "Product"
+msgstr ""
+
+msgctxt "model:ir.action,name:act_product_customer_form"
+msgid "Customers"
+msgstr ""
+
+msgctxt "model:ir.ui.menu,name:menu_product_customer"
+msgid "Customers"
+msgstr ""
+
+msgctxt "model:sale.product_customer,name:"
+msgid "Product Customer"
+msgstr ""
diff --git a/modules/sale_product_customer/locale/fr.po b/modules/sale_product_customer/locale/fr.po
new file mode 100644
index 0000000000..d6bc8d859b
--- /dev/null
+++ b/modules/sale_product_customer/locale/fr.po
@@ -0,0 +1,51 @@
+#
+msgid ""
+msgstr "Content-Type: text/plain; charset=utf-8\n"
+
+msgctxt "field:product.product,product_customers:"
+msgid "Customers"
+msgstr "Clients"
+
+msgctxt "field:product.template,product_customers:"
+msgid "Customers"
+msgstr "Clients"
+
+msgctxt "field:sale.amendment.line,product_customer:"
+msgid "Customer's Product"
+msgstr "Produit Client"
+
+msgctxt "field:sale.line,product_customer:"
+msgid "Customer's Product"
+msgstr "Produit Client"
+
+msgctxt "field:sale.product_customer,code:"
+msgid "Code"
+msgstr "Code"
+
+msgctxt "field:sale.product_customer,name:"
+msgid "Name"
+msgstr "Nom"
+
+msgctxt "field:sale.product_customer,party:"
+msgid "Customer"
+msgstr "Client"
+
+msgctxt "field:sale.product_customer,product:"
+msgid "Variant"
+msgstr "Variante"
+
+msgctxt "field:sale.product_customer,template:"
+msgid "Product"
+msgstr "Produit"
+
+msgctxt "model:ir.action,name:act_product_customer_form"
+msgid "Customers"
+msgstr "Clients"
+
+msgctxt "model:ir.ui.menu,name:menu_product_customer"
+msgid "Customers"
+msgstr "Clients"
+
+msgctxt "model:sale.product_customer,name:"
+msgid "Product Customer"
+msgstr "Produit Client"
diff --git a/modules/sale_product_customer/locale/hu.po b/modules/sale_product_customer/locale/hu.po
new file mode 100644
index 0000000000..160ff60a6b
--- /dev/null
+++ b/modules/sale_product_customer/locale/hu.po
@@ -0,0 +1,51 @@
+#
+msgid ""
+msgstr "Content-Type: text/plain; charset=utf-8\n"
+
+msgctxt "field:product.product,product_customers:"
+msgid "Customers"
+msgstr ""
+
+msgctxt "field:product.template,product_customers:"
+msgid "Customers"
+msgstr ""
+
+msgctxt "field:sale.amendment.line,product_customer:"
+msgid "Customer's Product"
+msgstr ""
+
+msgctxt "field:sale.line,product_customer:"
+msgid "Customer's Product"
+msgstr ""
+
+msgctxt "field:sale.product_customer,code:"
+msgid "Code"
+msgstr ""
+
+msgctxt "field:sale.product_customer,name:"
+msgid "Name"
+msgstr ""
+
+msgctxt "field:sale.product_customer,party:"
+msgid "Customer"
+msgstr ""
+
+msgctxt "field:sale.product_customer,product:"
+msgid "Variant"
+msgstr ""
+
+msgctxt "field:sale.product_customer,template:"
+msgid "Product"
+msgstr ""
+
+msgctxt "model:ir.action,name:act_product_customer_form"
+msgid "Customers"
+msgstr ""
+
+msgctxt "model:ir.ui.menu,name:menu_product_customer"
+msgid "Customers"
+msgstr ""
+
+msgctxt "model:sale.product_customer,name:"
+msgid "Product Customer"
+msgstr ""
diff --git a/modules/sale_product_customer/locale/id.po b/modules/sale_product_customer/locale/id.po
new file mode 100644
index 0000000000..00d570da21
--- /dev/null
+++ b/modules/sale_product_customer/locale/id.po
@@ -0,0 +1,53 @@
+#
+msgid ""
+msgstr "Content-Type: text/plain; charset=utf-8\n"
+
+msgctxt "field:product.product,product_customers:"
+msgid "Customers"
+msgstr ""
+
+msgctxt "field:product.template,product_customers:"
+msgid "Customers"
+msgstr ""
+
+msgctxt "field:sale.amendment.line,product_customer:"
+msgid "Customer's Product"
+msgstr "Produk Pelanggan"
+
+msgctxt "field:sale.line,product_customer:"
+msgid "Customer's Product"
+msgstr "Produk Pelanggan"
+
+msgctxt "field:sale.product_customer,code:"
+msgid "Code"
+msgstr "Kode"
+
+msgctxt "field:sale.product_customer,name:"
+msgid "Name"
+msgstr "Nama"
+
+msgctxt "field:sale.product_customer,party:"
+msgid "Customer"
+msgstr "Pelanggan"
+
+msgctxt "field:sale.product_customer,product:"
+msgid "Variant"
+msgstr ""
+
+msgctxt "field:sale.product_customer,template:"
+msgid "Product"
+msgstr "Produk"
+
+#, fuzzy
+msgctxt "model:ir.action,name:act_product_customer_form"
+msgid "Customers"
+msgstr "Pelanggan"
+
+#, fuzzy
+msgctxt "model:ir.ui.menu,name:menu_product_customer"
+msgid "Customers"
+msgstr "Pelanggan"
+
+msgctxt "model:sale.product_customer,name:"
+msgid "Product Customer"
+msgstr ""
diff --git a/modules/sale_product_customer/locale/it.po b/modules/sale_product_customer/locale/it.po
new file mode 100644
index 0000000000..0da0b71fee
--- /dev/null
+++ b/modules/sale_product_customer/locale/it.po
@@ -0,0 +1,53 @@
+#
+msgid ""
+msgstr "Content-Type: text/plain; charset=utf-8\n"
+
+msgctxt "field:product.product,product_customers:"
+msgid "Customers"
+msgstr "Clienti"
+
+msgctxt "field:product.template,product_customers:"
+msgid "Customers"
+msgstr "Clienti"
+
+msgctxt "field:sale.amendment.line,product_customer:"
+msgid "Customer's Product"
+msgstr ""
+
+msgctxt "field:sale.line,product_customer:"
+msgid "Customer's Product"
+msgstr ""
+
+msgctxt "field:sale.product_customer,code:"
+msgid "Code"
+msgstr "Codice"
+
+msgctxt "field:sale.product_customer,name:"
+msgid "Name"
+msgstr "Nome"
+
+msgctxt "field:sale.product_customer,party:"
+msgid "Customer"
+msgstr "Cliente"
+
+msgctxt "field:sale.product_customer,product:"
+msgid "Variant"
+msgstr "Variante"
+
+msgctxt "field:sale.product_customer,template:"
+msgid "Product"
+msgstr "Prodotto"
+
+#, fuzzy
+msgctxt "model:ir.action,name:act_product_customer_form"
+msgid "Customers"
+msgstr "Clienti"
+
+#, fuzzy
+msgctxt "model:ir.ui.menu,name:menu_product_customer"
+msgid "Customers"
+msgstr "Clienti"
+
+msgctxt "model:sale.product_customer,name:"
+msgid "Product Customer"
+msgstr ""
diff --git a/modules/sale_product_customer/locale/lo.po b/modules/sale_product_customer/locale/lo.po
new file mode 100644
index 0000000000..160ff60a6b
--- /dev/null
+++ b/modules/sale_product_customer/locale/lo.po
@@ -0,0 +1,51 @@
+#
+msgid ""
+msgstr "Content-Type: text/plain; charset=utf-8\n"
+
+msgctxt "field:product.product,product_customers:"
+msgid "Customers"
+msgstr ""
+
+msgctxt "field:product.template,product_customers:"
+msgid "Customers"
+msgstr ""
+
+msgctxt "field:sale.amendment.line,product_customer:"
+msgid "Customer's Product"
+msgstr ""
+
+msgctxt "field:sale.line,product_customer:"
+msgid "Customer's Product"
+msgstr ""
+
+msgctxt "field:sale.product_customer,code:"
+msgid "Code"
+msgstr ""
+
+msgctxt "field:sale.product_customer,name:"
+msgid "Name"
+msgstr ""
+
+msgctxt "field:sale.product_customer,party:"
+msgid "Customer"
+msgstr ""
+
+msgctxt "field:sale.product_customer,product:"
+msgid "Variant"
+msgstr ""
+
+msgctxt "field:sale.product_customer,template:"
+msgid "Product"
+msgstr ""
+
+msgctxt "model:ir.action,name:act_product_customer_form"
+msgid "Customers"
+msgstr ""
+
+msgctxt "model:ir.ui.menu,name:menu_product_customer"
+msgid "Customers"
+msgstr ""
+
+msgctxt "model:sale.product_customer,name:"
+msgid "Product Customer"
+msgstr ""
diff --git a/modules/sale_product_customer/locale/lt.po b/modules/sale_product_customer/locale/lt.po
new file mode 100644
index 0000000000..160ff60a6b
--- /dev/null
+++ b/modules/sale_product_customer/locale/lt.po
@@ -0,0 +1,51 @@
+#
+msgid ""
+msgstr "Content-Type: text/plain; charset=utf-8\n"
+
+msgctxt "field:product.product,product_customers:"
+msgid "Customers"
+msgstr ""
+
+msgctxt "field:product.template,product_customers:"
+msgid "Customers"
+msgstr ""
+
+msgctxt "field:sale.amendment.line,product_customer:"
+msgid "Customer's Product"
+msgstr ""
+
+msgctxt "field:sale.line,product_customer:"
+msgid "Customer's Product"
+msgstr ""
+
+msgctxt "field:sale.product_customer,code:"
+msgid "Code"
+msgstr ""
+
+msgctxt "field:sale.product_customer,name:"
+msgid "Name"
+msgstr ""
+
+msgctxt "field:sale.product_customer,party:"
+msgid "Customer"
+msgstr ""
+
+msgctxt "field:sale.product_customer,product:"
+msgid "Variant"
+msgstr ""
+
+msgctxt "field:sale.product_customer,template:"
+msgid "Product"
+msgstr ""
+
+msgctxt "model:ir.action,name:act_product_customer_form"
+msgid "Customers"
+msgstr ""
+
+msgctxt "model:ir.ui.menu,name:menu_product_customer"
+msgid "Customers"
+msgstr ""
+
+msgctxt "model:sale.product_customer,name:"
+msgid "Product Customer"
+msgstr ""
diff --git a/modules/sale_product_customer/locale/nl.po b/modules/sale_product_customer/locale/nl.po
new file mode 100644
index 0000000000..631e61324b
--- /dev/null
+++ b/modules/sale_product_customer/locale/nl.po
@@ -0,0 +1,53 @@
+#
+msgid ""
+msgstr "Content-Type: text/plain; charset=utf-8\n"
+
+msgctxt "field:product.product,product_customers:"
+msgid "Customers"
+msgstr "Klanten"
+
+msgctxt "field:product.template,product_customers:"
+msgid "Customers"
+msgstr "Klanten"
+
+msgctxt "field:sale.amendment.line,product_customer:"
+msgid "Customer's Product"
+msgstr "Klant product"
+
+msgctxt "field:sale.line,product_customer:"
+msgid "Customer's Product"
+msgstr "Klant product"
+
+msgctxt "field:sale.product_customer,code:"
+msgid "Code"
+msgstr "Code"
+
+msgctxt "field:sale.product_customer,name:"
+msgid "Name"
+msgstr "Naam"
+
+msgctxt "field:sale.product_customer,party:"
+msgid "Customer"
+msgstr "Klant"
+
+msgctxt "field:sale.product_customer,product:"
+msgid "Variant"
+msgstr "Variant"
+
+msgctxt "field:sale.product_customer,template:"
+msgid "Product"
+msgstr "Product"
+
+#, fuzzy
+msgctxt "model:ir.action,name:act_product_customer_form"
+msgid "Customers"
+msgstr "Klanten"
+
+#, fuzzy
+msgctxt "model:ir.ui.menu,name:menu_product_customer"
+msgid "Customers"
+msgstr "Klanten"
+
+msgctxt "model:sale.product_customer,name:"
+msgid "Product Customer"
+msgstr "Product klant"
diff --git a/modules/sale_product_customer/locale/pl.po b/modules/sale_product_customer/locale/pl.po
new file mode 100644
index 0000000000..160ff60a6b
--- /dev/null
+++ b/modules/sale_product_customer/locale/pl.po
@@ -0,0 +1,51 @@
+#
+msgid ""
+msgstr "Content-Type: text/plain; charset=utf-8\n"
+
+msgctxt "field:product.product,product_customers:"
+msgid "Customers"
+msgstr ""
+
+msgctxt "field:product.template,product_customers:"
+msgid "Customers"
+msgstr ""
+
+msgctxt "field:sale.amendment.line,product_customer:"
+msgid "Customer's Product"
+msgstr ""
+
+msgctxt "field:sale.line,product_customer:"
+msgid "Customer's Product"
+msgstr ""
+
+msgctxt "field:sale.product_customer,code:"
+msgid "Code"
+msgstr ""
+
+msgctxt "field:sale.product_customer,name:"
+msgid "Name"
+msgstr ""
+
+msgctxt "field:sale.product_customer,party:"
+msgid "Customer"
+msgstr ""
+
+msgctxt "field:sale.product_customer,product:"
+msgid "Variant"
+msgstr ""
+
+msgctxt "field:sale.product_customer,template:"
+msgid "Product"
+msgstr ""
+
+msgctxt "model:ir.action,name:act_product_customer_form"
+msgid "Customers"
+msgstr ""
+
+msgctxt "model:ir.ui.menu,name:menu_product_customer"
+msgid "Customers"
+msgstr ""
+
+msgctxt "model:sale.product_customer,name:"
+msgid "Product Customer"
+msgstr ""
diff --git a/modules/sale_product_customer/locale/pt.po b/modules/sale_product_customer/locale/pt.po
new file mode 100644
index 0000000000..160ff60a6b
--- /dev/null
+++ b/modules/sale_product_customer/locale/pt.po
@@ -0,0 +1,51 @@
+#
+msgid ""
+msgstr "Content-Type: text/plain; charset=utf-8\n"
+
+msgctxt "field:product.product,product_customers:"
+msgid "Customers"
+msgstr ""
+
+msgctxt "field:product.template,product_customers:"
+msgid "Customers"
+msgstr ""
+
+msgctxt "field:sale.amendment.line,product_customer:"
+msgid "Customer's Product"
+msgstr ""
+
+msgctxt "field:sale.line,product_customer:"
+msgid "Customer's Product"
+msgstr ""
+
+msgctxt "field:sale.product_customer,code:"
+msgid "Code"
+msgstr ""
+
+msgctxt "field:sale.product_customer,name:"
+msgid "Name"
+msgstr ""
+
+msgctxt "field:sale.product_customer,party:"
+msgid "Customer"
+msgstr ""
+
+msgctxt "field:sale.product_customer,product:"
+msgid "Variant"
+msgstr ""
+
+msgctxt "field:sale.product_customer,template:"
+msgid "Product"
+msgstr ""
+
+msgctxt "model:ir.action,name:act_product_customer_form"
+msgid "Customers"
+msgstr ""
+
+msgctxt "model:ir.ui.menu,name:menu_product_customer"
+msgid "Customers"
+msgstr ""
+
+msgctxt "model:sale.product_customer,name:"
+msgid "Product Customer"
+msgstr ""
diff --git a/modules/sale_product_customer/locale/ro.po b/modules/sale_product_customer/locale/ro.po
new file mode 100644
index 0000000000..5baa5f4cde
--- /dev/null
+++ b/modules/sale_product_customer/locale/ro.po
@@ -0,0 +1,51 @@
+#
+msgid ""
+msgstr "Content-Type: text/plain; charset=utf-8\n"
+
+msgctxt "field:product.product,product_customers:"
+msgid "Customers"
+msgstr ""
+
+msgctxt "field:product.template,product_customers:"
+msgid "Customers"
+msgstr ""
+
+msgctxt "field:sale.amendment.line,product_customer:"
+msgid "Customer's Product"
+msgstr ""
+
+msgctxt "field:sale.line,product_customer:"
+msgid "Customer's Product"
+msgstr ""
+
+msgctxt "field:sale.product_customer,code:"
+msgid "Code"
+msgstr "Cod"
+
+msgctxt "field:sale.product_customer,name:"
+msgid "Name"
+msgstr ""
+
+msgctxt "field:sale.product_customer,party:"
+msgid "Customer"
+msgstr ""
+
+msgctxt "field:sale.product_customer,product:"
+msgid "Variant"
+msgstr ""
+
+msgctxt "field:sale.product_customer,template:"
+msgid "Product"
+msgstr "Produs"
+
+msgctxt "model:ir.action,name:act_product_customer_form"
+msgid "Customers"
+msgstr ""
+
+msgctxt "model:ir.ui.menu,name:menu_product_customer"
+msgid "Customers"
+msgstr ""
+
+msgctxt "model:sale.product_customer,name:"
+msgid "Product Customer"
+msgstr ""
diff --git a/modules/sale_product_customer/locale/ru.po b/modules/sale_product_customer/locale/ru.po
new file mode 100644
index 0000000000..160ff60a6b
--- /dev/null
+++ b/modules/sale_product_customer/locale/ru.po
@@ -0,0 +1,51 @@
+#
+msgid ""
+msgstr "Content-Type: text/plain; charset=utf-8\n"
+
+msgctxt "field:product.product,product_customers:"
+msgid "Customers"
+msgstr ""
+
+msgctxt "field:product.template,product_customers:"
+msgid "Customers"
+msgstr ""
+
+msgctxt "field:sale.amendment.line,product_customer:"
+msgid "Customer's Product"
+msgstr ""
+
+msgctxt "field:sale.line,product_customer:"
+msgid "Customer's Product"
+msgstr ""
+
+msgctxt "field:sale.product_customer,code:"
+msgid "Code"
+msgstr ""
+
+msgctxt "field:sale.product_customer,name:"
+msgid "Name"
+msgstr ""
+
+msgctxt "field:sale.product_customer,party:"
+msgid "Customer"
+msgstr ""
+
+msgctxt "field:sale.product_customer,product:"
+msgid "Variant"
+msgstr ""
+
+msgctxt "field:sale.product_customer,template:"
+msgid "Product"
+msgstr ""
+
+msgctxt "model:ir.action,name:act_product_customer_form"
+msgid "Customers"
+msgstr ""
+
+msgctxt "model:ir.ui.menu,name:menu_product_customer"
+msgid "Customers"
+msgstr ""
+
+msgctxt "model:sale.product_customer,name:"
+msgid "Product Customer"
+msgstr ""
diff --git a/modules/sale_product_customer/locale/sl.po b/modules/sale_product_customer/locale/sl.po
new file mode 100644
index 0000000000..160ff60a6b
--- /dev/null
+++ b/modules/sale_product_customer/locale/sl.po
@@ -0,0 +1,51 @@
+#
+msgid ""
+msgstr "Content-Type: text/plain; charset=utf-8\n"
+
+msgctxt "field:product.product,product_customers:"
+msgid "Customers"
+msgstr ""
+
+msgctxt "field:product.template,product_customers:"
+msgid "Customers"
+msgstr ""
+
+msgctxt "field:sale.amendment.line,product_customer:"
+msgid "Customer's Product"
+msgstr ""
+
+msgctxt "field:sale.line,product_customer:"
+msgid "Customer's Product"
+msgstr ""
+
+msgctxt "field:sale.product_customer,code:"
+msgid "Code"
+msgstr ""
+
+msgctxt "field:sale.product_customer,name:"
+msgid "Name"
+msgstr ""
+
+msgctxt "field:sale.product_customer,party:"
+msgid "Customer"
+msgstr ""
+
+msgctxt "field:sale.product_customer,product:"
+msgid "Variant"
+msgstr ""
+
+msgctxt "field:sale.product_customer,template:"
+msgid "Product"
+msgstr ""
+
+msgctxt "model:ir.action,name:act_product_customer_form"
+msgid "Customers"
+msgstr ""
+
+msgctxt "model:ir.ui.menu,name:menu_product_customer"
+msgid "Customers"
+msgstr ""
+
+msgctxt "model:sale.product_customer,name:"
+msgid "Product Customer"
+msgstr ""
diff --git a/modules/sale_product_customer/locale/tr.po b/modules/sale_product_customer/locale/tr.po
new file mode 100644
index 0000000000..160ff60a6b
--- /dev/null
+++ b/modules/sale_product_customer/locale/tr.po
@@ -0,0 +1,51 @@
+#
+msgid ""
+msgstr "Content-Type: text/plain; charset=utf-8\n"
+
+msgctxt "field:product.product,product_customers:"
+msgid "Customers"
+msgstr ""
+
+msgctxt "field:product.template,product_customers:"
+msgid "Customers"
+msgstr ""
+
+msgctxt "field:sale.amendment.line,product_customer:"
+msgid "Customer's Product"
+msgstr ""
+
+msgctxt "field:sale.line,product_customer:"
+msgid "Customer's Product"
+msgstr ""
+
+msgctxt "field:sale.product_customer,code:"
+msgid "Code"
+msgstr ""
+
+msgctxt "field:sale.product_customer,name:"
+msgid "Name"
+msgstr ""
+
+msgctxt "field:sale.product_customer,party:"
+msgid "Customer"
+msgstr ""
+
+msgctxt "field:sale.product_customer,product:"
+msgid "Variant"
+msgstr ""
+
+msgctxt "field:sale.product_customer,template:"
+msgid "Product"
+msgstr ""
+
+msgctxt "model:ir.action,name:act_product_customer_form"
+msgid "Customers"
+msgstr ""
+
+msgctxt "model:ir.ui.menu,name:menu_product_customer"
+msgid "Customers"
+msgstr ""
+
+msgctxt "model:sale.product_customer,name:"
+msgid "Product Customer"
+msgstr ""
diff --git a/modules/sale_product_customer/locale/zh_CN.po b/modules/sale_product_customer/locale/zh_CN.po
new file mode 100644
index 0000000000..160ff60a6b
--- /dev/null
+++ b/modules/sale_product_customer/locale/zh_CN.po
@@ -0,0 +1,51 @@
+#
+msgid ""
+msgstr "Content-Type: text/plain; charset=utf-8\n"
+
+msgctxt "field:product.product,product_customers:"
+msgid "Customers"
+msgstr ""
+
+msgctxt "field:product.template,product_customers:"
+msgid "Customers"
+msgstr ""
+
+msgctxt "field:sale.amendment.line,product_customer:"
+msgid "Customer's Product"
+msgstr ""
+
+msgctxt "field:sale.line,product_customer:"
+msgid "Customer's Product"
+msgstr ""
+
+msgctxt "field:sale.product_customer,code:"
+msgid "Code"
+msgstr ""
+
+msgctxt "field:sale.product_customer,name:"
+msgid "Name"
+msgstr ""
+
+msgctxt "field:sale.product_customer,party:"
+msgid "Customer"
+msgstr ""
+
+msgctxt "field:sale.product_customer,product:"
+msgid "Variant"
+msgstr ""
+
+msgctxt "field:sale.product_customer,template:"
+msgid "Product"
+msgstr ""
+
+msgctxt "model:ir.action,name:act_product_customer_form"
+msgid "Customers"
+msgstr ""
+
+msgctxt "model:ir.ui.menu,name:menu_product_customer"
+msgid "Customers"
+msgstr ""
+
+msgctxt "model:sale.product_customer,name:"
+msgid "Product Customer"
+msgstr ""
diff --git a/modules/sale_product_customer/product.py b/modules/sale_product_customer/product.py
new file mode 100644
index 0000000000..465a84e0fa
--- /dev/null
+++ b/modules/sale_product_customer/product.py
@@ -0,0 +1,167 @@
+# This file is part of Tryton. The COPYRIGHT file at the top level of
+# this repository contains the full copyright notices and license terms.
+
+from trytond.model import (
+ ModelSQL, ModelView, sequence_ordered, MatchMixin, DeactivableMixin,
+ fields)
+from trytond.pool import PoolMeta, Pool
+from trytond.pyson import If, Eval, Bool
+from trytond.tools import lstrip_wildcard
+
+
+class ProductCustomer(
+ sequence_ordered(), DeactivableMixin, ModelSQL, ModelView, MatchMixin):
+ 'Product Customer'
+ __name__ = 'sale.product_customer'
+
+ template = fields.Many2One(
+ 'product.template', "Product",
+ required=True, ondelete='CASCADE', select=True,
+ domain=[
+ If(Bool(Eval('product')),
+ ('products', '=', Eval('product')),
+ ()),
+ If(Eval('active'), ('active', '=', True), ()),
+ ],
+ depends=['product', 'active'])
+ product = fields.Many2One(
+ 'product.product', "Variant", select=True,
+ domain=[
+ If(Bool(Eval('template')),
+ ('template', '=', Eval('template')),
+ ()),
+ If(Eval('active'), ('active', '=', True), ()),
+ ],
+ depends=['template', 'active'])
+ party = fields.Many2One('party.party', "Customer", required=True,
+ ondelete='CASCADE')
+ name = fields.Char("Name", translate=True)
+ code = fields.Char("Code")
+
+ @fields.depends(
+ 'product', '_parent_product.template')
+ def on_change_product(self):
+ if self.product:
+ self.template = self.product.template
+
+ def get_rec_name(self, name):
+ if self.name:
+ name = self.name
+ elif self.product:
+ name = self.product.name
+ else:
+ name = self.template.name
+ if self.code:
+ name = '[' + self.code + '] ' + name
+ return name
+
+ @classmethod
+ def search_rec_name(cls, name, clause):
+ if clause[1].startswith('!') or clause[1].startswith('not '):
+ bool_op = 'AND'
+ else:
+ bool_op = 'OR'
+ code_value = clause[2]
+ if clause[1].endswith('like'):
+ code_value = lstrip_wildcard(clause[2])
+ domain = [bool_op,
+ ('template',) + tuple(clause[1:]),
+ ('product',) + tuple(clause[1:]),
+ ('party',) + tuple(clause[1:]),
+ ('code', clause[1], code_value) + tuple(clause[3:]),
+ ('name',) + tuple(clause[1:]),
+ ]
+ return domain
+
+
+class Template(metaclass=PoolMeta):
+ __name__ = 'product.template'
+ product_customers = fields.One2Many(
+ 'sale.product_customer', 'template', "Customers",
+ states={
+ 'invisible': ~Eval('salable', False),
+ },
+ domain=[
+ If(~Eval('active'), ('active', '=', False), ()),
+ ],
+ depends=['salable', 'active'])
+
+ def product_customer_used(self, **pattern):
+ for product_customer in self.product_customers:
+ if product_customer.match(pattern):
+ yield product_customer
+
+ @classmethod
+ def copy(cls, templates, default=None):
+ pool = Pool()
+ ProductCustomer = pool.get('sale.product_customer')
+ if default is None:
+ default = {}
+ else:
+ default = default.copy()
+
+ copy_customers = 'product_customers' not in default
+ default.setdefault('product_customers', None)
+ new_templates = super().copy(templates, default)
+ if copy_customers:
+ old2new = {}
+ to_copy = []
+ for template, new_template in zip(templates, new_templates):
+ to_copy.extend(
+ pc for pc in template.product_customers if not pc.product)
+ old2new[template.id] = new_template.id
+ if to_copy:
+ ProductCustomer.copy(to_copy, {
+ 'template': lambda d: old2new[d['template']],
+ })
+ return new_templates
+
+
+class Product(metaclass=PoolMeta):
+ __name__ = 'product.product'
+ product_customers = fields.One2Many(
+ 'sale.product_customer', 'product', "Customers",
+ domain=[
+ ('template', '=', Eval('template')),
+ If(~Eval('active'), ('active', '=', False), ()),
+ ],
+ states={
+ 'invisible': ~Eval('salable', False),
+ },
+ depends=['template', 'salable', 'active'])
+
+ def product_customer_used(self, **pattern):
+ for product_customer in self.product_customers:
+ if product_customer.match(pattern):
+ yield product_customer
+ pattern['product'] = None
+ yield from self.template.product_customer_used(**pattern)
+
+ @classmethod
+ def copy(cls, products, default=None):
+ pool = Pool()
+ ProductCustomer = pool.get('sale.product_customer')
+ if default is None:
+ default = {}
+ else:
+ default = default.copy()
+
+ copy_customers = 'product_customers' not in default
+ if 'template' in default:
+ default.setdefault('product_customers', None)
+ new_products = super().copy(products, default)
+ if 'template' in default and copy_customers:
+ template2new = {}
+ product2new = {}
+ to_copy = []
+ for product, new_product in zip(products, new_products):
+ if product.product_customers:
+ to_copy.extend(product.product_customers)
+ template2new[product.template.id] = new_product.template.id
+ product2new[product.id] = new_product.id
+ if to_copy:
+ ProductCustomer.copy(to_copy, {
+ 'product': lambda d: product2new[d['product']],
+ 'template': lambda d: template2new[d['template']],
+ })
+ return new_products
diff --git a/modules/sale_product_customer/product.xml b/modules/sale_product_customer/product.xml
new file mode 100644
index 0000000000..70184cd889
--- /dev/null
+++ b/modules/sale_product_customer/product.xml
@@ -0,0 +1,12 @@
+
+
+
+
+
+ product.template
+
+ template_form
+
+
+
diff --git a/modules/sale_product_customer/sale.py b/modules/sale_product_customer/sale.py
new file mode 100644
index 0000000000..d63568bd95
--- /dev/null
+++ b/modules/sale_product_customer/sale.py
@@ -0,0 +1,121 @@
+# This file is part of Tryton. The COPYRIGHT file at the top level of
+# this repository contains the full copyright notices and license terms.
+
+from trytond.model import fields
+from trytond.pool import PoolMeta
+from trytond.pyson import If, Bool, Eval
+
+
+class Line(metaclass=PoolMeta):
+ __name__ = 'sale.line'
+
+ product_customer = fields.Many2One(
+ 'sale.product_customer', "Customer's Product",
+ ondelete='RESTRICT',
+ domain=[
+ If(Bool(Eval('product')),
+ ['OR',
+ [
+ ('template.products', '=', Eval('product')),
+ ('product', '=', None),
+ ],
+ ('product', '=', Eval('product')),
+ ],
+ []),
+ ('party', '=', Eval('_parent_sale', {}).get('party')),
+ ],
+ states={
+ 'invisible': Eval('type') != 'line',
+ 'readonly': Eval('sale_state') != 'draft',
+ },
+ depends=['product', 'type', 'sale_state'])
+
+ @fields.depends('sale', '_parent_sale.party')
+ def _get_product_customer_pattern(self):
+ return {
+ 'party': (
+ self.sale.party.id if self.sale and self.sale.party else -1),
+ }
+
+ @fields.depends('product', 'product_customer',
+ methods=['_get_product_customer_pattern'])
+ def on_change_product(self):
+ super().on_change_product()
+ if not self.product:
+ return
+ product_customers = list(self.product.product_customer_used(
+ **self._get_product_customer_pattern()))
+ if len(product_customers) == 1:
+ self.product_customer, = product_customers
+ elif (self.product_customer
+ and self.product_customer not in product_customers):
+ self.product_customer = None
+
+ @fields.depends('product', 'product_customer',
+ methods=['on_change_product'])
+ def on_change_product_customer(self):
+ if self.product_customer:
+ if self.product_customer.product:
+ self.product = self.product_customer.product
+ elif not self.product:
+ if len(self.product_customer.template.products) == 1:
+ self.product, = self.product_customer.template.products
+ self.on_change_product()
+
+
+class AmendmentLine(metaclass=PoolMeta):
+ __name__ = 'sale.amendment.line'
+
+ product_customer = fields.Many2One(
+ 'sale.product_customer', "Customer's Product",
+ domain=[
+ ['OR',
+ [
+ ('template.products', '=', Eval('product')),
+ ('product', '=', None),
+ ],
+ ('product', '=', Eval('product')),
+ ],
+ ('party', '=', Eval('party', -1)),
+ ],
+ states={
+ 'invisible': Eval('action') != 'line',
+ },
+ depends=['action', 'product', 'party'])
+
+ @fields.depends('line')
+ def on_change_line(self):
+ super().on_change_line()
+ if self.line:
+ self.product_customer = self.line.product_customer
+
+ @fields.depends('product', 'product_customer', 'line')
+ def on_change_product(self):
+ try:
+ super().on_change_product()
+ except AttributeError:
+ pass
+ if not self.product or not self.line:
+ return
+ product_customers = list(self.product.product_customer_used(
+ **self.line._get_product_customer_pattern()))
+ if len(product_customers) == 1:
+ self.product_customer, = product_customers
+ elif (self.product_customer
+ and self.product_customer not in product_customers):
+ self.product_customer = None
+
+ @fields.depends('product', 'product_customer',
+ methods=['on_change_product'])
+ def on_change_product_customer(self):
+ if self.product_customer:
+ if self.product_customer.product:
+ self.product = self.product_customer.product
+ elif not self.product:
+ if len(self.product_customer.template.products) == 1:
+ self.product, = self.product_customer.template.products
+ self.on_change_product()
+
+ def _apply_line(self, sale, sale_line):
+ super()._apply_line(sale, sale_line)
+ sale_line.product_customer = self.product_customer
diff --git a/modules/sale_product_customer/sale.xml b/modules/sale_product_customer/sale.xml
new file mode 100644
index 0000000000..452492a96e
--- /dev/null
+++ b/modules/sale_product_customer/sale.xml
@@ -0,0 +1,88 @@
+
+
+
+
+
+ sale.line
+
+ sale_line_form
+
+
+ sale.line
+
+ sale_line_tree
+
+
+ sale.line
+
+ sale_line_tree_sequence
+
+
+
+ sale.product_customer
+ form
+ product_customer_form
+
+
+ sale.product_customer
+ tree
+
+ product_customer_tree
+
+
+
+ sale.product_customer
+ tree
+
+ product_customer_tree_sequence
+
+
+
+ Customers
+ sale.product_customer
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ sale.amendment.line
+
+ sale_amendment_line_form
+
+
+
diff --git a/modules/sale_product_customer/setup.py b/modules/sale_product_customer/setup.py
new file mode 100755
index 0000000000..be25abe7b9
--- /dev/null
+++ b/modules/sale_product_customer/setup.py
@@ -0,0 +1,151 @@
+#!/usr/bin/env python3
+# This file is part of Tryton. The COPYRIGHT file at the top level of
+# this repository contains the full copyright notices and license terms.
+
+import io
+import os
+import re
+from configparser import ConfigParser
+from setuptools import setup, find_packages
+
+
+def read(fname):
+ return io.open(
+ os.path.join(os.path.dirname(__file__), fname),
+ 'r', encoding='utf-8').read()
+
+
+def get_require_version(name):
+ if minor_version % 2:
+ require = '%s >= %s.%s.dev0, < %s.%s'
+ else:
+ require = '%s >= %s.%s, < %s.%s'
+ require %= (name, major_version, minor_version,
+ major_version, minor_version + 1)
+ return require
+
+
+config = ConfigParser()
+config.read_file(open(os.path.join(os.path.dirname(__file__), 'tryton.cfg')))
+info = dict(config.items('tryton'))
+for key in ('depends', 'extras_depend', 'xml'):
+ if key in info:
+ info[key] = info[key].strip().splitlines()
+version = info.get('version', '0.0.1')
+major_version, minor_version, _ = version.split('.', 2)
+major_version = int(major_version)
+minor_version = int(minor_version)
+name = 'trytond_sale_product_customer'
+
+download_url = 'http://downloads.tryton.org/%s.%s/' % (
+ major_version, minor_version)
+if minor_version % 2:
+ version = '%s.%s.dev0' % (major_version, minor_version)
+ download_url = (
+ 'hg+http://hg.tryton.org/modules/%s#egg=%s-%s' % (
+ name[8:], name, version))
+local_version = []
+if os.environ.get('CI_JOB_ID'):
+ local_version.append(os.environ['CI_JOB_ID'])
+else:
+ for build in ['CI_BUILD_NUMBER', 'CI_JOB_NUMBER']:
+ if os.environ.get(build):
+ local_version.append(os.environ[build])
+ else:
+ local_version = []
+ break
+if local_version:
+ version += '+' + '.'.join(local_version)
+
+requires = []
+for dep in info.get('depends', []):
+ if not re.match(r'(ir|res)(\W|$)', dep):
+ requires.append(get_require_version('trytond_%s' % dep))
+requires.append(get_require_version('trytond'))
+
+tests_require = [get_require_version('proteus'),
+ get_require_version('trytond_sale_amendment')]
+dependency_links = []
+if minor_version % 2:
+ dependency_links.append(
+ 'https://trydevpi.tryton.org/?local_version='
+ + '.'.join(local_version))
+
+setup(name=name,
+ version=version,
+ description='Tryton module to manage customer product on sale',
+ long_description=read('README.rst'),
+ author='Tryton',
+ author_email='bugs@tryton.org',
+ url='http://www.tryton.org/',
+ download_url=download_url,
+ project_urls={
+ "Bug Tracker": 'https://bugs.tryton.org/',
+ "Documentation": 'https://docs.tryton.org/',
+ "Forum": 'https://www.tryton.org/forum',
+ "Source Code": 'https://hg.tryton.org/modules/sale_product_customer',
+ },
+ keywords='tryton sale product customer',
+ package_dir={'trytond.modules.sale_product_customer': '.'},
+ packages=(
+ ['trytond.modules.sale_product_customer']
+ + ['trytond.modules.sale_product_customer.%s' % p
+ for p in find_packages()]
+ ),
+ package_data={
+ 'trytond.modules.sale_product_customer': (info.get('xml', [])
+ + ['tryton.cfg', 'view/*.xml', 'locale/*.po', '*.fodt',
+ 'icons/*.svg', 'tests/*.rst']),
+ },
+ classifiers=[
+ 'Development Status :: 5 - Production/Stable',
+ 'Environment :: Plugins',
+ 'Framework :: Tryton',
+ 'Intended Audience :: Developers',
+ 'Intended Audience :: Financial and Insurance Industry',
+ 'Intended Audience :: Legal Industry',
+ 'License :: OSI Approved :: '
+ 'GNU General Public License v3 or later (GPLv3+)',
+ 'Natural Language :: Bulgarian',
+ 'Natural Language :: Catalan',
+ 'Natural Language :: Chinese (Simplified)',
+ 'Natural Language :: Czech',
+ 'Natural Language :: Dutch',
+ 'Natural Language :: English',
+ 'Natural Language :: Finnish',
+ 'Natural Language :: French',
+ 'Natural Language :: German',
+ 'Natural Language :: Hungarian',
+ 'Natural Language :: Indonesian',
+ 'Natural Language :: Italian',
+ 'Natural Language :: Persian',
+ 'Natural Language :: Polish',
+ 'Natural Language :: Portuguese (Brazilian)',
+ 'Natural Language :: Romanian',
+ 'Natural Language :: Russian',
+ 'Natural Language :: Slovenian',
+ 'Natural Language :: Spanish',
+ 'Natural Language :: Turkish',
+ 'Operating System :: OS Independent',
+ 'Programming Language :: Python :: 3',
+ 'Programming Language :: Python :: 3.6',
+ 'Programming Language :: Python :: 3.7',
+ 'Programming Language :: Python :: 3.8',
+ 'Programming Language :: Python :: 3.9',
+ 'Programming Language :: Python :: Implementation :: CPython',
+ 'Programming Language :: Python :: Implementation :: PyPy',
+ 'Topic :: Office/Business',
+ ],
+ license='GPL-3',
+ python_requires='>=3.6',
+ install_requires=requires,
+ dependency_links=dependency_links,
+ zip_safe=False,
+ entry_points="""
+ [trytond.modules]
+ sale_product_customer = trytond.modules.sale_product_customer
+ """,
+ test_suite='tests',
+ test_loader='trytond.test_loader:Loader',
+ tests_require=tests_require,
+ )
diff --git a/modules/sale_product_customer/tests/__init__.py b/modules/sale_product_customer/tests/__init__.py
new file mode 100644
index 0000000000..070079cc97
--- /dev/null
+++ b/modules/sale_product_customer/tests/__init__.py
@@ -0,0 +1,9 @@
+# This file is part of Tryton. The COPYRIGHT file at the top level of
+# this repository contains the full copyright notices and license terms.
+
+try:
+ from trytond.modules.sale_product_customer.tests.test_sale_product_customer import suite # noqa: E501
+except ImportError:
+ from .test_sale_product_customer import suite
+
+__all__ = ['suite']
diff --git a/modules/sale_product_customer/tests/scenario_sale_copy_product_customer.rst b/modules/sale_product_customer/tests/scenario_sale_copy_product_customer.rst
new file mode 100644
index 0000000000..12244cb711
--- /dev/null
+++ b/modules/sale_product_customer/tests/scenario_sale_copy_product_customer.rst
@@ -0,0 +1,58 @@
+===================================
+Sale Copy Product Customer Scenario
+===================================
+
+Imports::
+
+ >>> from decimal import Decimal
+ >>> from proteus import Model
+ >>> from trytond.tests.tools import activate_modules
+ >>> from trytond.modules.company.tests.tools import create_company, \
+ ... get_company
+
+Activate modules::
+
+ >>> config = activate_modules('sale_product_customer')
+
+Create company::
+
+ >>> _ = create_company()
+ >>> company = get_company()
+
+Create party::
+
+ >>> Party = Model.get('party.party')
+ >>> customer = Party(name='customer')
+ >>> customer.save()
+
+Create a product with customers::
+
+ >>> ProductUom = Model.get('product.uom')
+ >>> unit, = ProductUom.find([('name', '=', 'Unit')])
+ >>> ProductTemplate = Model.get('product.template')
+
+ >>> template = ProductTemplate()
+ >>> template.name = 'product'
+ >>> template.default_uom = unit
+ >>> template.type = 'goods'
+ >>> template.salable = True
+ >>> template.list_price = Decimal('10')
+ >>> template.cost_price_method = 'fixed'
+ >>> product_customer = template.product_customers.new()
+ >>> product_customer.party = customer
+ >>> template.save()
+ >>> product, = template.products
+ >>> product_customer = product.product_customers.new()
+ >>> product_customer.party = customer
+ >>> product_customer.template == template
+ True
+ >>> product.save()
+
+Customer is copied when copying the template::
+
+ >>> template_copy, = template.duplicate()
+ >>> product_copy, = template_copy.products
+ >>> len(template_copy.product_customers)
+ 2
+ >>> len(product_copy.product_customers)
+ 1
diff --git a/modules/sale_product_customer/tests/scenario_sale_product_customer.rst b/modules/sale_product_customer/tests/scenario_sale_product_customer.rst
new file mode 100644
index 0000000000..0f1adc977e
--- /dev/null
+++ b/modules/sale_product_customer/tests/scenario_sale_product_customer.rst
@@ -0,0 +1,73 @@
+==============================
+Sale Product Customer Scenario
+==============================
+
+Imports::
+
+ >>> from decimal import Decimal
+ >>> from proteus import Model, Wizard
+ >>> from trytond.tests.tools import activate_modules
+ >>> from trytond.modules.company.tests.tools import create_company, \
+ ... get_company
+
+Activate modules::
+
+ >>> config = activate_modules('sale_product_customer')
+
+Create company::
+
+ >>> _ = create_company()
+ >>> company = get_company()
+
+Create parties::
+
+ >>> Party = Model.get('party.party')
+ >>> customer = Party(name='Customer')
+ >>> customer.save()
+
+Create product::
+
+ >>> ProductUom = Model.get('product.uom')
+ >>> unit, = ProductUom.find([('name', '=', 'Unit')])
+ >>> ProductTemplate = Model.get('product.template')
+
+ >>> template = ProductTemplate()
+ >>> template.name = 'product'
+ >>> template.default_uom = unit
+ >>> template.type = 'goods'
+ >>> template.salable = True
+ >>> template.list_price = Decimal('10')
+ >>> template.save()
+ >>> product, = template.products
+ >>> product_customer = product.product_customers.new()
+ >>> product_customer.party = customer
+ >>> product_customer.code = 'CUST'
+ >>> product.save()
+
+Create sale::
+
+ >>> Sale = Model.get('sale.sale')
+ >>> sale = Sale()
+ >>> sale.party = customer
+ >>> line = sale.lines.new()
+
+Check filling product customer::
+
+ >>> line.product = product
+ >>> line.product_customer.code
+ 'CUST'
+
+Add product customer to the template::
+
+ >>> product_customer2 = template.product_customers.new()
+ >>> product_customer2.party = customer
+ >>> product_customer2.code = 'TEMPCUST'
+ >>> template.save()
+
+Count product linked to customer::
+
+ >>> ProductCustomer = Model.get('sale.product_customer')
+ >>> products = ProductCustomer.find(
+ ... [('party', '=', customer.id)])
+ >>> len(products) == 2
+ True
diff --git a/modules/sale_product_customer/tests/test_sale_product_customer.py b/modules/sale_product_customer/tests/test_sale_product_customer.py
new file mode 100644
index 0000000000..fea3871b27
--- /dev/null
+++ b/modules/sale_product_customer/tests/test_sale_product_customer.py
@@ -0,0 +1,34 @@
+# This file is part of Tryton. The COPYRIGHT file at the top level of
+# this repository contains the full copyright notices and license terms.
+
+import unittest
+
+import doctest
+
+from trytond.tests.test_tryton import ModuleTestCase
+from trytond.tests.test_tryton import suite as test_suite
+from trytond.tests.test_tryton import doctest_teardown
+from trytond.tests.test_tryton import doctest_checker
+
+
+class SaleProductCustomerTestCase(ModuleTestCase):
+ 'Test Sale Product Customer module'
+ module = 'sale_product_customer'
+ extras = ['sale_amendment']
+
+
+def suite():
+ suite = test_suite()
+ suite.addTests(unittest.TestLoader().loadTestsFromTestCase(
+ SaleProductCustomerTestCase))
+ suite.addTests(doctest.DocFileSuite(
+ 'scenario_sale_product_customer.rst',
+ tearDown=doctest_teardown, encoding='utf-8',
+ checker=doctest_checker,
+ optionflags=doctest.REPORT_ONLY_FIRST_FAILURE))
+ suite.addTests(doctest.DocFileSuite(
+ 'scenario_sale_copy_product_customer.rst',
+ tearDown=doctest_teardown, encoding='utf-8',
+ checker=doctest_checker,
+ optionflags=doctest.REPORT_ONLY_FIRST_FAILURE))
+ return suite
diff --git a/modules/sale_product_customer/tox.ini b/modules/sale_product_customer/tox.ini
new file mode 100644
index 0000000000..197496c0cb
--- /dev/null
+++ b/modules/sale_product_customer/tox.ini
@@ -0,0 +1,15 @@
+[tox]
+envlist = {py36,py37,py38,py39}-{sqlite,postgresql},pypy3-{sqlite,postgresql}
+
+[testenv]
+commands = {envpython} setup.py test
+deps =
+ {py36,py37,py38,py39}-postgresql: psycopg2 >= 2.5
+ pypy3-postgresql: psycopg2cffi >= 2.5
+ py36-sqlite: sqlitebck
+setenv =
+ sqlite: TRYTOND_DATABASE_URI={env:SQLITE_URI:sqlite://}
+ postgresql: TRYTOND_DATABASE_URI={env:POSTGRESQL_URI:postgresql://}
+ sqlite: DB_NAME={env:SQLITE_NAME::memory:}
+ postgresql: DB_NAME={env:POSTGRESQL_NAME:test}
+install_command = pip install --pre --find-links https://trydevpi.tryton.org/?local_version={env:CI_JOB_ID:{env:CI_BUILD_NUMBER}.{env:CI_JOB_NUMBER}} {opts} {packages}
diff --git a/modules/sale_product_customer/tryton.cfg b/modules/sale_product_customer/tryton.cfg
new file mode 100644
index 0000000000..fd83bd509c
--- /dev/null
+++ b/modules/sale_product_customer/tryton.cfg
@@ -0,0 +1,11 @@
+[tryton]
+version=6.0.4
+depends:
+ ir
+ product
+ sale
+extras_depend:
+ sale_amendment
+xml:
+ product.xml
+ sale.xml
diff --git a/modules/sale_product_customer/view/product_customer_form.xml b/modules/sale_product_customer/view/product_customer_form.xml
new file mode 100644
index 0000000000..a5f844cced
--- /dev/null
+++ b/modules/sale_product_customer/view/product_customer_form.xml
@@ -0,0 +1,21 @@
+
+
+
diff --git a/modules/sale_product_customer/view/product_customer_tree.xml b/modules/sale_product_customer/view/product_customer_tree.xml
new file mode 100644
index 0000000000..e07df602bc
--- /dev/null
+++ b/modules/sale_product_customer/view/product_customer_tree.xml
@@ -0,0 +1,10 @@
+
+
+
+
+
+
+
+
+
diff --git a/modules/sale_product_customer/view/product_customer_tree_sequence.xml b/modules/sale_product_customer/view/product_customer_tree_sequence.xml
new file mode 100644
index 0000000000..f256576f08
--- /dev/null
+++ b/modules/sale_product_customer/view/product_customer_tree_sequence.xml
@@ -0,0 +1,10 @@
+
+
+
+
+
+
+
+
+
diff --git a/modules/sale_product_customer/view/sale_amendment_line_form.xml b/modules/sale_product_customer/view/sale_amendment_line_form.xml
new file mode 100644
index 0000000000..a401e72d94
--- /dev/null
+++ b/modules/sale_product_customer/view/sale_amendment_line_form.xml
@@ -0,0 +1,9 @@
+
+
+
+
+
+
+
+
diff --git a/modules/sale_product_customer/view/sale_line_form.xml b/modules/sale_product_customer/view/sale_line_form.xml
new file mode 100644
index 0000000000..3197fc8482
--- /dev/null
+++ b/modules/sale_product_customer/view/sale_line_form.xml
@@ -0,0 +1,9 @@
+
+
+
+
+
+
+
+
diff --git a/modules/sale_product_customer/view/sale_line_tree.xml b/modules/sale_product_customer/view/sale_line_tree.xml
new file mode 100644
index 0000000000..66292c34f6
--- /dev/null
+++ b/modules/sale_product_customer/view/sale_line_tree.xml
@@ -0,0 +1,8 @@
+
+
+
+
+
+
+
diff --git a/modules/sale_product_customer/view/sale_line_tree_sequence.xml b/modules/sale_product_customer/view/sale_line_tree_sequence.xml
new file mode 100644
index 0000000000..66292c34f6
--- /dev/null
+++ b/modules/sale_product_customer/view/sale_line_tree_sequence.xml
@@ -0,0 +1,8 @@
+
+
+
+
+
+
+
diff --git a/modules/sale_product_customer/view/template_form.xml b/modules/sale_product_customer/view/template_form.xml
new file mode 100644
index 0000000000..c58523d9b6
--- /dev/null
+++ b/modules/sale_product_customer/view/template_form.xml
@@ -0,0 +1,8 @@
+
+
+
+
+
+
+
diff --git a/modules/sale_promotion/.drone.yml b/modules/sale_promotion/.drone.yml
new file mode 100644
index 0000000000..2049d30a49
--- /dev/null
+++ b/modules/sale_promotion/.drone.yml
@@ -0,0 +1,68 @@
+clone:
+ hg:
+ image: plugins/hg
+ environment:
+ - HG_SHARE_POOL=/root/.cache/hg
+ volumes:
+ - cache:/root/.cache
+
+pipeline:
+ tox:
+ image: ${IMAGE}
+ environment:
+ - CFLAGS=-O0
+ - DB_CACHE=/cache
+ - TOX_TESTENV_PASSENV=CFLAGS DB_CACHE CI_BUILD_NUMBER CI_JOB_NUMBER CI_JOB_ID
+ - POSTGRESQL_URI=postgresql://postgres@postgresql:5432/
+ commands:
+ - echo "[extensions]" >> /root/.hgrc
+ - echo "hgext.share =" >> /root/.hgrc
+ - echo "[share]" >> /root/.hgrc
+ - echo "pool = /root/.cache/hg" >> /root/.hgrc
+ - pip install tox
+ - tox -e "${TOXENV}-${DATABASE}"
+ volumes:
+ - cache:/root/.cache
+ check_dist:
+ image: ${IMAGE}
+ commands:
+ - pip install twine
+ - python setup.py sdist
+ - twine check dist/*
+
+services:
+ postgresql:
+ image: postgres
+ environment:
+ - POSTGRES_HOST_AUTH_METHOD=trust
+ command: "-c fsync=off -c synchronous_commit=off -c full_page_writes=off"
+ when:
+ matrix:
+ DATABASE: postgresql
+
+matrix:
+ include:
+ - IMAGE: python:3.6
+ TOXENV: py36
+ DATABASE: sqlite
+ - IMAGE: python:3.6
+ TOXENV: py36
+ DATABASE: postgresql
+ - IMAGE: python:3.7
+ TOXENV: py37
+ DATABASE: sqlite
+ - IMAGE: python:3.7
+ TOXENV: py37
+ DATABASE: postgresql
+ - IMAGE: python:3.8
+ TOXENV: py38
+ DATABASE: sqlite
+ - IMAGE: python:3.8
+ TOXENV: py38
+ DATABASE: postgresql
+ - IMAGE: python:3.9
+ TOXENV: py39
+ DATABASE: sqlite
+ - IMAGE: python:3.9
+ TOXENV: py39
+ DATABASE: postgresql
diff --git a/modules/sale_promotion/.flake8 b/modules/sale_promotion/.flake8
new file mode 100644
index 0000000000..fa6b4f66d1
--- /dev/null
+++ b/modules/sale_promotion/.flake8
@@ -0,0 +1,2 @@
+[flake8]
+ignore=E123,E124,E126,E128,E741,W503
diff --git a/modules/sale_promotion/CHANGELOG b/modules/sale_promotion/CHANGELOG
new file mode 100644
index 0000000000..174957f06a
--- /dev/null
+++ b/modules/sale_promotion/CHANGELOG
@@ -0,0 +1,50 @@
+Version 6.0.2 - 2021-11-04
+* Bug fixes (see mercurial logs for details)
+
+Version 6.0.1 - 2021-10-01
+* Bug fixes (see mercurial logs for details)
+
+Version 6.0.0 - 2021-05-03
+* Bug fixes (see mercurial logs for details)
+* Apply promotion per amount of sale
+
+Version 5.8.0 - 2020-11-02
+* Bug fixes (see mercurial logs for details)
+* Remove support for Python 3.5
+* Apply promotion on any reduced line
+
+Version 5.6.0 - 2020-05-04
+* Bug fixes (see mercurial logs for details)
+
+Version 5.4.0 - 2019-11-04
+* Bug fixes (see mercurial logs for details)
+
+Version 5.2.0 - 2019-05-06
+* Bug fixes (see mercurial logs for details)
+
+Version 5.0.0 - 2018-10-01
+* Bug fixes (see mercurial logs for details)
+* Do not apply promotion on free or empty product
+* Remove support for Python 2.7
+
+Version 4.8.0 - 2018-04-23
+* Bug fixes (see mercurial logs for details)
+* Add list of categories on promotion
+* Remove unit constraint on list of products from promotion
+
+Version 4.6.0 - 2017-10-30
+* Bug fixes (see mercurial logs for details)
+* Support price list when computing unit price
+
+Version 4.4.0 - 2017-05-01
+* Bug fixes (see mercurial logs for details)
+
+Version 4.2.0 - 2016-11-28
+* Bug fixes (see mercurial logs for details)
+
+Version 4.0.0 - 2016-05-02
+* Bug fixes (see mercurial logs for details)
+* Add Python3 support
+
+Version 3.8.0 - 2015-11-02
+* Initial release
diff --git a/modules/sale_promotion/COPYRIGHT b/modules/sale_promotion/COPYRIGHT
new file mode 100644
index 0000000000..3f6095d527
--- /dev/null
+++ b/modules/sale_promotion/COPYRIGHT
@@ -0,0 +1,15 @@
+Copyright (C) 2015-2021 Cédric Krier.
+Copyright (C) 2015-2021 B2CK SPRL.
+
+This program is free software: you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation, either version 3 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program. If not, see .
diff --git a/modules/sale_promotion/LICENSE b/modules/sale_promotion/LICENSE
new file mode 100644
index 0000000000..94a9ed024d
--- /dev/null
+++ b/modules/sale_promotion/LICENSE
@@ -0,0 +1,674 @@
+ GNU GENERAL PUBLIC LICENSE
+ Version 3, 29 June 2007
+
+ Copyright (C) 2007 Free Software Foundation, Inc.
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+ Preamble
+
+ The GNU General Public License is a free, copyleft license for
+software and other kinds of works.
+
+ The licenses for most software and other practical works are designed
+to take away your freedom to share and change the works. By contrast,
+the GNU General Public License is intended to guarantee your freedom to
+share and change all versions of a program--to make sure it remains free
+software for all its users. We, the Free Software Foundation, use the
+GNU General Public License for most of our software; it applies also to
+any other work released this way by its authors. You can apply it to
+your programs, too.
+
+ When we speak of free software, we are referring to freedom, not
+price. Our General Public Licenses are designed to make sure that you
+have the freedom to distribute copies of free software (and charge for
+them if you wish), that you receive source code or can get it if you
+want it, that you can change the software or use pieces of it in new
+free programs, and that you know you can do these things.
+
+ To protect your rights, we need to prevent others from denying you
+these rights or asking you to surrender the rights. Therefore, you have
+certain responsibilities if you distribute copies of the software, or if
+you modify it: responsibilities to respect the freedom of others.
+
+ For example, if you distribute copies of such a program, whether
+gratis or for a fee, you must pass on to the recipients the same
+freedoms that you received. You must make sure that they, too, receive
+or can get the source code. And you must show them these terms so they
+know their rights.
+
+ Developers that use the GNU GPL protect your rights with two steps:
+(1) assert copyright on the software, and (2) offer you this License
+giving you legal permission to copy, distribute and/or modify it.
+
+ For the developers' and authors' protection, the GPL clearly explains
+that there is no warranty for this free software. For both users' and
+authors' sake, the GPL requires that modified versions be marked as
+changed, so that their problems will not be attributed erroneously to
+authors of previous versions.
+
+ Some devices are designed to deny users access to install or run
+modified versions of the software inside them, although the manufacturer
+can do so. This is fundamentally incompatible with the aim of
+protecting users' freedom to change the software. The systematic
+pattern of such abuse occurs in the area of products for individuals to
+use, which is precisely where it is most unacceptable. Therefore, we
+have designed this version of the GPL to prohibit the practice for those
+products. If such problems arise substantially in other domains, we
+stand ready to extend this provision to those domains in future versions
+of the GPL, as needed to protect the freedom of users.
+
+ Finally, every program is threatened constantly by software patents.
+States should not allow patents to restrict development and use of
+software on general-purpose computers, but in those that do, we wish to
+avoid the special danger that patents applied to a free program could
+make it effectively proprietary. To prevent this, the GPL assures that
+patents cannot be used to render the program non-free.
+
+ The precise terms and conditions for copying, distribution and
+modification follow.
+
+ TERMS AND CONDITIONS
+
+ 0. Definitions.
+
+ "This License" refers to version 3 of the GNU General Public License.
+
+ "Copyright" also means copyright-like laws that apply to other kinds of
+works, such as semiconductor masks.
+
+ "The Program" refers to any copyrightable work licensed under this
+License. Each licensee is addressed as "you". "Licensees" and
+"recipients" may be individuals or organizations.
+
+ To "modify" a work means to copy from or adapt all or part of the work
+in a fashion requiring copyright permission, other than the making of an
+exact copy. The resulting work is called a "modified version" of the
+earlier work or a work "based on" the earlier work.
+
+ A "covered work" means either the unmodified Program or a work based
+on the Program.
+
+ To "propagate" a work means to do anything with it that, without
+permission, would make you directly or secondarily liable for
+infringement under applicable copyright law, except executing it on a
+computer or modifying a private copy. Propagation includes copying,
+distribution (with or without modification), making available to the
+public, and in some countries other activities as well.
+
+ To "convey" a work means any kind of propagation that enables other
+parties to make or receive copies. Mere interaction with a user through
+a computer network, with no transfer of a copy, is not conveying.
+
+ An interactive user interface displays "Appropriate Legal Notices"
+to the extent that it includes a convenient and prominently visible
+feature that (1) displays an appropriate copyright notice, and (2)
+tells the user that there is no warranty for the work (except to the
+extent that warranties are provided), that licensees may convey the
+work under this License, and how to view a copy of this License. If
+the interface presents a list of user commands or options, such as a
+menu, a prominent item in the list meets this criterion.
+
+ 1. Source Code.
+
+ The "source code" for a work means the preferred form of the work
+for making modifications to it. "Object code" means any non-source
+form of a work.
+
+ A "Standard Interface" means an interface that either is an official
+standard defined by a recognized standards body, or, in the case of
+interfaces specified for a particular programming language, one that
+is widely used among developers working in that language.
+
+ The "System Libraries" of an executable work include anything, other
+than the work as a whole, that (a) is included in the normal form of
+packaging a Major Component, but which is not part of that Major
+Component, and (b) serves only to enable use of the work with that
+Major Component, or to implement a Standard Interface for which an
+implementation is available to the public in source code form. A
+"Major Component", in this context, means a major essential component
+(kernel, window system, and so on) of the specific operating system
+(if any) on which the executable work runs, or a compiler used to
+produce the work, or an object code interpreter used to run it.
+
+ The "Corresponding Source" for a work in object code form means all
+the source code needed to generate, install, and (for an executable
+work) run the object code and to modify the work, including scripts to
+control those activities. However, it does not include the work's
+System Libraries, or general-purpose tools or generally available free
+programs which are used unmodified in performing those activities but
+which are not part of the work. For example, Corresponding Source
+includes interface definition files associated with source files for
+the work, and the source code for shared libraries and dynamically
+linked subprograms that the work is specifically designed to require,
+such as by intimate data communication or control flow between those
+subprograms and other parts of the work.
+
+ The Corresponding Source need not include anything that users
+can regenerate automatically from other parts of the Corresponding
+Source.
+
+ The Corresponding Source for a work in source code form is that
+same work.
+
+ 2. Basic Permissions.
+
+ All rights granted under this License are granted for the term of
+copyright on the Program, and are irrevocable provided the stated
+conditions are met. This License explicitly affirms your unlimited
+permission to run the unmodified Program. The output from running a
+covered work is covered by this License only if the output, given its
+content, constitutes a covered work. This License acknowledges your
+rights of fair use or other equivalent, as provided by copyright law.
+
+ You may make, run and propagate covered works that you do not
+convey, without conditions so long as your license otherwise remains
+in force. You may convey covered works to others for the sole purpose
+of having them make modifications exclusively for you, or provide you
+with facilities for running those works, provided that you comply with
+the terms of this License in conveying all material for which you do
+not control copyright. Those thus making or running the covered works
+for you must do so exclusively on your behalf, under your direction
+and control, on terms that prohibit them from making any copies of
+your copyrighted material outside their relationship with you.
+
+ Conveying under any other circumstances is permitted solely under
+the conditions stated below. Sublicensing is not allowed; section 10
+makes it unnecessary.
+
+ 3. Protecting Users' Legal Rights From Anti-Circumvention Law.
+
+ No covered work shall be deemed part of an effective technological
+measure under any applicable law fulfilling obligations under article
+11 of the WIPO copyright treaty adopted on 20 December 1996, or
+similar laws prohibiting or restricting circumvention of such
+measures.
+
+ When you convey a covered work, you waive any legal power to forbid
+circumvention of technological measures to the extent such circumvention
+is effected by exercising rights under this License with respect to
+the covered work, and you disclaim any intention to limit operation or
+modification of the work as a means of enforcing, against the work's
+users, your or third parties' legal rights to forbid circumvention of
+technological measures.
+
+ 4. Conveying Verbatim Copies.
+
+ You may convey verbatim copies of the Program's source code as you
+receive it, in any medium, provided that you conspicuously and
+appropriately publish on each copy an appropriate copyright notice;
+keep intact all notices stating that this License and any
+non-permissive terms added in accord with section 7 apply to the code;
+keep intact all notices of the absence of any warranty; and give all
+recipients a copy of this License along with the Program.
+
+ You may charge any price or no price for each copy that you convey,
+and you may offer support or warranty protection for a fee.
+
+ 5. Conveying Modified Source Versions.
+
+ You may convey a work based on the Program, or the modifications to
+produce it from the Program, in the form of source code under the
+terms of section 4, provided that you also meet all of these conditions:
+
+ a) The work must carry prominent notices stating that you modified
+ it, and giving a relevant date.
+
+ b) The work must carry prominent notices stating that it is
+ released under this License and any conditions added under section
+ 7. This requirement modifies the requirement in section 4 to
+ "keep intact all notices".
+
+ c) You must license the entire work, as a whole, under this
+ License to anyone who comes into possession of a copy. This
+ License will therefore apply, along with any applicable section 7
+ additional terms, to the whole of the work, and all its parts,
+ regardless of how they are packaged. This License gives no
+ permission to license the work in any other way, but it does not
+ invalidate such permission if you have separately received it.
+
+ d) If the work has interactive user interfaces, each must display
+ Appropriate Legal Notices; however, if the Program has interactive
+ interfaces that do not display Appropriate Legal Notices, your
+ work need not make them do so.
+
+ A compilation of a covered work with other separate and independent
+works, which are not by their nature extensions of the covered work,
+and which are not combined with it such as to form a larger program,
+in or on a volume of a storage or distribution medium, is called an
+"aggregate" if the compilation and its resulting copyright are not
+used to limit the access or legal rights of the compilation's users
+beyond what the individual works permit. Inclusion of a covered work
+in an aggregate does not cause this License to apply to the other
+parts of the aggregate.
+
+ 6. Conveying Non-Source Forms.
+
+ You may convey a covered work in object code form under the terms
+of sections 4 and 5, provided that you also convey the
+machine-readable Corresponding Source under the terms of this License,
+in one of these ways:
+
+ a) Convey the object code in, or embodied in, a physical product
+ (including a physical distribution medium), accompanied by the
+ Corresponding Source fixed on a durable physical medium
+ customarily used for software interchange.
+
+ b) Convey the object code in, or embodied in, a physical product
+ (including a physical distribution medium), accompanied by a
+ written offer, valid for at least three years and valid for as
+ long as you offer spare parts or customer support for that product
+ model, to give anyone who possesses the object code either (1) a
+ copy of the Corresponding Source for all the software in the
+ product that is covered by this License, on a durable physical
+ medium customarily used for software interchange, for a price no
+ more than your reasonable cost of physically performing this
+ conveying of source, or (2) access to copy the
+ Corresponding Source from a network server at no charge.
+
+ c) Convey individual copies of the object code with a copy of the
+ written offer to provide the Corresponding Source. This
+ alternative is allowed only occasionally and noncommercially, and
+ only if you received the object code with such an offer, in accord
+ with subsection 6b.
+
+ d) Convey the object code by offering access from a designated
+ place (gratis or for a charge), and offer equivalent access to the
+ Corresponding Source in the same way through the same place at no
+ further charge. You need not require recipients to copy the
+ Corresponding Source along with the object code. If the place to
+ copy the object code is a network server, the Corresponding Source
+ may be on a different server (operated by you or a third party)
+ that supports equivalent copying facilities, provided you maintain
+ clear directions next to the object code saying where to find the
+ Corresponding Source. Regardless of what server hosts the
+ Corresponding Source, you remain obligated to ensure that it is
+ available for as long as needed to satisfy these requirements.
+
+ e) Convey the object code using peer-to-peer transmission, provided
+ you inform other peers where the object code and Corresponding
+ Source of the work are being offered to the general public at no
+ charge under subsection 6d.
+
+ A separable portion of the object code, whose source code is excluded
+from the Corresponding Source as a System Library, need not be
+included in conveying the object code work.
+
+ A "User Product" is either (1) a "consumer product", which means any
+tangible personal property which is normally used for personal, family,
+or household purposes, or (2) anything designed or sold for incorporation
+into a dwelling. In determining whether a product is a consumer product,
+doubtful cases shall be resolved in favor of coverage. For a particular
+product received by a particular user, "normally used" refers to a
+typical or common use of that class of product, regardless of the status
+of the particular user or of the way in which the particular user
+actually uses, or expects or is expected to use, the product. A product
+is a consumer product regardless of whether the product has substantial
+commercial, industrial or non-consumer uses, unless such uses represent
+the only significant mode of use of the product.
+
+ "Installation Information" for a User Product means any methods,
+procedures, authorization keys, or other information required to install
+and execute modified versions of a covered work in that User Product from
+a modified version of its Corresponding Source. The information must
+suffice to ensure that the continued functioning of the modified object
+code is in no case prevented or interfered with solely because
+modification has been made.
+
+ If you convey an object code work under this section in, or with, or
+specifically for use in, a User Product, and the conveying occurs as
+part of a transaction in which the right of possession and use of the
+User Product is transferred to the recipient in perpetuity or for a
+fixed term (regardless of how the transaction is characterized), the
+Corresponding Source conveyed under this section must be accompanied
+by the Installation Information. But this requirement does not apply
+if neither you nor any third party retains the ability to install
+modified object code on the User Product (for example, the work has
+been installed in ROM).
+
+ The requirement to provide Installation Information does not include a
+requirement to continue to provide support service, warranty, or updates
+for a work that has been modified or installed by the recipient, or for
+the User Product in which it has been modified or installed. Access to a
+network may be denied when the modification itself materially and
+adversely affects the operation of the network or violates the rules and
+protocols for communication across the network.
+
+ Corresponding Source conveyed, and Installation Information provided,
+in accord with this section must be in a format that is publicly
+documented (and with an implementation available to the public in
+source code form), and must require no special password or key for
+unpacking, reading or copying.
+
+ 7. Additional Terms.
+
+ "Additional permissions" are terms that supplement the terms of this
+License by making exceptions from one or more of its conditions.
+Additional permissions that are applicable to the entire Program shall
+be treated as though they were included in this License, to the extent
+that they are valid under applicable law. If additional permissions
+apply only to part of the Program, that part may be used separately
+under those permissions, but the entire Program remains governed by
+this License without regard to the additional permissions.
+
+ When you convey a copy of a covered work, you may at your option
+remove any additional permissions from that copy, or from any part of
+it. (Additional permissions may be written to require their own
+removal in certain cases when you modify the work.) You may place
+additional permissions on material, added by you to a covered work,
+for which you have or can give appropriate copyright permission.
+
+ Notwithstanding any other provision of this License, for material you
+add to a covered work, you may (if authorized by the copyright holders of
+that material) supplement the terms of this License with terms:
+
+ a) Disclaiming warranty or limiting liability differently from the
+ terms of sections 15 and 16 of this License; or
+
+ b) Requiring preservation of specified reasonable legal notices or
+ author attributions in that material or in the Appropriate Legal
+ Notices displayed by works containing it; or
+
+ c) Prohibiting misrepresentation of the origin of that material, or
+ requiring that modified versions of such material be marked in
+ reasonable ways as different from the original version; or
+
+ d) Limiting the use for publicity purposes of names of licensors or
+ authors of the material; or
+
+ e) Declining to grant rights under trademark law for use of some
+ trade names, trademarks, or service marks; or
+
+ f) Requiring indemnification of licensors and authors of that
+ material by anyone who conveys the material (or modified versions of
+ it) with contractual assumptions of liability to the recipient, for
+ any liability that these contractual assumptions directly impose on
+ those licensors and authors.
+
+ All other non-permissive additional terms are considered "further
+restrictions" within the meaning of section 10. If the Program as you
+received it, or any part of it, contains a notice stating that it is
+governed by this License along with a term that is a further
+restriction, you may remove that term. If a license document contains
+a further restriction but permits relicensing or conveying under this
+License, you may add to a covered work material governed by the terms
+of that license document, provided that the further restriction does
+not survive such relicensing or conveying.
+
+ If you add terms to a covered work in accord with this section, you
+must place, in the relevant source files, a statement of the
+additional terms that apply to those files, or a notice indicating
+where to find the applicable terms.
+
+ Additional terms, permissive or non-permissive, may be stated in the
+form of a separately written license, or stated as exceptions;
+the above requirements apply either way.
+
+ 8. Termination.
+
+ You may not propagate or modify a covered work except as expressly
+provided under this License. Any attempt otherwise to propagate or
+modify it is void, and will automatically terminate your rights under
+this License (including any patent licenses granted under the third
+paragraph of section 11).
+
+ However, if you cease all violation of this License, then your
+license from a particular copyright holder is reinstated (a)
+provisionally, unless and until the copyright holder explicitly and
+finally terminates your license, and (b) permanently, if the copyright
+holder fails to notify you of the violation by some reasonable means
+prior to 60 days after the cessation.
+
+ Moreover, your license from a particular copyright holder is
+reinstated permanently if the copyright holder notifies you of the
+violation by some reasonable means, this is the first time you have
+received notice of violation of this License (for any work) from that
+copyright holder, and you cure the violation prior to 30 days after
+your receipt of the notice.
+
+ Termination of your rights under this section does not terminate the
+licenses of parties who have received copies or rights from you under
+this License. If your rights have been terminated and not permanently
+reinstated, you do not qualify to receive new licenses for the same
+material under section 10.
+
+ 9. Acceptance Not Required for Having Copies.
+
+ You are not required to accept this License in order to receive or
+run a copy of the Program. Ancillary propagation of a covered work
+occurring solely as a consequence of using peer-to-peer transmission
+to receive a copy likewise does not require acceptance. However,
+nothing other than this License grants you permission to propagate or
+modify any covered work. These actions infringe copyright if you do
+not accept this License. Therefore, by modifying or propagating a
+covered work, you indicate your acceptance of this License to do so.
+
+ 10. Automatic Licensing of Downstream Recipients.
+
+ Each time you convey a covered work, the recipient automatically
+receives a license from the original licensors, to run, modify and
+propagate that work, subject to this License. You are not responsible
+for enforcing compliance by third parties with this License.
+
+ An "entity transaction" is a transaction transferring control of an
+organization, or substantially all assets of one, or subdividing an
+organization, or merging organizations. If propagation of a covered
+work results from an entity transaction, each party to that
+transaction who receives a copy of the work also receives whatever
+licenses to the work the party's predecessor in interest had or could
+give under the previous paragraph, plus a right to possession of the
+Corresponding Source of the work from the predecessor in interest, if
+the predecessor has it or can get it with reasonable efforts.
+
+ You may not impose any further restrictions on the exercise of the
+rights granted or affirmed under this License. For example, you may
+not impose a license fee, royalty, or other charge for exercise of
+rights granted under this License, and you may not initiate litigation
+(including a cross-claim or counterclaim in a lawsuit) alleging that
+any patent claim is infringed by making, using, selling, offering for
+sale, or importing the Program or any portion of it.
+
+ 11. Patents.
+
+ A "contributor" is a copyright holder who authorizes use under this
+License of the Program or a work on which the Program is based. The
+work thus licensed is called the contributor's "contributor version".
+
+ A contributor's "essential patent claims" are all patent claims
+owned or controlled by the contributor, whether already acquired or
+hereafter acquired, that would be infringed by some manner, permitted
+by this License, of making, using, or selling its contributor version,
+but do not include claims that would be infringed only as a
+consequence of further modification of the contributor version. For
+purposes of this definition, "control" includes the right to grant
+patent sublicenses in a manner consistent with the requirements of
+this License.
+
+ Each contributor grants you a non-exclusive, worldwide, royalty-free
+patent license under the contributor's essential patent claims, to
+make, use, sell, offer for sale, import and otherwise run, modify and
+propagate the contents of its contributor version.
+
+ In the following three paragraphs, a "patent license" is any express
+agreement or commitment, however denominated, not to enforce a patent
+(such as an express permission to practice a patent or covenant not to
+sue for patent infringement). To "grant" such a patent license to a
+party means to make such an agreement or commitment not to enforce a
+patent against the party.
+
+ If you convey a covered work, knowingly relying on a patent license,
+and the Corresponding Source of the work is not available for anyone
+to copy, free of charge and under the terms of this License, through a
+publicly available network server or other readily accessible means,
+then you must either (1) cause the Corresponding Source to be so
+available, or (2) arrange to deprive yourself of the benefit of the
+patent license for this particular work, or (3) arrange, in a manner
+consistent with the requirements of this License, to extend the patent
+license to downstream recipients. "Knowingly relying" means you have
+actual knowledge that, but for the patent license, your conveying the
+covered work in a country, or your recipient's use of the covered work
+in a country, would infringe one or more identifiable patents in that
+country that you have reason to believe are valid.
+
+ If, pursuant to or in connection with a single transaction or
+arrangement, you convey, or propagate by procuring conveyance of, a
+covered work, and grant a patent license to some of the parties
+receiving the covered work authorizing them to use, propagate, modify
+or convey a specific copy of the covered work, then the patent license
+you grant is automatically extended to all recipients of the covered
+work and works based on it.
+
+ A patent license is "discriminatory" if it does not include within
+the scope of its coverage, prohibits the exercise of, or is
+conditioned on the non-exercise of one or more of the rights that are
+specifically granted under this License. You may not convey a covered
+work if you are a party to an arrangement with a third party that is
+in the business of distributing software, under which you make payment
+to the third party based on the extent of your activity of conveying
+the work, and under which the third party grants, to any of the
+parties who would receive the covered work from you, a discriminatory
+patent license (a) in connection with copies of the covered work
+conveyed by you (or copies made from those copies), or (b) primarily
+for and in connection with specific products or compilations that
+contain the covered work, unless you entered into that arrangement,
+or that patent license was granted, prior to 28 March 2007.
+
+ Nothing in this License shall be construed as excluding or limiting
+any implied license or other defenses to infringement that may
+otherwise be available to you under applicable patent law.
+
+ 12. No Surrender of Others' Freedom.
+
+ If conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License. If you cannot convey a
+covered work so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you may
+not convey it at all. For example, if you agree to terms that obligate you
+to collect a royalty for further conveying from those to whom you convey
+the Program, the only way you could satisfy both those terms and this
+License would be to refrain entirely from conveying the Program.
+
+ 13. Use with the GNU Affero General Public License.
+
+ Notwithstanding any other provision of this License, you have
+permission to link or combine any covered work with a work licensed
+under version 3 of the GNU Affero General Public License into a single
+combined work, and to convey the resulting work. The terms of this
+License will continue to apply to the part which is the covered work,
+but the special requirements of the GNU Affero General Public License,
+section 13, concerning interaction through a network will apply to the
+combination as such.
+
+ 14. Revised Versions of this License.
+
+ The Free Software Foundation may publish revised and/or new versions of
+the GNU General Public License from time to time. Such new versions will
+be similar in spirit to the present version, but may differ in detail to
+address new problems or concerns.
+
+ Each version is given a distinguishing version number. If the
+Program specifies that a certain numbered version of the GNU General
+Public License "or any later version" applies to it, you have the
+option of following the terms and conditions either of that numbered
+version or of any later version published by the Free Software
+Foundation. If the Program does not specify a version number of the
+GNU General Public License, you may choose any version ever published
+by the Free Software Foundation.
+
+ If the Program specifies that a proxy can decide which future
+versions of the GNU General Public License can be used, that proxy's
+public statement of acceptance of a version permanently authorizes you
+to choose that version for the Program.
+
+ Later license versions may give you additional or different
+permissions. However, no additional obligations are imposed on any
+author or copyright holder as a result of your choosing to follow a
+later version.
+
+ 15. Disclaimer of Warranty.
+
+ THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY
+APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT
+HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY
+OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO,
+THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM
+IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF
+ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
+
+ 16. Limitation of Liability.
+
+ IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS
+THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY
+GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE
+USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF
+DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD
+PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS),
+EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF
+SUCH DAMAGES.
+
+ 17. Interpretation of Sections 15 and 16.
+
+ If the disclaimer of warranty and limitation of liability provided
+above cannot be given local legal effect according to their terms,
+reviewing courts shall apply local law that most closely approximates
+an absolute waiver of all civil liability in connection with the
+Program, unless a warranty or assumption of liability accompanies a
+copy of the Program in return for a fee.
+
+ END OF TERMS AND CONDITIONS
+
+ How to Apply These Terms to Your New Programs
+
+ If you develop a new program, and you want it to be of the greatest
+possible use to the public, the best way to achieve this is to make it
+free software which everyone can redistribute and change under these terms.
+
+ To do so, attach the following notices to the program. It is safest
+to attach them to the start of each source file to most effectively
+state the exclusion of warranty; and each file should have at least
+the "copyright" line and a pointer to where the full notice is found.
+
+
+ Copyright (C)
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see .
+
+Also add information on how to contact you by electronic and paper mail.
+
+ If the program does terminal interaction, make it output a short
+notice like this when it starts in an interactive mode:
+
+ Copyright (C)
+ This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
+ This is free software, and you are welcome to redistribute it
+ under certain conditions; type `show c' for details.
+
+The hypothetical commands `show w' and `show c' should show the appropriate
+parts of the General Public License. Of course, your program's commands
+might be different; for a GUI interface, you would use an "about box".
+
+ You should also get your employer (if you work as a programmer) or school,
+if any, to sign a "copyright disclaimer" for the program, if necessary.
+For more information on this, and how to apply and follow the GNU GPL, see
+.
+
+ The GNU General Public License does not permit incorporating your program
+into proprietary programs. If your program is a subroutine library, you
+may consider it more useful to permit linking proprietary applications with
+the library. If this is what you want to do, use the GNU Lesser General
+Public License instead of this License. But first, please read
+.
diff --git a/modules/sale_promotion/MANIFEST.in b/modules/sale_promotion/MANIFEST.in
new file mode 100644
index 0000000000..e88b2348a3
--- /dev/null
+++ b/modules/sale_promotion/MANIFEST.in
@@ -0,0 +1,5 @@
+include CHANGELOG
+include COPYRIGHT
+include LICENSE
+include README.rst
+include doc/*
diff --git a/modules/sale_promotion/README.rst b/modules/sale_promotion/README.rst
new file mode 120000
index 0000000000..176d9c2695
--- /dev/null
+++ b/modules/sale_promotion/README.rst
@@ -0,0 +1 @@
+doc/index.rst
\ No newline at end of file
diff --git a/modules/sale_promotion/__init__.py b/modules/sale_promotion/__init__.py
new file mode 100644
index 0000000000..eaf8a1dcb7
--- /dev/null
+++ b/modules/sale_promotion/__init__.py
@@ -0,0 +1,15 @@
+# This file is part of Tryton. The COPYRIGHT file at the top level of
+# this repository contains the full copyright notices and license terms.
+
+from trytond.pool import Pool
+from . import sale
+
+
+def register():
+ Pool.register(
+ sale.Promotion,
+ sale.Promotion_Product,
+ sale.Promotion_ProductCategory,
+ sale.Sale,
+ sale.Line,
+ module='sale_promotion', type_='model')
diff --git a/modules/sale_promotion/doc/index.rst b/modules/sale_promotion/doc/index.rst
new file mode 100644
index 0000000000..3e9a61e32b
--- /dev/null
+++ b/modules/sale_promotion/doc/index.rst
@@ -0,0 +1,25 @@
+Sale Promotion
+##############
+
+The sale_promotion module allows to apply promotions on sale based on criteria.
+
+The promotion is applied by changing the unit price of the affected lines when
+the sale goes into quotation but the unit price is restored when going back to
+draft.
+
+Sale Promotion
+**************
+
+Each matching *Sale Promotion* is considered for application but only those who
+reduces the unit price of the lines are really applied.
+The criteria are the fields:
+
+- *Company*: The company should be the same as the sale.
+- *Price List*: The sale price list.
+- *Start Date*/*End Date*: The period for which the promotion is valid.
+- *Amount*: The amount of the sale.
+- *Quantity*: The sum quantity of the sale lines which have the same *Unit*.
+- *Products*: The list of products to apply the promotion.
+- *Categories*: The list of product categories to apply the promotion.
+
+The new unit price is computed by the field *Formula*.
diff --git a/modules/sale_promotion/exceptions.py b/modules/sale_promotion/exceptions.py
new file mode 100644
index 0000000000..801fcd7bf7
--- /dev/null
+++ b/modules/sale_promotion/exceptions.py
@@ -0,0 +1,8 @@
+# This file is part of Tryton. The COPYRIGHT file at the top level of
+# this repository contains the full copyright notices and license terms.
+
+from trytond.model.exceptions import ValidationError
+
+
+class FormulaError(ValidationError):
+ pass
diff --git a/modules/sale_promotion/locale/bg.po b/modules/sale_promotion/locale/bg.po
new file mode 100644
index 0000000000..5041374bf4
--- /dev/null
+++ b/modules/sale_promotion/locale/bg.po
@@ -0,0 +1,146 @@
+#
+msgid ""
+msgstr "Content-Type: text/plain; charset=utf-8\n"
+
+msgctxt "field:sale.line,draft_unit_price:"
+msgid "Draft Unit Price"
+msgstr ""
+
+#, fuzzy
+msgctxt "field:sale.line,promotion:"
+msgid "Promotion"
+msgstr "Promotions"
+
+msgctxt "field:sale.promotion,amount:"
+msgid "Amount"
+msgstr ""
+
+msgctxt "field:sale.promotion,categories:"
+msgid "Categories"
+msgstr ""
+
+#, fuzzy
+msgctxt "field:sale.promotion,company:"
+msgid "Company"
+msgstr "Фирма"
+
+msgctxt "field:sale.promotion,currency:"
+msgid "Currency"
+msgstr ""
+
+#, fuzzy
+msgctxt "field:sale.promotion,currency_digits:"
+msgid "Currency Digits"
+msgstr "Десетични единици"
+
+#, fuzzy
+msgctxt "field:sale.promotion,end_date:"
+msgid "End Date"
+msgstr "Крайна дата"
+
+#, fuzzy
+msgctxt "field:sale.promotion,formula:"
+msgid "Formula"
+msgstr "Формула"
+
+#, fuzzy
+msgctxt "field:sale.promotion,name:"
+msgid "Name"
+msgstr "Условие за плащане"
+
+#, fuzzy
+msgctxt "field:sale.promotion,price_list:"
+msgid "Price List"
+msgstr "Ценова листа"
+
+#, fuzzy
+msgctxt "field:sale.promotion,products:"
+msgid "Products"
+msgstr "Продукти по местонахождения"
+
+#, fuzzy
+msgctxt "field:sale.promotion,quantity:"
+msgid "Quantity"
+msgstr "Количество"
+
+#, fuzzy
+msgctxt "field:sale.promotion,start_date:"
+msgid "Start Date"
+msgstr "Начална дата"
+
+#, fuzzy
+msgctxt "field:sale.promotion,unit:"
+msgid "Unit"
+msgstr "Единица"
+
+#, fuzzy
+msgctxt "field:sale.promotion,unit_digits:"
+msgid "Unit Digits"
+msgstr "Десетични единици"
+
+msgctxt "field:sale.promotion,untaxed_amount:"
+msgid "Untaxed Amount"
+msgstr ""
+
+msgctxt "field:sale.promotion-product.category,category:"
+msgid "Category"
+msgstr ""
+
+#, fuzzy
+msgctxt "field:sale.promotion-product.category,promotion:"
+msgid "Promotion"
+msgstr "Promotions"
+
+#, fuzzy
+msgctxt "field:sale.promotion-product.product,product:"
+msgid "Product"
+msgstr "Продукт"
+
+#, fuzzy
+msgctxt "field:sale.promotion-product.product,promotion:"
+msgid "Promotion"
+msgstr "Promotions"
+
+#, fuzzy
+msgctxt "help:sale.promotion,formula:"
+msgid ""
+"Python expression that will be evaluated with:\n"
+"- unit_price: the original unit_price"
+msgstr ""
+"Израз на python който ще се изпълни с:\n"
+"- unit_price: оригиналната единична цена"
+
+msgctxt "model:ir.action,name:act_promotion_form"
+msgid "Promotions"
+msgstr "Promotions"
+
+msgctxt "model:ir.action,name:act_promotion_relate"
+msgid "Sale Promotions"
+msgstr "Sale Promotions"
+
+msgctxt "model:ir.message,text:msg_invalid_formula"
+msgid ""
+"Invalid formula \"%(formula)s\" in promotion \"%(promotion)s\" 'with "
+"exception \"%(exception)s\"."
+msgstr ""
+
+msgctxt "model:ir.rule.group,name:rule_group_promotion_companies"
+msgid "User in companies"
+msgstr ""
+
+msgctxt "model:ir.ui.menu,name:menu_promotion"
+msgid "Promotions"
+msgstr "Promotions"
+
+#, fuzzy
+msgctxt "model:sale.promotion,name:"
+msgid "Sale Promotion"
+msgstr "Sale Promotions"
+
+msgctxt "model:sale.promotion-product.category,name:"
+msgid "Sale Promotion - Product Category"
+msgstr ""
+
+msgctxt "model:sale.promotion-product.product,name:"
+msgid "Sale Promotion - Product"
+msgstr ""
diff --git a/modules/sale_promotion/locale/ca.po b/modules/sale_promotion/locale/ca.po
new file mode 100644
index 0000000000..b989ff5847
--- /dev/null
+++ b/modules/sale_promotion/locale/ca.po
@@ -0,0 +1,131 @@
+#
+msgid ""
+msgstr "Content-Type: text/plain; charset=utf-8\n"
+
+msgctxt "field:sale.line,draft_unit_price:"
+msgid "Draft Unit Price"
+msgstr "Preu unitari esborrany"
+
+msgctxt "field:sale.line,promotion:"
+msgid "Promotion"
+msgstr "Promoció"
+
+msgctxt "field:sale.promotion,amount:"
+msgid "Amount"
+msgstr "Import"
+
+msgctxt "field:sale.promotion,categories:"
+msgid "Categories"
+msgstr "Categories"
+
+msgctxt "field:sale.promotion,company:"
+msgid "Company"
+msgstr "Empresa"
+
+msgctxt "field:sale.promotion,currency:"
+msgid "Currency"
+msgstr "Moneda"
+
+msgctxt "field:sale.promotion,currency_digits:"
+msgid "Currency Digits"
+msgstr "Decimals de la moneda"
+
+msgctxt "field:sale.promotion,end_date:"
+msgid "End Date"
+msgstr "Data final"
+
+msgctxt "field:sale.promotion,formula:"
+msgid "Formula"
+msgstr "Fórmula"
+
+msgctxt "field:sale.promotion,name:"
+msgid "Name"
+msgstr "Nom"
+
+msgctxt "field:sale.promotion,price_list:"
+msgid "Price List"
+msgstr "Tarifa"
+
+msgctxt "field:sale.promotion,products:"
+msgid "Products"
+msgstr "Productes"
+
+msgctxt "field:sale.promotion,quantity:"
+msgid "Quantity"
+msgstr "Quantitat"
+
+msgctxt "field:sale.promotion,start_date:"
+msgid "Start Date"
+msgstr "Data inicial"
+
+msgctxt "field:sale.promotion,unit:"
+msgid "Unit"
+msgstr "Unitat"
+
+msgctxt "field:sale.promotion,unit_digits:"
+msgid "Unit Digits"
+msgstr "Dígits de la unitat"
+
+msgctxt "field:sale.promotion,untaxed_amount:"
+msgid "Untaxed Amount"
+msgstr "Base imponible"
+
+msgctxt "field:sale.promotion-product.category,category:"
+msgid "Category"
+msgstr "Categoria"
+
+msgctxt "field:sale.promotion-product.category,promotion:"
+msgid "Promotion"
+msgstr "Promoció"
+
+msgctxt "field:sale.promotion-product.product,product:"
+msgid "Product"
+msgstr "Producte"
+
+msgctxt "field:sale.promotion-product.product,promotion:"
+msgid "Promotion"
+msgstr "Promoció"
+
+msgctxt "help:sale.promotion,formula:"
+msgid ""
+"Python expression that will be evaluated with:\n"
+"- unit_price: the original unit_price"
+msgstr ""
+"Expressió Python que s'avaluarà amb:\n"
+"- unit_price: El preu unitari original"
+
+msgctxt "model:ir.action,name:act_promotion_form"
+msgid "Promotions"
+msgstr "Promocions"
+
+msgctxt "model:ir.action,name:act_promotion_relate"
+msgid "Sale Promotions"
+msgstr "Promocions de venda"
+
+msgctxt "model:ir.message,text:msg_invalid_formula"
+msgid ""
+"Invalid formula \"%(formula)s\" in promotion \"%(promotion)s\" 'with "
+"exception \"%(exception)s\"."
+msgstr ""
+"La fórmula \"%(formula)s\" de la promoció \"%(promotion)s\" es invàlida amb "
+"l'excepció \"%(exception)s\"."
+
+msgctxt "model:ir.rule.group,name:rule_group_promotion_companies"
+msgid "User in companies"
+msgstr "Usuari a les empreses"
+
+msgctxt "model:ir.ui.menu,name:menu_promotion"
+msgid "Promotions"
+msgstr "Promocions"
+
+msgctxt "model:sale.promotion,name:"
+msgid "Sale Promotion"
+msgstr "Promoció de venda"
+
+msgctxt "model:sale.promotion-product.category,name:"
+msgid "Sale Promotion - Product Category"
+msgstr "Promoció de venda - Categoria de producte"
+
+msgctxt "model:sale.promotion-product.product,name:"
+msgid "Sale Promotion - Product"
+msgstr "Promoció de venda - Producte"
diff --git a/modules/sale_promotion/locale/cs.po b/modules/sale_promotion/locale/cs.po
new file mode 100644
index 0000000000..1b85ba3c37
--- /dev/null
+++ b/modules/sale_promotion/locale/cs.po
@@ -0,0 +1,132 @@
+#
+msgid ""
+msgstr "Content-Type: text/plain; charset=utf-8\n"
+
+msgctxt "field:sale.line,draft_unit_price:"
+msgid "Draft Unit Price"
+msgstr ""
+
+#, fuzzy
+msgctxt "field:sale.line,promotion:"
+msgid "Promotion"
+msgstr "Promotions"
+
+msgctxt "field:sale.promotion,amount:"
+msgid "Amount"
+msgstr ""
+
+msgctxt "field:sale.promotion,categories:"
+msgid "Categories"
+msgstr ""
+
+msgctxt "field:sale.promotion,company:"
+msgid "Company"
+msgstr ""
+
+msgctxt "field:sale.promotion,currency:"
+msgid "Currency"
+msgstr ""
+
+msgctxt "field:sale.promotion,currency_digits:"
+msgid "Currency Digits"
+msgstr ""
+
+msgctxt "field:sale.promotion,end_date:"
+msgid "End Date"
+msgstr ""
+
+msgctxt "field:sale.promotion,formula:"
+msgid "Formula"
+msgstr ""
+
+#, fuzzy
+msgctxt "field:sale.promotion,name:"
+msgid "Name"
+msgstr "Namu"
+
+msgctxt "field:sale.promotion,price_list:"
+msgid "Price List"
+msgstr ""
+
+msgctxt "field:sale.promotion,products:"
+msgid "Products"
+msgstr ""
+
+msgctxt "field:sale.promotion,quantity:"
+msgid "Quantity"
+msgstr ""
+
+msgctxt "field:sale.promotion,start_date:"
+msgid "Start Date"
+msgstr ""
+
+msgctxt "field:sale.promotion,unit:"
+msgid "Unit"
+msgstr ""
+
+msgctxt "field:sale.promotion,unit_digits:"
+msgid "Unit Digits"
+msgstr ""
+
+msgctxt "field:sale.promotion,untaxed_amount:"
+msgid "Untaxed Amount"
+msgstr ""
+
+msgctxt "field:sale.promotion-product.category,category:"
+msgid "Category"
+msgstr ""
+
+#, fuzzy
+msgctxt "field:sale.promotion-product.category,promotion:"
+msgid "Promotion"
+msgstr "Promotions"
+
+msgctxt "field:sale.promotion-product.product,product:"
+msgid "Product"
+msgstr ""
+
+#, fuzzy
+msgctxt "field:sale.promotion-product.product,promotion:"
+msgid "Promotion"
+msgstr "Promotions"
+
+msgctxt "help:sale.promotion,formula:"
+msgid ""
+"Python expression that will be evaluated with:\n"
+"- unit_price: the original unit_price"
+msgstr ""
+
+msgctxt "model:ir.action,name:act_promotion_form"
+msgid "Promotions"
+msgstr "Promotions"
+
+msgctxt "model:ir.action,name:act_promotion_relate"
+msgid "Sale Promotions"
+msgstr "Sale Promotions"
+
+msgctxt "model:ir.message,text:msg_invalid_formula"
+msgid ""
+"Invalid formula \"%(formula)s\" in promotion \"%(promotion)s\" 'with "
+"exception \"%(exception)s\"."
+msgstr ""
+
+msgctxt "model:ir.rule.group,name:rule_group_promotion_companies"
+msgid "User in companies"
+msgstr ""
+
+msgctxt "model:ir.ui.menu,name:menu_promotion"
+msgid "Promotions"
+msgstr "Promotions"
+
+#, fuzzy
+msgctxt "model:sale.promotion,name:"
+msgid "Sale Promotion"
+msgstr "Sale Promotions"
+
+msgctxt "model:sale.promotion-product.category,name:"
+msgid "Sale Promotion - Product Category"
+msgstr ""
+
+msgctxt "model:sale.promotion-product.product,name:"
+msgid "Sale Promotion - Product"
+msgstr ""
diff --git a/modules/sale_promotion/locale/de.po b/modules/sale_promotion/locale/de.po
new file mode 100644
index 0000000000..72f40d4141
--- /dev/null
+++ b/modules/sale_promotion/locale/de.po
@@ -0,0 +1,131 @@
+#
+msgid ""
+msgstr "Content-Type: text/plain; charset=utf-8\n"
+
+msgctxt "field:sale.line,draft_unit_price:"
+msgid "Draft Unit Price"
+msgstr "Einzelpreis Entwurf"
+
+msgctxt "field:sale.line,promotion:"
+msgid "Promotion"
+msgstr "Verkaufsaktion"
+
+msgctxt "field:sale.promotion,amount:"
+msgid "Amount"
+msgstr "Betrag"
+
+msgctxt "field:sale.promotion,categories:"
+msgid "Categories"
+msgstr "Kategorien"
+
+msgctxt "field:sale.promotion,company:"
+msgid "Company"
+msgstr "Unternehmen"
+
+msgctxt "field:sale.promotion,currency:"
+msgid "Currency"
+msgstr "Währung"
+
+msgctxt "field:sale.promotion,currency_digits:"
+msgid "Currency Digits"
+msgstr "Nachkommastellen Währung"
+
+msgctxt "field:sale.promotion,end_date:"
+msgid "End Date"
+msgstr "Enddatum"
+
+msgctxt "field:sale.promotion,formula:"
+msgid "Formula"
+msgstr "Formel"
+
+msgctxt "field:sale.promotion,name:"
+msgid "Name"
+msgstr "Name"
+
+msgctxt "field:sale.promotion,price_list:"
+msgid "Price List"
+msgstr "Preisliste"
+
+msgctxt "field:sale.promotion,products:"
+msgid "Products"
+msgstr "Artikel"
+
+msgctxt "field:sale.promotion,quantity:"
+msgid "Quantity"
+msgstr "Menge"
+
+msgctxt "field:sale.promotion,start_date:"
+msgid "Start Date"
+msgstr "Startdatum"
+
+msgctxt "field:sale.promotion,unit:"
+msgid "Unit"
+msgstr "Einheit"
+
+msgctxt "field:sale.promotion,unit_digits:"
+msgid "Unit Digits"
+msgstr "Nachkommastellen"
+
+msgctxt "field:sale.promotion,untaxed_amount:"
+msgid "Untaxed Amount"
+msgstr "Nettobetrag"
+
+msgctxt "field:sale.promotion-product.category,category:"
+msgid "Category"
+msgstr "Kategorie"
+
+msgctxt "field:sale.promotion-product.category,promotion:"
+msgid "Promotion"
+msgstr "Verkaufsaktion"
+
+msgctxt "field:sale.promotion-product.product,product:"
+msgid "Product"
+msgstr "Artikel"
+
+msgctxt "field:sale.promotion-product.product,promotion:"
+msgid "Promotion"
+msgstr "Verkaufsaktion"
+
+msgctxt "help:sale.promotion,formula:"
+msgid ""
+"Python expression that will be evaluated with:\n"
+"- unit_price: the original unit_price"
+msgstr ""
+"Ein Pythonausdruck, der ausgewertet wird mit:\n"
+"unit_price: originaler unit_price (Preis pro Einheit)"
+
+msgctxt "model:ir.action,name:act_promotion_form"
+msgid "Promotions"
+msgstr "Verkaufsaktionen"
+
+msgctxt "model:ir.action,name:act_promotion_relate"
+msgid "Sale Promotions"
+msgstr "Verkaufsaktionen"
+
+msgctxt "model:ir.message,text:msg_invalid_formula"
+msgid ""
+"Invalid formula \"%(formula)s\" in promotion \"%(promotion)s\" 'with "
+"exception \"%(exception)s\"."
+msgstr ""
+"Ungültige Formel \"%(formula)s\" in Verkaufsaktion \"%(promotion)s\" mit "
+"Fehler \"%(exception)s\"."
+
+msgctxt "model:ir.rule.group,name:rule_group_promotion_companies"
+msgid "User in companies"
+msgstr "Benutzer im Unternehmen"
+
+msgctxt "model:ir.ui.menu,name:menu_promotion"
+msgid "Promotions"
+msgstr "Verkaufsaktionen"
+
+msgctxt "model:sale.promotion,name:"
+msgid "Sale Promotion"
+msgstr "Verkaufsaktion"
+
+msgctxt "model:sale.promotion-product.category,name:"
+msgid "Sale Promotion - Product Category"
+msgstr "Verkaufsaktion - Artikelkategorie"
+
+msgctxt "model:sale.promotion-product.product,name:"
+msgid "Sale Promotion - Product"
+msgstr "Verkaufsaktion - Artikel"
diff --git a/modules/sale_promotion/locale/es.po b/modules/sale_promotion/locale/es.po
new file mode 100644
index 0000000000..0dfd326380
--- /dev/null
+++ b/modules/sale_promotion/locale/es.po
@@ -0,0 +1,131 @@
+#
+msgid ""
+msgstr "Content-Type: text/plain; charset=utf-8\n"
+
+msgctxt "field:sale.line,draft_unit_price:"
+msgid "Draft Unit Price"
+msgstr "Precio unitario borrador"
+
+msgctxt "field:sale.line,promotion:"
+msgid "Promotion"
+msgstr "Promoción"
+
+msgctxt "field:sale.promotion,amount:"
+msgid "Amount"
+msgstr "Importe"
+
+msgctxt "field:sale.promotion,categories:"
+msgid "Categories"
+msgstr "Categorías"
+
+msgctxt "field:sale.promotion,company:"
+msgid "Company"
+msgstr "Empresa"
+
+msgctxt "field:sale.promotion,currency:"
+msgid "Currency"
+msgstr "Moneda"
+
+msgctxt "field:sale.promotion,currency_digits:"
+msgid "Currency Digits"
+msgstr "Decimales de la moneda"
+
+msgctxt "field:sale.promotion,end_date:"
+msgid "End Date"
+msgstr "Fecha final"
+
+msgctxt "field:sale.promotion,formula:"
+msgid "Formula"
+msgstr "Fórmula"
+
+msgctxt "field:sale.promotion,name:"
+msgid "Name"
+msgstr "Nombre"
+
+msgctxt "field:sale.promotion,price_list:"
+msgid "Price List"
+msgstr "Tarifa"
+
+msgctxt "field:sale.promotion,products:"
+msgid "Products"
+msgstr "Productos"
+
+msgctxt "field:sale.promotion,quantity:"
+msgid "Quantity"
+msgstr "Cantidad"
+
+msgctxt "field:sale.promotion,start_date:"
+msgid "Start Date"
+msgstr "Fecha inicial"
+
+msgctxt "field:sale.promotion,unit:"
+msgid "Unit"
+msgstr "Unidad"
+
+msgctxt "field:sale.promotion,unit_digits:"
+msgid "Unit Digits"
+msgstr "Dígitos de la unidad"
+
+msgctxt "field:sale.promotion,untaxed_amount:"
+msgid "Untaxed Amount"
+msgstr "Base imponible"
+
+msgctxt "field:sale.promotion-product.category,category:"
+msgid "Category"
+msgstr "Categoría"
+
+msgctxt "field:sale.promotion-product.category,promotion:"
+msgid "Promotion"
+msgstr "Promoción"
+
+msgctxt "field:sale.promotion-product.product,product:"
+msgid "Product"
+msgstr "Producto"
+
+msgctxt "field:sale.promotion-product.product,promotion:"
+msgid "Promotion"
+msgstr "Promoción"
+
+msgctxt "help:sale.promotion,formula:"
+msgid ""
+"Python expression that will be evaluated with:\n"
+"- unit_price: the original unit_price"
+msgstr ""
+"Expresión Python que será evaluada con:\n"
+"- unit_price: el campo unit_price original"
+
+msgctxt "model:ir.action,name:act_promotion_form"
+msgid "Promotions"
+msgstr "Promociones"
+
+msgctxt "model:ir.action,name:act_promotion_relate"
+msgid "Sale Promotions"
+msgstr "Promociones de venta"
+
+msgctxt "model:ir.message,text:msg_invalid_formula"
+msgid ""
+"Invalid formula \"%(formula)s\" in promotion \"%(promotion)s\" 'with "
+"exception \"%(exception)s\"."
+msgstr ""
+"La fórmula \"%(formula)s\" de la promoción \"%(promotion)s\" no es valida "
+"generando la excepción \"%(exception)s\"."
+
+msgctxt "model:ir.rule.group,name:rule_group_promotion_companies"
+msgid "User in companies"
+msgstr "Usuario en las empresas"
+
+msgctxt "model:ir.ui.menu,name:menu_promotion"
+msgid "Promotions"
+msgstr "Promociones"
+
+msgctxt "model:sale.promotion,name:"
+msgid "Sale Promotion"
+msgstr "Promoción de venta"
+
+msgctxt "model:sale.promotion-product.category,name:"
+msgid "Sale Promotion - Product Category"
+msgstr "Promoción de venta - Categoría de producto"
+
+msgctxt "model:sale.promotion-product.product,name:"
+msgid "Sale Promotion - Product"
+msgstr "Promoción de venta - Producto"
diff --git a/modules/sale_promotion/locale/es_419.po b/modules/sale_promotion/locale/es_419.po
new file mode 100644
index 0000000000..279e58ec42
--- /dev/null
+++ b/modules/sale_promotion/locale/es_419.po
@@ -0,0 +1,132 @@
+#
+msgid ""
+msgstr "Content-Type: text/plain; charset=utf-8\n"
+
+msgctxt "field:sale.line,draft_unit_price:"
+msgid "Draft Unit Price"
+msgstr "Precio unitario borrador"
+
+msgctxt "field:sale.line,promotion:"
+msgid "Promotion"
+msgstr ""
+
+msgctxt "field:sale.promotion,amount:"
+msgid "Amount"
+msgstr ""
+
+msgctxt "field:sale.promotion,categories:"
+msgid "Categories"
+msgstr ""
+
+msgctxt "field:sale.promotion,company:"
+msgid "Company"
+msgstr ""
+
+msgctxt "field:sale.promotion,currency:"
+msgid "Currency"
+msgstr ""
+
+msgctxt "field:sale.promotion,currency_digits:"
+msgid "Currency Digits"
+msgstr ""
+
+msgctxt "field:sale.promotion,end_date:"
+msgid "End Date"
+msgstr ""
+
+msgctxt "field:sale.promotion,formula:"
+msgid "Formula"
+msgstr ""
+
+msgctxt "field:sale.promotion,name:"
+msgid "Name"
+msgstr ""
+
+msgctxt "field:sale.promotion,price_list:"
+msgid "Price List"
+msgstr "Lista de precios"
+
+msgctxt "field:sale.promotion,products:"
+msgid "Products"
+msgstr ""
+
+msgctxt "field:sale.promotion,quantity:"
+msgid "Quantity"
+msgstr ""
+
+msgctxt "field:sale.promotion,start_date:"
+msgid "Start Date"
+msgstr ""
+
+msgctxt "field:sale.promotion,unit:"
+msgid "Unit"
+msgstr ""
+
+msgctxt "field:sale.promotion,unit_digits:"
+msgid "Unit Digits"
+msgstr ""
+
+msgctxt "field:sale.promotion,untaxed_amount:"
+msgid "Untaxed Amount"
+msgstr ""
+
+msgctxt "field:sale.promotion-product.category,category:"
+msgid "Category"
+msgstr ""
+
+msgctxt "field:sale.promotion-product.category,promotion:"
+msgid "Promotion"
+msgstr ""
+
+msgctxt "field:sale.promotion-product.product,product:"
+msgid "Product"
+msgstr ""
+
+msgctxt "field:sale.promotion-product.product,promotion:"
+msgid "Promotion"
+msgstr ""
+
+msgctxt "help:sale.promotion,formula:"
+msgid ""
+"Python expression that will be evaluated with:\n"
+"- unit_price: the original unit_price"
+msgstr ""
+"Expresión Python que se evaluará con:\n"
+"- unit_price: el precio unitario original"
+
+msgctxt "model:ir.action,name:act_promotion_form"
+msgid "Promotions"
+msgstr ""
+
+msgctxt "model:ir.action,name:act_promotion_relate"
+msgid "Sale Promotions"
+msgstr ""
+
+#, fuzzy
+msgctxt "model:ir.message,text:msg_invalid_formula"
+msgid ""
+"Invalid formula \"%(formula)s\" in promotion \"%(promotion)s\" 'with "
+"exception \"%(exception)s\"."
+msgstr ""
+"Fórmula \"%(formula)s\" no válida en la promoción \"%(promotion)s\" con "
+"excepción \"%(exception)s\"."
+
+msgctxt "model:ir.rule.group,name:rule_group_promotion_companies"
+msgid "User in companies"
+msgstr ""
+
+msgctxt "model:ir.ui.menu,name:menu_promotion"
+msgid "Promotions"
+msgstr ""
+
+msgctxt "model:sale.promotion,name:"
+msgid "Sale Promotion"
+msgstr ""
+
+msgctxt "model:sale.promotion-product.category,name:"
+msgid "Sale Promotion - Product Category"
+msgstr ""
+
+msgctxt "model:sale.promotion-product.product,name:"
+msgid "Sale Promotion - Product"
+msgstr ""
diff --git a/modules/sale_promotion/locale/et.po b/modules/sale_promotion/locale/et.po
new file mode 100644
index 0000000000..b14c30da30
--- /dev/null
+++ b/modules/sale_promotion/locale/et.po
@@ -0,0 +1,129 @@
+#
+msgid ""
+msgstr "Content-Type: text/plain; charset=utf-8\n"
+
+msgctxt "field:sale.line,draft_unit_price:"
+msgid "Draft Unit Price"
+msgstr "Ühiku hinna mustand"
+
+msgctxt "field:sale.line,promotion:"
+msgid "Promotion"
+msgstr "Soodustus"
+
+msgctxt "field:sale.promotion,amount:"
+msgid "Amount"
+msgstr ""
+
+msgctxt "field:sale.promotion,categories:"
+msgid "Categories"
+msgstr "Kategooriad"
+
+msgctxt "field:sale.promotion,company:"
+msgid "Company"
+msgstr "Ettevõte"
+
+msgctxt "field:sale.promotion,currency:"
+msgid "Currency"
+msgstr ""
+
+#, fuzzy
+msgctxt "field:sale.promotion,currency_digits:"
+msgid "Currency Digits"
+msgstr "Ühiku numbriväärtus"
+
+msgctxt "field:sale.promotion,end_date:"
+msgid "End Date"
+msgstr "Lõppkuupäev"
+
+msgctxt "field:sale.promotion,formula:"
+msgid "Formula"
+msgstr "Valem"
+
+msgctxt "field:sale.promotion,name:"
+msgid "Name"
+msgstr "Nimi"
+
+msgctxt "field:sale.promotion,price_list:"
+msgid "Price List"
+msgstr "Hinnakiri"
+
+msgctxt "field:sale.promotion,products:"
+msgid "Products"
+msgstr "Tooted"
+
+msgctxt "field:sale.promotion,quantity:"
+msgid "Quantity"
+msgstr "Kogus"
+
+msgctxt "field:sale.promotion,start_date:"
+msgid "Start Date"
+msgstr "Alguskuupäev"
+
+msgctxt "field:sale.promotion,unit:"
+msgid "Unit"
+msgstr "Ühik"
+
+msgctxt "field:sale.promotion,unit_digits:"
+msgid "Unit Digits"
+msgstr "Ühiku numbriväärtus"
+
+msgctxt "field:sale.promotion,untaxed_amount:"
+msgid "Untaxed Amount"
+msgstr ""
+
+msgctxt "field:sale.promotion-product.category,category:"
+msgid "Category"
+msgstr "Kategooria"
+
+msgctxt "field:sale.promotion-product.category,promotion:"
+msgid "Promotion"
+msgstr "Soodustus"
+
+msgctxt "field:sale.promotion-product.product,product:"
+msgid "Product"
+msgstr "Toode"
+
+msgctxt "field:sale.promotion-product.product,promotion:"
+msgid "Promotion"
+msgstr "Soodustus"
+
+msgctxt "help:sale.promotion,formula:"
+msgid ""
+"Python expression that will be evaluated with:\n"
+"- unit_price: the original unit_price"
+msgstr ""
+
+msgctxt "model:ir.action,name:act_promotion_form"
+msgid "Promotions"
+msgstr "Soodustused"
+
+msgctxt "model:ir.action,name:act_promotion_relate"
+msgid "Sale Promotions"
+msgstr "Müügisoodustus"
+
+msgctxt "model:ir.message,text:msg_invalid_formula"
+msgid ""
+"Invalid formula \"%(formula)s\" in promotion \"%(promotion)s\" 'with "
+"exception \"%(exception)s\"."
+msgstr ""
+
+#, fuzzy
+msgctxt "model:ir.rule.group,name:rule_group_promotion_companies"
+msgid "User in companies"
+msgstr "Kasutaja ettevõttes"
+
+msgctxt "model:ir.ui.menu,name:menu_promotion"
+msgid "Promotions"
+msgstr "Soodustused"
+
+msgctxt "model:sale.promotion,name:"
+msgid "Sale Promotion"
+msgstr "Müüg soodustus"
+
+msgctxt "model:sale.promotion-product.category,name:"
+msgid "Sale Promotion - Product Category"
+msgstr "Müügisoodustus - toote kategooria"
+
+msgctxt "model:sale.promotion-product.product,name:"
+msgid "Sale Promotion - Product"
+msgstr "Müügisoodustus - toode"
diff --git a/modules/sale_promotion/locale/fa.po b/modules/sale_promotion/locale/fa.po
new file mode 100644
index 0000000000..d73cce8fc0
--- /dev/null
+++ b/modules/sale_promotion/locale/fa.po
@@ -0,0 +1,130 @@
+#
+msgid ""
+msgstr "Content-Type: text/plain; charset=utf-8\n"
+
+msgctxt "field:sale.line,draft_unit_price:"
+msgid "Draft Unit Price"
+msgstr "پیش نویس واحد قیمت"
+
+msgctxt "field:sale.line,promotion:"
+msgid "Promotion"
+msgstr "تبلیغ و ترویج"
+
+msgctxt "field:sale.promotion,amount:"
+msgid "Amount"
+msgstr ""
+
+msgctxt "field:sale.promotion,categories:"
+msgid "Categories"
+msgstr "دسته بندی ها"
+
+msgctxt "field:sale.promotion,company:"
+msgid "Company"
+msgstr "شرکت"
+
+msgctxt "field:sale.promotion,currency:"
+msgid "Currency"
+msgstr ""
+
+#, fuzzy
+msgctxt "field:sale.promotion,currency_digits:"
+msgid "Currency Digits"
+msgstr "ارقام واحد"
+
+msgctxt "field:sale.promotion,end_date:"
+msgid "End Date"
+msgstr "تاریخ پایان"
+
+msgctxt "field:sale.promotion,formula:"
+msgid "Formula"
+msgstr "فرمول"
+
+msgctxt "field:sale.promotion,name:"
+msgid "Name"
+msgstr "نام"
+
+msgctxt "field:sale.promotion,price_list:"
+msgid "Price List"
+msgstr "لیست قیمت"
+
+msgctxt "field:sale.promotion,products:"
+msgid "Products"
+msgstr "محصولات"
+
+msgctxt "field:sale.promotion,quantity:"
+msgid "Quantity"
+msgstr "مقدار/تعداد"
+
+msgctxt "field:sale.promotion,start_date:"
+msgid "Start Date"
+msgstr "تاریخ شروع"
+
+msgctxt "field:sale.promotion,unit:"
+msgid "Unit"
+msgstr "واحد"
+
+msgctxt "field:sale.promotion,unit_digits:"
+msgid "Unit Digits"
+msgstr "ارقام واحد"
+
+msgctxt "field:sale.promotion,untaxed_amount:"
+msgid "Untaxed Amount"
+msgstr ""
+
+msgctxt "field:sale.promotion-product.category,category:"
+msgid "Category"
+msgstr "دستهبندی"
+
+msgctxt "field:sale.promotion-product.category,promotion:"
+msgid "Promotion"
+msgstr "تبلیغ و ترویج"
+
+msgctxt "field:sale.promotion-product.product,product:"
+msgid "Product"
+msgstr "محصول"
+
+msgctxt "field:sale.promotion-product.product,promotion:"
+msgid "Promotion"
+msgstr "تبلیغ و ترویج"
+
+msgctxt "help:sale.promotion,formula:"
+msgid ""
+"Python expression that will be evaluated with:\n"
+"- unit_price: the original unit_price"
+msgstr ""
+"عبارت پایتون که با آن ارزیابی می شود:\n"
+"- واحد_قیمت: واحد_قیمت اصلی"
+
+msgctxt "model:ir.action,name:act_promotion_form"
+msgid "Promotions"
+msgstr "ترویج ها و تبلیغات"
+
+msgctxt "model:ir.action,name:act_promotion_relate"
+msgid "Sale Promotions"
+msgstr "ترویج ها و تبلیغات فروش"
+
+msgctxt "model:ir.message,text:msg_invalid_formula"
+msgid ""
+"Invalid formula \"%(formula)s\" in promotion \"%(promotion)s\" 'with "
+"exception \"%(exception)s\"."
+msgstr "فرمول: \"%s\" در ترویج وتبلیع : \"%s\" با شرایط :\"%s\" نامعتبر میباشد."
+
+msgctxt "model:ir.rule.group,name:rule_group_promotion_companies"
+msgid "User in companies"
+msgstr ""
+
+msgctxt "model:ir.ui.menu,name:menu_promotion"
+msgid "Promotions"
+msgstr "ترویج ها و تبلیغات"
+
+msgctxt "model:sale.promotion,name:"
+msgid "Sale Promotion"
+msgstr "تبلیغ و ترویج فروش"
+
+msgctxt "model:sale.promotion-product.category,name:"
+msgid "Sale Promotion - Product Category"
+msgstr "دسته بندی محصولات - تبلیغ و ترویج فروش"
+
+msgctxt "model:sale.promotion-product.product,name:"
+msgid "Sale Promotion - Product"
+msgstr "محصولات - تبلیغ و ترویج فروش"
diff --git a/modules/sale_promotion/locale/fi.po b/modules/sale_promotion/locale/fi.po
new file mode 100644
index 0000000000..9e5c4ffd9c
--- /dev/null
+++ b/modules/sale_promotion/locale/fi.po
@@ -0,0 +1,131 @@
+#
+msgid ""
+msgstr "Content-Type: text/plain; charset=utf-8\n"
+
+msgctxt "field:sale.line,draft_unit_price:"
+msgid "Draft Unit Price"
+msgstr ""
+
+#, fuzzy
+msgctxt "field:sale.line,promotion:"
+msgid "Promotion"
+msgstr "Promotions"
+
+msgctxt "field:sale.promotion,amount:"
+msgid "Amount"
+msgstr ""
+
+msgctxt "field:sale.promotion,categories:"
+msgid "Categories"
+msgstr ""
+
+msgctxt "field:sale.promotion,company:"
+msgid "Company"
+msgstr ""
+
+msgctxt "field:sale.promotion,currency:"
+msgid "Currency"
+msgstr ""
+
+msgctxt "field:sale.promotion,currency_digits:"
+msgid "Currency Digits"
+msgstr ""
+
+msgctxt "field:sale.promotion,end_date:"
+msgid "End Date"
+msgstr ""
+
+msgctxt "field:sale.promotion,formula:"
+msgid "Formula"
+msgstr ""
+
+msgctxt "field:sale.promotion,name:"
+msgid "Name"
+msgstr ""
+
+msgctxt "field:sale.promotion,price_list:"
+msgid "Price List"
+msgstr ""
+
+msgctxt "field:sale.promotion,products:"
+msgid "Products"
+msgstr ""
+
+msgctxt "field:sale.promotion,quantity:"
+msgid "Quantity"
+msgstr ""
+
+msgctxt "field:sale.promotion,start_date:"
+msgid "Start Date"
+msgstr ""
+
+msgctxt "field:sale.promotion,unit:"
+msgid "Unit"
+msgstr ""
+
+msgctxt "field:sale.promotion,unit_digits:"
+msgid "Unit Digits"
+msgstr ""
+
+msgctxt "field:sale.promotion,untaxed_amount:"
+msgid "Untaxed Amount"
+msgstr ""
+
+msgctxt "field:sale.promotion-product.category,category:"
+msgid "Category"
+msgstr ""
+
+#, fuzzy
+msgctxt "field:sale.promotion-product.category,promotion:"
+msgid "Promotion"
+msgstr "Promotions"
+
+msgctxt "field:sale.promotion-product.product,product:"
+msgid "Product"
+msgstr ""
+
+#, fuzzy
+msgctxt "field:sale.promotion-product.product,promotion:"
+msgid "Promotion"
+msgstr "Promotions"
+
+msgctxt "help:sale.promotion,formula:"
+msgid ""
+"Python expression that will be evaluated with:\n"
+"- unit_price: the original unit_price"
+msgstr ""
+
+msgctxt "model:ir.action,name:act_promotion_form"
+msgid "Promotions"
+msgstr "Promotions"
+
+msgctxt "model:ir.action,name:act_promotion_relate"
+msgid "Sale Promotions"
+msgstr "Sale Promotions"
+
+msgctxt "model:ir.message,text:msg_invalid_formula"
+msgid ""
+"Invalid formula \"%(formula)s\" in promotion \"%(promotion)s\" 'with "
+"exception \"%(exception)s\"."
+msgstr ""
+
+msgctxt "model:ir.rule.group,name:rule_group_promotion_companies"
+msgid "User in companies"
+msgstr ""
+
+msgctxt "model:ir.ui.menu,name:menu_promotion"
+msgid "Promotions"
+msgstr "Promotions"
+
+#, fuzzy
+msgctxt "model:sale.promotion,name:"
+msgid "Sale Promotion"
+msgstr "Sale Promotions"
+
+msgctxt "model:sale.promotion-product.category,name:"
+msgid "Sale Promotion - Product Category"
+msgstr ""
+
+msgctxt "model:sale.promotion-product.product,name:"
+msgid "Sale Promotion - Product"
+msgstr ""
diff --git a/modules/sale_promotion/locale/fr.po b/modules/sale_promotion/locale/fr.po
new file mode 100644
index 0000000000..1e710cd5a7
--- /dev/null
+++ b/modules/sale_promotion/locale/fr.po
@@ -0,0 +1,131 @@
+#
+msgid ""
+msgstr "Content-Type: text/plain; charset=utf-8\n"
+
+msgctxt "field:sale.line,draft_unit_price:"
+msgid "Draft Unit Price"
+msgstr "Prix unitaire brouillon"
+
+msgctxt "field:sale.line,promotion:"
+msgid "Promotion"
+msgstr "Promotion"
+
+msgctxt "field:sale.promotion,amount:"
+msgid "Amount"
+msgstr "Montant"
+
+msgctxt "field:sale.promotion,categories:"
+msgid "Categories"
+msgstr "Catégories"
+
+msgctxt "field:sale.promotion,company:"
+msgid "Company"
+msgstr "Société"
+
+msgctxt "field:sale.promotion,currency:"
+msgid "Currency"
+msgstr "Devise"
+
+msgctxt "field:sale.promotion,currency_digits:"
+msgid "Currency Digits"
+msgstr "Décimales de la devise"
+
+msgctxt "field:sale.promotion,end_date:"
+msgid "End Date"
+msgstr "Date de fin"
+
+msgctxt "field:sale.promotion,formula:"
+msgid "Formula"
+msgstr "Formule"
+
+msgctxt "field:sale.promotion,name:"
+msgid "Name"
+msgstr "Nom"
+
+msgctxt "field:sale.promotion,price_list:"
+msgid "Price List"
+msgstr "Liste de prix"
+
+msgctxt "field:sale.promotion,products:"
+msgid "Products"
+msgstr "Produits"
+
+msgctxt "field:sale.promotion,quantity:"
+msgid "Quantity"
+msgstr "Quantité"
+
+msgctxt "field:sale.promotion,start_date:"
+msgid "Start Date"
+msgstr "Date de début"
+
+msgctxt "field:sale.promotion,unit:"
+msgid "Unit"
+msgstr "Unité"
+
+msgctxt "field:sale.promotion,unit_digits:"
+msgid "Unit Digits"
+msgstr "Décimales de l'unité"
+
+msgctxt "field:sale.promotion,untaxed_amount:"
+msgid "Untaxed Amount"
+msgstr "Montant hors taxe"
+
+msgctxt "field:sale.promotion-product.category,category:"
+msgid "Category"
+msgstr "Catégorie"
+
+msgctxt "field:sale.promotion-product.category,promotion:"
+msgid "Promotion"
+msgstr "Promotion"
+
+msgctxt "field:sale.promotion-product.product,product:"
+msgid "Product"
+msgstr "Produit"
+
+msgctxt "field:sale.promotion-product.product,promotion:"
+msgid "Promotion"
+msgstr "Promotion"
+
+msgctxt "help:sale.promotion,formula:"
+msgid ""
+"Python expression that will be evaluated with:\n"
+"- unit_price: the original unit_price"
+msgstr ""
+"L'expression Python qui sera évaluée avec :\n"
+"- unit_price : le prix unitaire original"
+
+msgctxt "model:ir.action,name:act_promotion_form"
+msgid "Promotions"
+msgstr "Promotions"
+
+msgctxt "model:ir.action,name:act_promotion_relate"
+msgid "Sale Promotions"
+msgstr "Promotions de vente"
+
+msgctxt "model:ir.message,text:msg_invalid_formula"
+msgid ""
+"Invalid formula \"%(formula)s\" in promotion \"%(promotion)s\" 'with "
+"exception \"%(exception)s\"."
+msgstr ""
+"Formule invalide « %(formula)s » sur la promotion « %(promotion)s » avec "
+"l'exception « %(exception)s »."
+
+msgctxt "model:ir.rule.group,name:rule_group_promotion_companies"
+msgid "User in companies"
+msgstr "Utilisateur dans les sociétés"
+
+msgctxt "model:ir.ui.menu,name:menu_promotion"
+msgid "Promotions"
+msgstr "Promotions"
+
+msgctxt "model:sale.promotion,name:"
+msgid "Sale Promotion"
+msgstr "Promotion de vente"
+
+msgctxt "model:sale.promotion-product.category,name:"
+msgid "Sale Promotion - Product Category"
+msgstr "Promotion de vente - Catégorie de produit"
+
+msgctxt "model:sale.promotion-product.product,name:"
+msgid "Sale Promotion - Product"
+msgstr "Promotion de vente - Produit"
diff --git a/modules/sale_promotion/locale/hu.po b/modules/sale_promotion/locale/hu.po
new file mode 100644
index 0000000000..ef7ea84cac
--- /dev/null
+++ b/modules/sale_promotion/locale/hu.po
@@ -0,0 +1,144 @@
+#
+msgid ""
+msgstr "Content-Type: text/plain; charset=utf-8\n"
+
+msgctxt "field:sale.line,draft_unit_price:"
+msgid "Draft Unit Price"
+msgstr ""
+
+#, fuzzy
+msgctxt "field:sale.line,promotion:"
+msgid "Promotion"
+msgstr "Promotions"
+
+msgctxt "field:sale.promotion,amount:"
+msgid "Amount"
+msgstr ""
+
+msgctxt "field:sale.promotion,categories:"
+msgid "Categories"
+msgstr ""
+
+#, fuzzy
+msgctxt "field:sale.promotion,company:"
+msgid "Company"
+msgstr "Társaság"
+
+msgctxt "field:sale.promotion,currency:"
+msgid "Currency"
+msgstr ""
+
+#, fuzzy
+msgctxt "field:sale.promotion,currency_digits:"
+msgid "Currency Digits"
+msgstr "Tizedes vessző utáni számjegy"
+
+msgctxt "field:sale.promotion,end_date:"
+msgid "End Date"
+msgstr ""
+
+#, fuzzy
+msgctxt "field:sale.promotion,formula:"
+msgid "Formula"
+msgstr "Űrlap"
+
+#, fuzzy
+msgctxt "field:sale.promotion,name:"
+msgid "Name"
+msgstr "Név"
+
+#, fuzzy
+msgctxt "field:sale.promotion,price_list:"
+msgid "Price List"
+msgstr "Árlista"
+
+#, fuzzy
+msgctxt "field:sale.promotion,products:"
+msgid "Products"
+msgstr "Termékek"
+
+#, fuzzy
+msgctxt "field:sale.promotion,quantity:"
+msgid "Quantity"
+msgstr "Mennyiség"
+
+msgctxt "field:sale.promotion,start_date:"
+msgid "Start Date"
+msgstr ""
+
+#, fuzzy
+msgctxt "field:sale.promotion,unit:"
+msgid "Unit"
+msgstr "Egység"
+
+#, fuzzy
+msgctxt "field:sale.promotion,unit_digits:"
+msgid "Unit Digits"
+msgstr "Tizedes vessző utáni számjegy"
+
+msgctxt "field:sale.promotion,untaxed_amount:"
+msgid "Untaxed Amount"
+msgstr ""
+
+msgctxt "field:sale.promotion-product.category,category:"
+msgid "Category"
+msgstr ""
+
+#, fuzzy
+msgctxt "field:sale.promotion-product.category,promotion:"
+msgid "Promotion"
+msgstr "Promotions"
+
+#, fuzzy
+msgctxt "field:sale.promotion-product.product,product:"
+msgid "Product"
+msgstr "Termék"
+
+#, fuzzy
+msgctxt "field:sale.promotion-product.product,promotion:"
+msgid "Promotion"
+msgstr "Promotions"
+
+#, fuzzy
+msgctxt "help:sale.promotion,formula:"
+msgid ""
+"Python expression that will be evaluated with:\n"
+"- unit_price: the original unit_price"
+msgstr ""
+"Python kifejezés, mely :\n"
+" unit_price: originaler unit_price, szerint van kiértékelve (ár/egység)"
+
+msgctxt "model:ir.action,name:act_promotion_form"
+msgid "Promotions"
+msgstr "Promotions"
+
+msgctxt "model:ir.action,name:act_promotion_relate"
+msgid "Sale Promotions"
+msgstr "Sale Promotions"
+
+msgctxt "model:ir.message,text:msg_invalid_formula"
+msgid ""
+"Invalid formula \"%(formula)s\" in promotion \"%(promotion)s\" 'with "
+"exception \"%(exception)s\"."
+msgstr ""
+
+msgctxt "model:ir.rule.group,name:rule_group_promotion_companies"
+msgid "User in companies"
+msgstr ""
+
+msgctxt "model:ir.ui.menu,name:menu_promotion"
+msgid "Promotions"
+msgstr "Promotions"
+
+#, fuzzy
+msgctxt "model:sale.promotion,name:"
+msgid "Sale Promotion"
+msgstr "Sale Promotions"
+
+msgctxt "model:sale.promotion-product.category,name:"
+msgid "Sale Promotion - Product Category"
+msgstr ""
+
+msgctxt "model:sale.promotion-product.product,name:"
+msgid "Sale Promotion - Product"
+msgstr ""
diff --git a/modules/sale_promotion/locale/id.po b/modules/sale_promotion/locale/id.po
new file mode 100644
index 0000000000..b904de6290
--- /dev/null
+++ b/modules/sale_promotion/locale/id.po
@@ -0,0 +1,128 @@
+#
+msgid ""
+msgstr "Content-Type: text/plain; charset=utf-8\n"
+
+msgctxt "field:sale.line,draft_unit_price:"
+msgid "Draft Unit Price"
+msgstr ""
+
+msgctxt "field:sale.line,promotion:"
+msgid "Promotion"
+msgstr ""
+
+msgctxt "field:sale.promotion,amount:"
+msgid "Amount"
+msgstr ""
+
+msgctxt "field:sale.promotion,categories:"
+msgid "Categories"
+msgstr ""
+
+msgctxt "field:sale.promotion,company:"
+msgid "Company"
+msgstr "Perusahaan"
+
+msgctxt "field:sale.promotion,currency:"
+msgid "Currency"
+msgstr ""
+
+msgctxt "field:sale.promotion,currency_digits:"
+msgid "Currency Digits"
+msgstr ""
+
+msgctxt "field:sale.promotion,end_date:"
+msgid "End Date"
+msgstr "Tanggal Akhir"
+
+msgctxt "field:sale.promotion,formula:"
+msgid "Formula"
+msgstr ""
+
+msgctxt "field:sale.promotion,name:"
+msgid "Name"
+msgstr "Nama"
+
+msgctxt "field:sale.promotion,price_list:"
+msgid "Price List"
+msgstr ""
+
+msgctxt "field:sale.promotion,products:"
+msgid "Products"
+msgstr ""
+
+msgctxt "field:sale.promotion,quantity:"
+msgid "Quantity"
+msgstr ""
+
+msgctxt "field:sale.promotion,start_date:"
+msgid "Start Date"
+msgstr "Tanggal Awal"
+
+msgctxt "field:sale.promotion,unit:"
+msgid "Unit"
+msgstr ""
+
+msgctxt "field:sale.promotion,unit_digits:"
+msgid "Unit Digits"
+msgstr ""
+
+msgctxt "field:sale.promotion,untaxed_amount:"
+msgid "Untaxed Amount"
+msgstr ""
+
+msgctxt "field:sale.promotion-product.category,category:"
+msgid "Category"
+msgstr "Kategori"
+
+msgctxt "field:sale.promotion-product.category,promotion:"
+msgid "Promotion"
+msgstr ""
+
+msgctxt "field:sale.promotion-product.product,product:"
+msgid "Product"
+msgstr "Produk"
+
+msgctxt "field:sale.promotion-product.product,promotion:"
+msgid "Promotion"
+msgstr ""
+
+msgctxt "help:sale.promotion,formula:"
+msgid ""
+"Python expression that will be evaluated with:\n"
+"- unit_price: the original unit_price"
+msgstr ""
+
+msgctxt "model:ir.action,name:act_promotion_form"
+msgid "Promotions"
+msgstr ""
+
+msgctxt "model:ir.action,name:act_promotion_relate"
+msgid "Sale Promotions"
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_invalid_formula"
+msgid ""
+"Invalid formula \"%(formula)s\" in promotion \"%(promotion)s\" 'with "
+"exception \"%(exception)s\"."
+msgstr ""
+
+#, fuzzy
+msgctxt "model:ir.rule.group,name:rule_group_promotion_companies"
+msgid "User in companies"
+msgstr "Pengguna di dalam perusahaan"
+
+msgctxt "model:ir.ui.menu,name:menu_promotion"
+msgid "Promotions"
+msgstr ""
+
+msgctxt "model:sale.promotion,name:"
+msgid "Sale Promotion"
+msgstr ""
+
+msgctxt "model:sale.promotion-product.category,name:"
+msgid "Sale Promotion - Product Category"
+msgstr ""
+
+msgctxt "model:sale.promotion-product.product,name:"
+msgid "Sale Promotion - Product"
+msgstr ""
diff --git a/modules/sale_promotion/locale/it.po b/modules/sale_promotion/locale/it.po
new file mode 100644
index 0000000000..c7ad0714e8
--- /dev/null
+++ b/modules/sale_promotion/locale/it.po
@@ -0,0 +1,137 @@
+#
+msgid ""
+msgstr "Content-Type: text/plain; charset=utf-8\n"
+
+msgctxt "field:sale.line,draft_unit_price:"
+msgid "Draft Unit Price"
+msgstr "Bozza prezzo unitario"
+
+msgctxt "field:sale.line,promotion:"
+msgid "Promotion"
+msgstr "Promozione"
+
+msgctxt "field:sale.promotion,amount:"
+msgid "Amount"
+msgstr ""
+
+msgctxt "field:sale.promotion,categories:"
+msgid "Categories"
+msgstr ""
+
+msgctxt "field:sale.promotion,company:"
+msgid "Company"
+msgstr "Azienda"
+
+msgctxt "field:sale.promotion,currency:"
+msgid "Currency"
+msgstr ""
+
+#, fuzzy
+msgctxt "field:sale.promotion,currency_digits:"
+msgid "Currency Digits"
+msgstr "Posizioni Unità"
+
+msgctxt "field:sale.promotion,end_date:"
+msgid "End Date"
+msgstr "Data finale"
+
+msgctxt "field:sale.promotion,formula:"
+msgid "Formula"
+msgstr "Formula"
+
+msgctxt "field:sale.promotion,name:"
+msgid "Name"
+msgstr "Nome"
+
+msgctxt "field:sale.promotion,price_list:"
+msgid "Price List"
+msgstr "Listino"
+
+msgctxt "field:sale.promotion,products:"
+msgid "Products"
+msgstr "Prodotti"
+
+msgctxt "field:sale.promotion,quantity:"
+msgid "Quantity"
+msgstr "Quantità"
+
+msgctxt "field:sale.promotion,start_date:"
+msgid "Start Date"
+msgstr "Data iniziale"
+
+msgctxt "field:sale.promotion,unit:"
+msgid "Unit"
+msgstr "Unità"
+
+msgctxt "field:sale.promotion,unit_digits:"
+msgid "Unit Digits"
+msgstr "Posizioni Unità"
+
+msgctxt "field:sale.promotion,untaxed_amount:"
+msgid "Untaxed Amount"
+msgstr ""
+
+msgctxt "field:sale.promotion-product.category,category:"
+msgid "Category"
+msgstr ""
+
+#, fuzzy
+msgctxt "field:sale.promotion-product.category,promotion:"
+msgid "Promotion"
+msgstr "Promozione"
+
+msgctxt "field:sale.promotion-product.product,product:"
+msgid "Product"
+msgstr "Prodotto"
+
+msgctxt "field:sale.promotion-product.product,promotion:"
+msgid "Promotion"
+msgstr "Promozione"
+
+msgctxt "help:sale.promotion,formula:"
+msgid ""
+"Python expression that will be evaluated with:\n"
+"- unit_price: the original unit_price"
+msgstr ""
+"Espressione python che verrà valorizzata con:\n"
+"- unit_price: l'unit_price originario"
+
+#, fuzzy
+msgctxt "model:ir.action,name:act_promotion_form"
+msgid "Promotions"
+msgstr "Promotions"
+
+#, fuzzy
+msgctxt "model:ir.action,name:act_promotion_relate"
+msgid "Sale Promotions"
+msgstr "Sale Promotions"
+
+#, fuzzy
+msgctxt "model:ir.message,text:msg_invalid_formula"
+msgid ""
+"Invalid formula \"%(formula)s\" in promotion \"%(promotion)s\" 'with "
+"exception \"%(exception)s\"."
+msgstr ""
+"Formula \"%(formula)s\" invalida nella promozione \"%(promotion)s\" con "
+"eccezione \"%(exception)s\"."
+
+msgctxt "model:ir.rule.group,name:rule_group_promotion_companies"
+msgid "User in companies"
+msgstr ""
+
+#, fuzzy
+msgctxt "model:ir.ui.menu,name:menu_promotion"
+msgid "Promotions"
+msgstr "Promotions"
+
+msgctxt "model:sale.promotion,name:"
+msgid "Sale Promotion"
+msgstr "Promozione su vendite"
+
+msgctxt "model:sale.promotion-product.category,name:"
+msgid "Sale Promotion - Product Category"
+msgstr ""
+
+msgctxt "model:sale.promotion-product.product,name:"
+msgid "Sale Promotion - Product"
+msgstr "Promozione su vendita - prodotto"
diff --git a/modules/sale_promotion/locale/lo.po b/modules/sale_promotion/locale/lo.po
new file mode 100644
index 0000000000..a51690b4da
--- /dev/null
+++ b/modules/sale_promotion/locale/lo.po
@@ -0,0 +1,142 @@
+#
+msgid ""
+msgstr "Content-Type: text/plain; charset=utf-8\n"
+
+msgctxt "field:sale.line,draft_unit_price:"
+msgid "Draft Unit Price"
+msgstr ""
+
+#, fuzzy
+msgctxt "field:sale.line,promotion:"
+msgid "Promotion"
+msgstr "Promotions"
+
+msgctxt "field:sale.promotion,amount:"
+msgid "Amount"
+msgstr ""
+
+msgctxt "field:sale.promotion,categories:"
+msgid "Categories"
+msgstr ""
+
+#, fuzzy
+msgctxt "field:sale.promotion,company:"
+msgid "Company"
+msgstr "ຫ້ອງການ/ສຳນັກງານ"
+
+msgctxt "field:sale.promotion,currency:"
+msgid "Currency"
+msgstr ""
+
+#, fuzzy
+msgctxt "field:sale.promotion,currency_digits:"
+msgid "Currency Digits"
+msgstr "ຫົວໜ່ວຍເສດ"
+
+#, fuzzy
+msgctxt "field:sale.promotion,end_date:"
+msgid "End Date"
+msgstr "ວັນທີສິ້ນສຸດ"
+
+msgctxt "field:sale.promotion,formula:"
+msgid "Formula"
+msgstr ""
+
+#, fuzzy
+msgctxt "field:sale.promotion,name:"
+msgid "Name"
+msgstr "ຊື່"
+
+#, fuzzy
+msgctxt "field:sale.promotion,price_list:"
+msgid "Price List"
+msgstr "ລາຍການລາຄາ"
+
+#, fuzzy
+msgctxt "field:sale.promotion,products:"
+msgid "Products"
+msgstr "ຜະລິດຕະພັນ"
+
+#, fuzzy
+msgctxt "field:sale.promotion,quantity:"
+msgid "Quantity"
+msgstr "ຈຳນວນ"
+
+#, fuzzy
+msgctxt "field:sale.promotion,start_date:"
+msgid "Start Date"
+msgstr "ວັນທີເລີ່ມ"
+
+#, fuzzy
+msgctxt "field:sale.promotion,unit:"
+msgid "Unit"
+msgstr "ໜ່ວຍ"
+
+#, fuzzy
+msgctxt "field:sale.promotion,unit_digits:"
+msgid "Unit Digits"
+msgstr "ຫົວໜ່ວຍເສດ"
+
+msgctxt "field:sale.promotion,untaxed_amount:"
+msgid "Untaxed Amount"
+msgstr ""
+
+msgctxt "field:sale.promotion-product.category,category:"
+msgid "Category"
+msgstr ""
+
+#, fuzzy
+msgctxt "field:sale.promotion-product.category,promotion:"
+msgid "Promotion"
+msgstr "Promotions"
+
+#, fuzzy
+msgctxt "field:sale.promotion-product.product,product:"
+msgid "Product"
+msgstr "ຜະລິດຕະພັນ"
+
+#, fuzzy
+msgctxt "field:sale.promotion-product.product,promotion:"
+msgid "Promotion"
+msgstr "Promotions"
+
+msgctxt "help:sale.promotion,formula:"
+msgid ""
+"Python expression that will be evaluated with:\n"
+"- unit_price: the original unit_price"
+msgstr ""
+
+msgctxt "model:ir.action,name:act_promotion_form"
+msgid "Promotions"
+msgstr "Promotions"
+
+msgctxt "model:ir.action,name:act_promotion_relate"
+msgid "Sale Promotions"
+msgstr "Sale Promotions"
+
+msgctxt "model:ir.message,text:msg_invalid_formula"
+msgid ""
+"Invalid formula \"%(formula)s\" in promotion \"%(promotion)s\" 'with "
+"exception \"%(exception)s\"."
+msgstr ""
+
+msgctxt "model:ir.rule.group,name:rule_group_promotion_companies"
+msgid "User in companies"
+msgstr ""
+
+msgctxt "model:ir.ui.menu,name:menu_promotion"
+msgid "Promotions"
+msgstr "Promotions"
+
+#, fuzzy
+msgctxt "model:sale.promotion,name:"
+msgid "Sale Promotion"
+msgstr "Sale Promotions"
+
+msgctxt "model:sale.promotion-product.category,name:"
+msgid "Sale Promotion - Product Category"
+msgstr ""
+
+msgctxt "model:sale.promotion-product.product,name:"
+msgid "Sale Promotion - Product"
+msgstr ""
diff --git a/modules/sale_promotion/locale/lt.po b/modules/sale_promotion/locale/lt.po
new file mode 100644
index 0000000000..9c6a337517
--- /dev/null
+++ b/modules/sale_promotion/locale/lt.po
@@ -0,0 +1,132 @@
+#
+msgid ""
+msgstr "Content-Type: text/plain; charset=utf-8\n"
+
+msgctxt "field:sale.line,draft_unit_price:"
+msgid "Draft Unit Price"
+msgstr ""
+
+#, fuzzy
+msgctxt "field:sale.line,promotion:"
+msgid "Promotion"
+msgstr "Promotions"
+
+msgctxt "field:sale.promotion,amount:"
+msgid "Amount"
+msgstr ""
+
+msgctxt "field:sale.promotion,categories:"
+msgid "Categories"
+msgstr ""
+
+msgctxt "field:sale.promotion,company:"
+msgid "Company"
+msgstr "Organizacija"
+
+msgctxt "field:sale.promotion,currency:"
+msgid "Currency"
+msgstr ""
+
+msgctxt "field:sale.promotion,currency_digits:"
+msgid "Currency Digits"
+msgstr ""
+
+msgctxt "field:sale.promotion,end_date:"
+msgid "End Date"
+msgstr "Pabaigos data"
+
+msgctxt "field:sale.promotion,formula:"
+msgid "Formula"
+msgstr ""
+
+#, fuzzy
+msgctxt "field:sale.promotion,name:"
+msgid "Name"
+msgstr "Namu"
+
+msgctxt "field:sale.promotion,price_list:"
+msgid "Price List"
+msgstr ""
+
+msgctxt "field:sale.promotion,products:"
+msgid "Products"
+msgstr ""
+
+msgctxt "field:sale.promotion,quantity:"
+msgid "Quantity"
+msgstr ""
+
+msgctxt "field:sale.promotion,start_date:"
+msgid "Start Date"
+msgstr "Pradžios data"
+
+msgctxt "field:sale.promotion,unit:"
+msgid "Unit"
+msgstr ""
+
+msgctxt "field:sale.promotion,unit_digits:"
+msgid "Unit Digits"
+msgstr ""
+
+msgctxt "field:sale.promotion,untaxed_amount:"
+msgid "Untaxed Amount"
+msgstr ""
+
+msgctxt "field:sale.promotion-product.category,category:"
+msgid "Category"
+msgstr ""
+
+#, fuzzy
+msgctxt "field:sale.promotion-product.category,promotion:"
+msgid "Promotion"
+msgstr "Promotions"
+
+msgctxt "field:sale.promotion-product.product,product:"
+msgid "Product"
+msgstr ""
+
+#, fuzzy
+msgctxt "field:sale.promotion-product.product,promotion:"
+msgid "Promotion"
+msgstr "Promotions"
+
+msgctxt "help:sale.promotion,formula:"
+msgid ""
+"Python expression that will be evaluated with:\n"
+"- unit_price: the original unit_price"
+msgstr ""
+
+msgctxt "model:ir.action,name:act_promotion_form"
+msgid "Promotions"
+msgstr "Promotions"
+
+msgctxt "model:ir.action,name:act_promotion_relate"
+msgid "Sale Promotions"
+msgstr "Sale Promotions"
+
+msgctxt "model:ir.message,text:msg_invalid_formula"
+msgid ""
+"Invalid formula \"%(formula)s\" in promotion \"%(promotion)s\" 'with "
+"exception \"%(exception)s\"."
+msgstr ""
+
+msgctxt "model:ir.rule.group,name:rule_group_promotion_companies"
+msgid "User in companies"
+msgstr ""
+
+msgctxt "model:ir.ui.menu,name:menu_promotion"
+msgid "Promotions"
+msgstr "Promotions"
+
+#, fuzzy
+msgctxt "model:sale.promotion,name:"
+msgid "Sale Promotion"
+msgstr "Sale Promotions"
+
+msgctxt "model:sale.promotion-product.category,name:"
+msgid "Sale Promotion - Product Category"
+msgstr ""
+
+msgctxt "model:sale.promotion-product.product,name:"
+msgid "Sale Promotion - Product"
+msgstr ""
diff --git a/modules/sale_promotion/locale/nl.po b/modules/sale_promotion/locale/nl.po
new file mode 100644
index 0000000000..ed8a917738
--- /dev/null
+++ b/modules/sale_promotion/locale/nl.po
@@ -0,0 +1,132 @@
+#
+msgid ""
+msgstr "Content-Type: text/plain; charset=utf-8\n"
+
+msgctxt "field:sale.line,draft_unit_price:"
+msgid "Draft Unit Price"
+msgstr "concept eenheids prijs"
+
+msgctxt "field:sale.line,promotion:"
+msgid "Promotion"
+msgstr "Promoties"
+
+msgctxt "field:sale.promotion,amount:"
+msgid "Amount"
+msgstr "Bedrag"
+
+msgctxt "field:sale.promotion,categories:"
+msgid "Categories"
+msgstr "Categorieën"
+
+msgctxt "field:sale.promotion,company:"
+msgid "Company"
+msgstr "Bedrijf"
+
+msgctxt "field:sale.promotion,currency:"
+msgid "Currency"
+msgstr "Valuta"
+
+msgctxt "field:sale.promotion,currency_digits:"
+msgid "Currency Digits"
+msgstr "Valuta decimalen"
+
+msgctxt "field:sale.promotion,end_date:"
+msgid "End Date"
+msgstr "Eind datum"
+
+msgctxt "field:sale.promotion,formula:"
+msgid "Formula"
+msgstr "Formule"
+
+msgctxt "field:sale.promotion,name:"
+msgid "Name"
+msgstr "Naam"
+
+msgctxt "field:sale.promotion,price_list:"
+msgid "Price List"
+msgstr "prijslijst"
+
+msgctxt "field:sale.promotion,products:"
+msgid "Products"
+msgstr "Producten"
+
+msgctxt "field:sale.promotion,quantity:"
+msgid "Quantity"
+msgstr "Hoeveelheid"
+
+msgctxt "field:sale.promotion,start_date:"
+msgid "Start Date"
+msgstr "Start datum"
+
+msgctxt "field:sale.promotion,unit:"
+msgid "Unit"
+msgstr "Eenheid"
+
+msgctxt "field:sale.promotion,unit_digits:"
+msgid "Unit Digits"
+msgstr "Decimalen eenheid"
+
+msgctxt "field:sale.promotion,untaxed_amount:"
+msgid "Untaxed Amount"
+msgstr "Onbelast bedrag"
+
+msgctxt "field:sale.promotion-product.category,category:"
+msgid "Category"
+msgstr "Categorie"
+
+msgctxt "field:sale.promotion-product.category,promotion:"
+msgid "Promotion"
+msgstr "Promotie"
+
+msgctxt "field:sale.promotion-product.product,product:"
+msgid "Product"
+msgstr "Product"
+
+msgctxt "field:sale.promotion-product.product,promotion:"
+msgid "Promotion"
+msgstr "Promotie"
+
+msgctxt "help:sale.promotion,formula:"
+msgid ""
+"Python expression that will be evaluated with:\n"
+"- unit_price: the original unit_price"
+msgstr ""
+"Python-expressie die wordt geëvalueerd met:\n"
+"- unit_price: de oorspronkelijke eenheidsprijs"
+
+msgctxt "model:ir.action,name:act_promotion_form"
+msgid "Promotions"
+msgstr "Promoties"
+
+msgctxt "model:ir.action,name:act_promotion_relate"
+msgid "Sale Promotions"
+msgstr "Verkoopspromoties"
+
+msgctxt "model:ir.message,text:msg_invalid_formula"
+msgid ""
+"Invalid formula \"%(formula)s\" in promotion \"%(promotion)s\" 'with "
+"exception \"%(exception)s\"."
+msgstr ""
+"Ongeldige formule \"%(formula)s\" in promotie \"%(promotion)s\" 'met "
+"uitzondering \"%(exception)s\"."
+
+#, fuzzy
+msgctxt "model:ir.rule.group,name:rule_group_promotion_companies"
+msgid "User in companies"
+msgstr "Gebruiker in het bedrijf"
+
+msgctxt "model:ir.ui.menu,name:menu_promotion"
+msgid "Promotions"
+msgstr "Promoties"
+
+msgctxt "model:sale.promotion,name:"
+msgid "Sale Promotion"
+msgstr "Verkoopspromotie"
+
+msgctxt "model:sale.promotion-product.category,name:"
+msgid "Sale Promotion - Product Category"
+msgstr "Verkooppromotie - Productcategorie"
+
+msgctxt "model:sale.promotion-product.product,name:"
+msgid "Sale Promotion - Product"
+msgstr "Verkooppromotie - Product"
diff --git a/modules/sale_promotion/locale/pl.po b/modules/sale_promotion/locale/pl.po
new file mode 100644
index 0000000000..88ad57793c
--- /dev/null
+++ b/modules/sale_promotion/locale/pl.po
@@ -0,0 +1,132 @@
+#
+msgid ""
+msgstr "Content-Type: text/plain; charset=utf-8\n"
+
+msgctxt "field:sale.line,draft_unit_price:"
+msgid "Draft Unit Price"
+msgstr ""
+
+msgctxt "field:sale.line,promotion:"
+msgid "Promotion"
+msgstr "Promocja"
+
+msgctxt "field:sale.promotion,amount:"
+msgid "Amount"
+msgstr ""
+
+msgctxt "field:sale.promotion,categories:"
+msgid "Categories"
+msgstr ""
+
+msgctxt "field:sale.promotion,company:"
+msgid "Company"
+msgstr "Firma"
+
+msgctxt "field:sale.promotion,currency:"
+msgid "Currency"
+msgstr ""
+
+#, fuzzy
+msgctxt "field:sale.promotion,currency_digits:"
+msgid "Currency Digits"
+msgstr "Cyfry jednostki"
+
+msgctxt "field:sale.promotion,end_date:"
+msgid "End Date"
+msgstr "Data ukończenia"
+
+msgctxt "field:sale.promotion,formula:"
+msgid "Formula"
+msgstr "Formuła"
+
+msgctxt "field:sale.promotion,name:"
+msgid "Name"
+msgstr "Nazwa"
+
+msgctxt "field:sale.promotion,price_list:"
+msgid "Price List"
+msgstr "Cennik"
+
+msgctxt "field:sale.promotion,products:"
+msgid "Products"
+msgstr "Produkty"
+
+msgctxt "field:sale.promotion,quantity:"
+msgid "Quantity"
+msgstr "Ilość"
+
+msgctxt "field:sale.promotion,start_date:"
+msgid "Start Date"
+msgstr "Data rozpoczęcia"
+
+msgctxt "field:sale.promotion,unit:"
+msgid "Unit"
+msgstr "Jednostka"
+
+msgctxt "field:sale.promotion,unit_digits:"
+msgid "Unit Digits"
+msgstr "Cyfry jednostki"
+
+msgctxt "field:sale.promotion,untaxed_amount:"
+msgid "Untaxed Amount"
+msgstr ""
+
+msgctxt "field:sale.promotion-product.category,category:"
+msgid "Category"
+msgstr ""
+
+#, fuzzy
+msgctxt "field:sale.promotion-product.category,promotion:"
+msgid "Promotion"
+msgstr "Promocja"
+
+msgctxt "field:sale.promotion-product.product,product:"
+msgid "Product"
+msgstr "Produkt"
+
+msgctxt "field:sale.promotion-product.product,promotion:"
+msgid "Promotion"
+msgstr "Promocja"
+
+msgctxt "help:sale.promotion,formula:"
+msgid ""
+"Python expression that will be evaluated with:\n"
+"- unit_price: the original unit_price"
+msgstr ""
+
+#, fuzzy
+msgctxt "model:ir.action,name:act_promotion_form"
+msgid "Promotions"
+msgstr "Promotions"
+
+#, fuzzy
+msgctxt "model:ir.action,name:act_promotion_relate"
+msgid "Sale Promotions"
+msgstr "Sale Promotions"
+
+msgctxt "model:ir.message,text:msg_invalid_formula"
+msgid ""
+"Invalid formula \"%(formula)s\" in promotion \"%(promotion)s\" 'with "
+"exception \"%(exception)s\"."
+msgstr ""
+
+msgctxt "model:ir.rule.group,name:rule_group_promotion_companies"
+msgid "User in companies"
+msgstr ""
+
+#, fuzzy
+msgctxt "model:ir.ui.menu,name:menu_promotion"
+msgid "Promotions"
+msgstr "Promotions"
+
+msgctxt "model:sale.promotion,name:"
+msgid "Sale Promotion"
+msgstr "Promocja sprzedaży"
+
+msgctxt "model:sale.promotion-product.category,name:"
+msgid "Sale Promotion - Product Category"
+msgstr ""
+
+msgctxt "model:sale.promotion-product.product,name:"
+msgid "Sale Promotion - Product"
+msgstr "Promocja sprzedaży - Produkt"
diff --git a/modules/sale_promotion/locale/pt.po b/modules/sale_promotion/locale/pt.po
new file mode 100644
index 0000000000..e933439c76
--- /dev/null
+++ b/modules/sale_promotion/locale/pt.po
@@ -0,0 +1,137 @@
+#
+msgid ""
+msgstr "Content-Type: text/plain; charset=utf-8\n"
+
+msgctxt "field:sale.line,draft_unit_price:"
+msgid "Draft Unit Price"
+msgstr "Rascunho de Preço Unitário"
+
+msgctxt "field:sale.line,promotion:"
+msgid "Promotion"
+msgstr "Promoção"
+
+msgctxt "field:sale.promotion,amount:"
+msgid "Amount"
+msgstr ""
+
+msgctxt "field:sale.promotion,categories:"
+msgid "Categories"
+msgstr ""
+
+msgctxt "field:sale.promotion,company:"
+msgid "Company"
+msgstr "Empresa"
+
+msgctxt "field:sale.promotion,currency:"
+msgid "Currency"
+msgstr ""
+
+#, fuzzy
+msgctxt "field:sale.promotion,currency_digits:"
+msgid "Currency Digits"
+msgstr "Dígitos Decimais da Unidade"
+
+msgctxt "field:sale.promotion,end_date:"
+msgid "End Date"
+msgstr "Data Final"
+
+msgctxt "field:sale.promotion,formula:"
+msgid "Formula"
+msgstr "Fórmula"
+
+msgctxt "field:sale.promotion,name:"
+msgid "Name"
+msgstr "Nome"
+
+msgctxt "field:sale.promotion,price_list:"
+msgid "Price List"
+msgstr "Lista de Preços"
+
+msgctxt "field:sale.promotion,products:"
+msgid "Products"
+msgstr "Produtos"
+
+msgctxt "field:sale.promotion,quantity:"
+msgid "Quantity"
+msgstr "Quantidade"
+
+msgctxt "field:sale.promotion,start_date:"
+msgid "Start Date"
+msgstr "Data Inicial"
+
+msgctxt "field:sale.promotion,unit:"
+msgid "Unit"
+msgstr "Unidade"
+
+msgctxt "field:sale.promotion,unit_digits:"
+msgid "Unit Digits"
+msgstr "Dígitos Decimais da Unidade"
+
+msgctxt "field:sale.promotion,untaxed_amount:"
+msgid "Untaxed Amount"
+msgstr ""
+
+msgctxt "field:sale.promotion-product.category,category:"
+msgid "Category"
+msgstr ""
+
+#, fuzzy
+msgctxt "field:sale.promotion-product.category,promotion:"
+msgid "Promotion"
+msgstr "Promoção"
+
+msgctxt "field:sale.promotion-product.product,product:"
+msgid "Product"
+msgstr "Produto"
+
+msgctxt "field:sale.promotion-product.product,promotion:"
+msgid "Promotion"
+msgstr "Promoção"
+
+msgctxt "help:sale.promotion,formula:"
+msgid ""
+"Python expression that will be evaluated with:\n"
+"- unit_price: the original unit_price"
+msgstr ""
+"Expressão Python que será avaliada com:\n"
+"- unit_price: o preço unitário original"
+
+#, fuzzy
+msgctxt "model:ir.action,name:act_promotion_form"
+msgid "Promotions"
+msgstr "Promotions"
+
+#, fuzzy
+msgctxt "model:ir.action,name:act_promotion_relate"
+msgid "Sale Promotions"
+msgstr "Sale Promotions"
+
+#, fuzzy
+msgctxt "model:ir.message,text:msg_invalid_formula"
+msgid ""
+"Invalid formula \"%(formula)s\" in promotion \"%(promotion)s\" 'with "
+"exception \"%(exception)s\"."
+msgstr ""
+"Fórmula inválida \"%(formula)s\" na promoção \"%(promotion)s\" com a exceção"
+" \"%(exception)s\"."
+
+msgctxt "model:ir.rule.group,name:rule_group_promotion_companies"
+msgid "User in companies"
+msgstr ""
+
+#, fuzzy
+msgctxt "model:ir.ui.menu,name:menu_promotion"
+msgid "Promotions"
+msgstr "Promotions"
+
+msgctxt "model:sale.promotion,name:"
+msgid "Sale Promotion"
+msgstr "Promoção de Venda"
+
+msgctxt "model:sale.promotion-product.category,name:"
+msgid "Sale Promotion - Product Category"
+msgstr ""
+
+msgctxt "model:sale.promotion-product.product,name:"
+msgid "Sale Promotion - Product"
+msgstr "Promoção de Venda - Produto"
diff --git a/modules/sale_promotion/locale/ro.po b/modules/sale_promotion/locale/ro.po
new file mode 100644
index 0000000000..b27f172682
--- /dev/null
+++ b/modules/sale_promotion/locale/ro.po
@@ -0,0 +1,127 @@
+#
+msgid ""
+msgstr "Content-Type: text/plain; charset=utf-8\n"
+
+msgctxt "field:sale.line,draft_unit_price:"
+msgid "Draft Unit Price"
+msgstr ""
+
+msgctxt "field:sale.line,promotion:"
+msgid "Promotion"
+msgstr ""
+
+msgctxt "field:sale.promotion,amount:"
+msgid "Amount"
+msgstr ""
+
+msgctxt "field:sale.promotion,categories:"
+msgid "Categories"
+msgstr "Categorii"
+
+msgctxt "field:sale.promotion,company:"
+msgid "Company"
+msgstr "Companie"
+
+msgctxt "field:sale.promotion,currency:"
+msgid "Currency"
+msgstr ""
+
+msgctxt "field:sale.promotion,currency_digits:"
+msgid "Currency Digits"
+msgstr ""
+
+msgctxt "field:sale.promotion,end_date:"
+msgid "End Date"
+msgstr ""
+
+msgctxt "field:sale.promotion,formula:"
+msgid "Formula"
+msgstr ""
+
+msgctxt "field:sale.promotion,name:"
+msgid "Name"
+msgstr ""
+
+msgctxt "field:sale.promotion,price_list:"
+msgid "Price List"
+msgstr ""
+
+msgctxt "field:sale.promotion,products:"
+msgid "Products"
+msgstr ""
+
+msgctxt "field:sale.promotion,quantity:"
+msgid "Quantity"
+msgstr ""
+
+msgctxt "field:sale.promotion,start_date:"
+msgid "Start Date"
+msgstr ""
+
+msgctxt "field:sale.promotion,unit:"
+msgid "Unit"
+msgstr ""
+
+msgctxt "field:sale.promotion,unit_digits:"
+msgid "Unit Digits"
+msgstr ""
+
+msgctxt "field:sale.promotion,untaxed_amount:"
+msgid "Untaxed Amount"
+msgstr ""
+
+msgctxt "field:sale.promotion-product.category,category:"
+msgid "Category"
+msgstr "Categorie"
+
+msgctxt "field:sale.promotion-product.category,promotion:"
+msgid "Promotion"
+msgstr ""
+
+msgctxt "field:sale.promotion-product.product,product:"
+msgid "Product"
+msgstr "Produs"
+
+msgctxt "field:sale.promotion-product.product,promotion:"
+msgid "Promotion"
+msgstr ""
+
+msgctxt "help:sale.promotion,formula:"
+msgid ""
+"Python expression that will be evaluated with:\n"
+"- unit_price: the original unit_price"
+msgstr ""
+
+msgctxt "model:ir.action,name:act_promotion_form"
+msgid "Promotions"
+msgstr ""
+
+msgctxt "model:ir.action,name:act_promotion_relate"
+msgid "Sale Promotions"
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_invalid_formula"
+msgid ""
+"Invalid formula \"%(formula)s\" in promotion \"%(promotion)s\" 'with "
+"exception \"%(exception)s\"."
+msgstr ""
+
+msgctxt "model:ir.rule.group,name:rule_group_promotion_companies"
+msgid "User in companies"
+msgstr ""
+
+msgctxt "model:ir.ui.menu,name:menu_promotion"
+msgid "Promotions"
+msgstr ""
+
+msgctxt "model:sale.promotion,name:"
+msgid "Sale Promotion"
+msgstr ""
+
+msgctxt "model:sale.promotion-product.category,name:"
+msgid "Sale Promotion - Product Category"
+msgstr ""
+
+msgctxt "model:sale.promotion-product.product,name:"
+msgid "Sale Promotion - Product"
+msgstr ""
diff --git a/modules/sale_promotion/locale/ru.po b/modules/sale_promotion/locale/ru.po
new file mode 100644
index 0000000000..5cb0743924
--- /dev/null
+++ b/modules/sale_promotion/locale/ru.po
@@ -0,0 +1,141 @@
+#
+msgid ""
+msgstr "Content-Type: text/plain; charset=utf-8\n"
+
+msgctxt "field:sale.line,draft_unit_price:"
+msgid "Draft Unit Price"
+msgstr ""
+
+#, fuzzy
+msgctxt "field:sale.line,promotion:"
+msgid "Promotion"
+msgstr "Promotions"
+
+msgctxt "field:sale.promotion,amount:"
+msgid "Amount"
+msgstr ""
+
+msgctxt "field:sale.promotion,categories:"
+msgid "Categories"
+msgstr ""
+
+#, fuzzy
+msgctxt "field:sale.promotion,company:"
+msgid "Company"
+msgstr "Учет.орг."
+
+msgctxt "field:sale.promotion,currency:"
+msgid "Currency"
+msgstr ""
+
+#, fuzzy
+msgctxt "field:sale.promotion,currency_digits:"
+msgid "Currency Digits"
+msgstr "Кол-во цифр после запятой"
+
+#, fuzzy
+msgctxt "field:sale.promotion,end_date:"
+msgid "End Date"
+msgstr "Дата окончания"
+
+msgctxt "field:sale.promotion,formula:"
+msgid "Formula"
+msgstr ""
+
+#, fuzzy
+msgctxt "field:sale.promotion,name:"
+msgid "Name"
+msgstr "Правило оплаты"
+
+msgctxt "field:sale.promotion,price_list:"
+msgid "Price List"
+msgstr ""
+
+#, fuzzy
+msgctxt "field:sale.promotion,products:"
+msgid "Products"
+msgstr "Продукция"
+
+#, fuzzy
+msgctxt "field:sale.promotion,quantity:"
+msgid "Quantity"
+msgstr "Кол-во"
+
+#, fuzzy
+msgctxt "field:sale.promotion,start_date:"
+msgid "Start Date"
+msgstr "Дата начала"
+
+#, fuzzy
+msgctxt "field:sale.promotion,unit:"
+msgid "Unit"
+msgstr "Штука"
+
+#, fuzzy
+msgctxt "field:sale.promotion,unit_digits:"
+msgid "Unit Digits"
+msgstr "Кол-во цифр после запятой"
+
+msgctxt "field:sale.promotion,untaxed_amount:"
+msgid "Untaxed Amount"
+msgstr ""
+
+msgctxt "field:sale.promotion-product.category,category:"
+msgid "Category"
+msgstr ""
+
+#, fuzzy
+msgctxt "field:sale.promotion-product.category,promotion:"
+msgid "Promotion"
+msgstr "Promotions"
+
+#, fuzzy
+msgctxt "field:sale.promotion-product.product,product:"
+msgid "Product"
+msgstr "Товарно материальные ценности (ТМЦ)"
+
+#, fuzzy
+msgctxt "field:sale.promotion-product.product,promotion:"
+msgid "Promotion"
+msgstr "Promotions"
+
+msgctxt "help:sale.promotion,formula:"
+msgid ""
+"Python expression that will be evaluated with:\n"
+"- unit_price: the original unit_price"
+msgstr ""
+
+msgctxt "model:ir.action,name:act_promotion_form"
+msgid "Promotions"
+msgstr "Promotions"
+
+msgctxt "model:ir.action,name:act_promotion_relate"
+msgid "Sale Promotions"
+msgstr "Sale Promotions"
+
+msgctxt "model:ir.message,text:msg_invalid_formula"
+msgid ""
+"Invalid formula \"%(formula)s\" in promotion \"%(promotion)s\" 'with "
+"exception \"%(exception)s\"."
+msgstr ""
+
+msgctxt "model:ir.rule.group,name:rule_group_promotion_companies"
+msgid "User in companies"
+msgstr ""
+
+msgctxt "model:ir.ui.menu,name:menu_promotion"
+msgid "Promotions"
+msgstr "Promotions"
+
+#, fuzzy
+msgctxt "model:sale.promotion,name:"
+msgid "Sale Promotion"
+msgstr "Sale Promotions"
+
+msgctxt "model:sale.promotion-product.category,name:"
+msgid "Sale Promotion - Product Category"
+msgstr ""
+
+msgctxt "model:sale.promotion-product.product,name:"
+msgid "Sale Promotion - Product"
+msgstr ""
diff --git a/modules/sale_promotion/locale/sl.po b/modules/sale_promotion/locale/sl.po
new file mode 100644
index 0000000000..9525df28ae
--- /dev/null
+++ b/modules/sale_promotion/locale/sl.po
@@ -0,0 +1,137 @@
+#
+msgid ""
+msgstr "Content-Type: text/plain; charset=utf-8\n"
+
+msgctxt "field:sale.line,draft_unit_price:"
+msgid "Draft Unit Price"
+msgstr "Cena v pripravi"
+
+msgctxt "field:sale.line,promotion:"
+msgid "Promotion"
+msgstr "Spodbuda"
+
+msgctxt "field:sale.promotion,amount:"
+msgid "Amount"
+msgstr ""
+
+msgctxt "field:sale.promotion,categories:"
+msgid "Categories"
+msgstr ""
+
+msgctxt "field:sale.promotion,company:"
+msgid "Company"
+msgstr "Družba"
+
+msgctxt "field:sale.promotion,currency:"
+msgid "Currency"
+msgstr ""
+
+#, fuzzy
+msgctxt "field:sale.promotion,currency_digits:"
+msgid "Currency Digits"
+msgstr "Decimalke"
+
+msgctxt "field:sale.promotion,end_date:"
+msgid "End Date"
+msgstr "Končni datum"
+
+msgctxt "field:sale.promotion,formula:"
+msgid "Formula"
+msgstr "Formula"
+
+msgctxt "field:sale.promotion,name:"
+msgid "Name"
+msgstr "Naziv"
+
+msgctxt "field:sale.promotion,price_list:"
+msgid "Price List"
+msgstr "Cenik"
+
+msgctxt "field:sale.promotion,products:"
+msgid "Products"
+msgstr "Izdelki"
+
+msgctxt "field:sale.promotion,quantity:"
+msgid "Quantity"
+msgstr "Količina"
+
+msgctxt "field:sale.promotion,start_date:"
+msgid "Start Date"
+msgstr "Začetni datum"
+
+msgctxt "field:sale.promotion,unit:"
+msgid "Unit"
+msgstr "enota"
+
+msgctxt "field:sale.promotion,unit_digits:"
+msgid "Unit Digits"
+msgstr "Decimalke"
+
+msgctxt "field:sale.promotion,untaxed_amount:"
+msgid "Untaxed Amount"
+msgstr ""
+
+msgctxt "field:sale.promotion-product.category,category:"
+msgid "Category"
+msgstr ""
+
+#, fuzzy
+msgctxt "field:sale.promotion-product.category,promotion:"
+msgid "Promotion"
+msgstr "Spodbuda"
+
+msgctxt "field:sale.promotion-product.product,product:"
+msgid "Product"
+msgstr "Izdelek"
+
+msgctxt "field:sale.promotion-product.product,promotion:"
+msgid "Promotion"
+msgstr "Spodbuda"
+
+msgctxt "help:sale.promotion,formula:"
+msgid ""
+"Python expression that will be evaluated with:\n"
+"- unit_price: the original unit_price"
+msgstr ""
+"Pythonski izraz, preračunan z:\n"
+"- unit_price: izvorna cena"
+
+#, fuzzy
+msgctxt "model:ir.action,name:act_promotion_form"
+msgid "Promotions"
+msgstr "Promotions"
+
+#, fuzzy
+msgctxt "model:ir.action,name:act_promotion_relate"
+msgid "Sale Promotions"
+msgstr "Sale Promotions"
+
+#, fuzzy
+msgctxt "model:ir.message,text:msg_invalid_formula"
+msgid ""
+"Invalid formula \"%(formula)s\" in promotion \"%(promotion)s\" 'with "
+"exception \"%(exception)s\"."
+msgstr ""
+"Neveljavna formula \"%(formula)s\" v spodbude \"%(promotion)s\" z napako "
+"\"%(exception)s\"."
+
+msgctxt "model:ir.rule.group,name:rule_group_promotion_companies"
+msgid "User in companies"
+msgstr ""
+
+#, fuzzy
+msgctxt "model:ir.ui.menu,name:menu_promotion"
+msgid "Promotions"
+msgstr "Promotions"
+
+msgctxt "model:sale.promotion,name:"
+msgid "Sale Promotion"
+msgstr "Spodbuda prodaje"
+
+msgctxt "model:sale.promotion-product.category,name:"
+msgid "Sale Promotion - Product Category"
+msgstr ""
+
+msgctxt "model:sale.promotion-product.product,name:"
+msgid "Sale Promotion - Product"
+msgstr "Spodbuda prodaje - Izdelek"
diff --git a/modules/sale_promotion/locale/tr.po b/modules/sale_promotion/locale/tr.po
new file mode 100644
index 0000000000..9e5c4ffd9c
--- /dev/null
+++ b/modules/sale_promotion/locale/tr.po
@@ -0,0 +1,131 @@
+#
+msgid ""
+msgstr "Content-Type: text/plain; charset=utf-8\n"
+
+msgctxt "field:sale.line,draft_unit_price:"
+msgid "Draft Unit Price"
+msgstr ""
+
+#, fuzzy
+msgctxt "field:sale.line,promotion:"
+msgid "Promotion"
+msgstr "Promotions"
+
+msgctxt "field:sale.promotion,amount:"
+msgid "Amount"
+msgstr ""
+
+msgctxt "field:sale.promotion,categories:"
+msgid "Categories"
+msgstr ""
+
+msgctxt "field:sale.promotion,company:"
+msgid "Company"
+msgstr ""
+
+msgctxt "field:sale.promotion,currency:"
+msgid "Currency"
+msgstr ""
+
+msgctxt "field:sale.promotion,currency_digits:"
+msgid "Currency Digits"
+msgstr ""
+
+msgctxt "field:sale.promotion,end_date:"
+msgid "End Date"
+msgstr ""
+
+msgctxt "field:sale.promotion,formula:"
+msgid "Formula"
+msgstr ""
+
+msgctxt "field:sale.promotion,name:"
+msgid "Name"
+msgstr ""
+
+msgctxt "field:sale.promotion,price_list:"
+msgid "Price List"
+msgstr ""
+
+msgctxt "field:sale.promotion,products:"
+msgid "Products"
+msgstr ""
+
+msgctxt "field:sale.promotion,quantity:"
+msgid "Quantity"
+msgstr ""
+
+msgctxt "field:sale.promotion,start_date:"
+msgid "Start Date"
+msgstr ""
+
+msgctxt "field:sale.promotion,unit:"
+msgid "Unit"
+msgstr ""
+
+msgctxt "field:sale.promotion,unit_digits:"
+msgid "Unit Digits"
+msgstr ""
+
+msgctxt "field:sale.promotion,untaxed_amount:"
+msgid "Untaxed Amount"
+msgstr ""
+
+msgctxt "field:sale.promotion-product.category,category:"
+msgid "Category"
+msgstr ""
+
+#, fuzzy
+msgctxt "field:sale.promotion-product.category,promotion:"
+msgid "Promotion"
+msgstr "Promotions"
+
+msgctxt "field:sale.promotion-product.product,product:"
+msgid "Product"
+msgstr ""
+
+#, fuzzy
+msgctxt "field:sale.promotion-product.product,promotion:"
+msgid "Promotion"
+msgstr "Promotions"
+
+msgctxt "help:sale.promotion,formula:"
+msgid ""
+"Python expression that will be evaluated with:\n"
+"- unit_price: the original unit_price"
+msgstr ""
+
+msgctxt "model:ir.action,name:act_promotion_form"
+msgid "Promotions"
+msgstr "Promotions"
+
+msgctxt "model:ir.action,name:act_promotion_relate"
+msgid "Sale Promotions"
+msgstr "Sale Promotions"
+
+msgctxt "model:ir.message,text:msg_invalid_formula"
+msgid ""
+"Invalid formula \"%(formula)s\" in promotion \"%(promotion)s\" 'with "
+"exception \"%(exception)s\"."
+msgstr ""
+
+msgctxt "model:ir.rule.group,name:rule_group_promotion_companies"
+msgid "User in companies"
+msgstr ""
+
+msgctxt "model:ir.ui.menu,name:menu_promotion"
+msgid "Promotions"
+msgstr "Promotions"
+
+#, fuzzy
+msgctxt "model:sale.promotion,name:"
+msgid "Sale Promotion"
+msgstr "Sale Promotions"
+
+msgctxt "model:sale.promotion-product.category,name:"
+msgid "Sale Promotion - Product Category"
+msgstr ""
+
+msgctxt "model:sale.promotion-product.product,name:"
+msgid "Sale Promotion - Product"
+msgstr ""
diff --git a/modules/sale_promotion/locale/zh_CN.po b/modules/sale_promotion/locale/zh_CN.po
new file mode 100644
index 0000000000..c6e12d7c12
--- /dev/null
+++ b/modules/sale_promotion/locale/zh_CN.po
@@ -0,0 +1,132 @@
+#
+msgid ""
+msgstr "Content-Type: text/plain; charset=utf-8\n"
+
+msgctxt "field:sale.line,draft_unit_price:"
+msgid "Draft Unit Price"
+msgstr ""
+
+#, fuzzy
+msgctxt "field:sale.line,promotion:"
+msgid "Promotion"
+msgstr "Promotions"
+
+msgctxt "field:sale.promotion,amount:"
+msgid "Amount"
+msgstr ""
+
+msgctxt "field:sale.promotion,categories:"
+msgid "Categories"
+msgstr ""
+
+msgctxt "field:sale.promotion,company:"
+msgid "Company"
+msgstr ""
+
+msgctxt "field:sale.promotion,currency:"
+msgid "Currency"
+msgstr ""
+
+msgctxt "field:sale.promotion,currency_digits:"
+msgid "Currency Digits"
+msgstr ""
+
+msgctxt "field:sale.promotion,end_date:"
+msgid "End Date"
+msgstr ""
+
+msgctxt "field:sale.promotion,formula:"
+msgid "Formula"
+msgstr ""
+
+#, fuzzy
+msgctxt "field:sale.promotion,name:"
+msgid "Name"
+msgstr "纳木"
+
+msgctxt "field:sale.promotion,price_list:"
+msgid "Price List"
+msgstr ""
+
+msgctxt "field:sale.promotion,products:"
+msgid "Products"
+msgstr ""
+
+msgctxt "field:sale.promotion,quantity:"
+msgid "Quantity"
+msgstr ""
+
+msgctxt "field:sale.promotion,start_date:"
+msgid "Start Date"
+msgstr ""
+
+msgctxt "field:sale.promotion,unit:"
+msgid "Unit"
+msgstr ""
+
+msgctxt "field:sale.promotion,unit_digits:"
+msgid "Unit Digits"
+msgstr ""
+
+msgctxt "field:sale.promotion,untaxed_amount:"
+msgid "Untaxed Amount"
+msgstr ""
+
+msgctxt "field:sale.promotion-product.category,category:"
+msgid "Category"
+msgstr ""
+
+#, fuzzy
+msgctxt "field:sale.promotion-product.category,promotion:"
+msgid "Promotion"
+msgstr "Promotions"
+
+msgctxt "field:sale.promotion-product.product,product:"
+msgid "Product"
+msgstr ""
+
+#, fuzzy
+msgctxt "field:sale.promotion-product.product,promotion:"
+msgid "Promotion"
+msgstr "Promotions"
+
+msgctxt "help:sale.promotion,formula:"
+msgid ""
+"Python expression that will be evaluated with:\n"
+"- unit_price: the original unit_price"
+msgstr ""
+
+msgctxt "model:ir.action,name:act_promotion_form"
+msgid "Promotions"
+msgstr "Promotions"
+
+msgctxt "model:ir.action,name:act_promotion_relate"
+msgid "Sale Promotions"
+msgstr "Sale Promotions"
+
+msgctxt "model:ir.message,text:msg_invalid_formula"
+msgid ""
+"Invalid formula \"%(formula)s\" in promotion \"%(promotion)s\" 'with "
+"exception \"%(exception)s\"."
+msgstr ""
+
+msgctxt "model:ir.rule.group,name:rule_group_promotion_companies"
+msgid "User in companies"
+msgstr ""
+
+msgctxt "model:ir.ui.menu,name:menu_promotion"
+msgid "Promotions"
+msgstr "Promotions"
+
+#, fuzzy
+msgctxt "model:sale.promotion,name:"
+msgid "Sale Promotion"
+msgstr "Sale Promotions"
+
+msgctxt "model:sale.promotion-product.category,name:"
+msgid "Sale Promotion - Product Category"
+msgstr ""
+
+msgctxt "model:sale.promotion-product.product,name:"
+msgid "Sale Promotion - Product"
+msgstr ""
diff --git a/modules/sale_promotion/message.xml b/modules/sale_promotion/message.xml
new file mode 100644
index 0000000000..302d0267b0
--- /dev/null
+++ b/modules/sale_promotion/message.xml
@@ -0,0 +1,10 @@
+
+
+
+
+
+ Invalid formula "%(formula)s" in promotion "%(promotion)s" 'with exception "%(exception)s".
+
+
+
diff --git a/modules/sale_promotion/sale.py b/modules/sale_promotion/sale.py
new file mode 100644
index 0000000000..f341f6256a
--- /dev/null
+++ b/modules/sale_promotion/sale.py
@@ -0,0 +1,351 @@
+# This file is part of Tryton. The COPYRIGHT file at the top level of
+# this repository contains the full copyright notices and license terms.
+import datetime
+from decimal import Decimal
+
+from simpleeval import simple_eval
+
+from trytond.i18n import gettext
+from trytond.pool import PoolMeta, Pool
+from trytond.model import (
+ ModelSQL, ModelView, MatchMixin, Workflow, DeactivableMixin, fields)
+from trytond.pyson import Eval, If, Bool
+from trytond.transaction import Transaction
+from trytond.tools import decistmt
+
+from trytond.modules.product import price_digits, round_price
+from .exceptions import FormulaError
+
+
+class Sale(metaclass=PoolMeta):
+ __name__ = 'sale.sale'
+
+ @classmethod
+ @ModelView.button
+ @Workflow.transition('draft')
+ def draft(cls, sales):
+ super(Sale, cls).draft(sales)
+ # Reset to draft unit price
+ for sale in sales:
+ changed = False
+ for line in sale.lines:
+ if line.type != 'line':
+ continue
+ if line.draft_unit_price is not None:
+ line.unit_price = line.draft_unit_price
+ line.draft_unit_price = None
+ changed = True
+ if line.promotion:
+ line.promotion = None
+ changed = True
+ if changed:
+ sale.lines = sale.lines # Trigger changes
+ cls.save(sales)
+
+ @classmethod
+ @ModelView.button
+ @Workflow.transition('quotation')
+ def quote(cls, sales):
+ super(Sale, cls).quote(sales)
+ # Store draft unit price before changing it
+ for sale in sales:
+ for line in sale.lines:
+ if line.type != 'line':
+ continue
+ if line.draft_unit_price is None:
+ line.draft_unit_price = line.unit_price
+ sale.apply_promotion()
+ cls.save(sales)
+
+ def apply_promotion(self):
+ 'Apply promotion'
+ pool = Pool()
+ Promotion = pool.get('sale.promotion')
+
+ promotions = Promotion.get_promotions(self)
+ for promotion in promotions:
+ promotion.apply(self)
+
+
+class Line(metaclass=PoolMeta):
+ __name__ = 'sale.line'
+
+ draft_unit_price = fields.Numeric('Draft Unit Price',
+ digits=price_digits, readonly=True)
+ promotion = fields.Many2One('sale.promotion', 'Promotion',
+ ondelete='RESTRICT',
+ domain=[
+ ('company', '=', Eval('_parent_sale', {}).get('company', -1)),
+ ])
+
+
+class Promotion(
+ DeactivableMixin, ModelSQL, ModelView, MatchMixin):
+ 'Sale Promotion'
+ __name__ = 'sale.promotion'
+
+ name = fields.Char('Name', translate=True, required=True)
+ company = fields.Many2One(
+ 'company.company', "Company", required=True, select=True,
+ states={
+ 'readonly': Eval('id', 0) > 0,
+ })
+ start_date = fields.Date('Start Date',
+ domain=['OR',
+ ('start_date', '<=', If(~Eval('end_date', None),
+ datetime.date.max,
+ Eval('end_date', datetime.date.max))),
+ ('start_date', '=', None),
+ ],
+ depends=['end_date'])
+ end_date = fields.Date('End Date',
+ domain=['OR',
+ ('end_date', '>=', If(~Eval('start_date', None),
+ datetime.date.min,
+ Eval('start_date', datetime.date.min))),
+ ('end_date', '=', None),
+ ],
+ depends=['start_date'])
+ price_list = fields.Many2One('product.price_list', 'Price List',
+ ondelete='CASCADE',
+ domain=[
+ ('company', '=', Eval('company', -1)),
+ ],
+ depends=['company'])
+
+ amount = fields.Numeric(
+ "Amount", digits=(16, Eval('currency_digits', 2)),
+ depends=['currency_digits'])
+ currency = fields.Many2One(
+ 'currency.currency', "Currency",
+ states={
+ 'required': Bool(Eval('amount', 0)),
+ },
+ depends=['amount'])
+ currency_digits = fields.Function(
+ fields.Integer("Currency Digits"), 'on_change_with_currency_digits')
+ untaxed_amount = fields.Boolean(
+ "Untaxed Amount",
+ states={
+ 'invisible': ~Eval('amount'),
+ },
+ depends=['amount'])
+
+ quantity = fields.Float('Quantity', digits=(16, Eval('unit_digits', 2)),
+ depends=['unit_digits'])
+ unit = fields.Many2One('product.uom', 'Unit',
+ states={
+ 'required': Bool(Eval('quantity', 0)),
+ },
+ depends=['quantity'])
+ unit_digits = fields.Function(fields.Integer('Unit Digits'),
+ 'on_change_with_unit_digits')
+ products = fields.Many2Many(
+ 'sale.promotion-product.product', 'promotion', 'product', "Products",
+ context={
+ 'company': Eval('company', -1),
+ },
+ depends=['company'])
+ categories = fields.Many2Many(
+ 'sale.promotion-product.category', 'promotion', 'category',
+ "Categories",
+ context={
+ 'company': Eval('company', -1),
+ },
+ depends=['company'])
+ formula = fields.Char('Formula', required=True,
+ help=('Python expression that will be evaluated with:\n'
+ '- unit_price: the original unit_price'))
+
+ @staticmethod
+ def default_company():
+ return Transaction().context.get('company')
+
+ @classmethod
+ def default_untaxed_amount(cls):
+ return False
+
+ @fields.depends('unit')
+ def on_change_with_unit_digits(self, name=None):
+ if self.unit:
+ return self.unit.digits
+ return 2
+
+ @fields.depends('currency')
+ def on_change_with_currency_digits(self, name=None):
+ if self.currency:
+ return self.currency.digits
+
+ @classmethod
+ def validate(cls, promotions):
+ super().validate(promotions)
+ for promotion in promotions:
+ promotion.check_formula()
+
+ def check_formula(self):
+ context = self.get_context_formula(None)
+ try:
+ if not isinstance(self.get_unit_price(**context), Decimal):
+ raise ValueError('Not a Decimal')
+ except Exception as exception:
+ raise FormulaError(
+ gettext('sale_promotion.msg_invalid_formula',
+ formula=self.formula,
+ promotion=self.rec_name,
+ exception=exception)) from exception
+
+ @classmethod
+ def _promotions_domain(cls, sale):
+ pool = Pool()
+ Date = pool.get('ir.date')
+ sale_date = sale.sale_date or Date.today()
+ return [
+ ['OR',
+ ('start_date', '<=', sale_date),
+ ('start_date', '=', None),
+ ],
+ ['OR',
+ ('end_date', '=', None),
+ ('end_date', '>=', sale_date),
+ ],
+ ['OR',
+ ('price_list', '=', None),
+ ('price_list', '=',
+ sale.price_list.id if sale.price_list else None),
+ ],
+ ('company', '=', sale.company.id),
+ ]
+
+ @classmethod
+ def get_promotions(cls, sale, pattern=None):
+ 'Yield promotions that apply to sale'
+ promotions = cls.search(cls._promotions_domain(sale))
+ if pattern is None:
+ pattern = {}
+ for promotion in promotions:
+ ppattern = pattern.copy()
+ ppattern.update(promotion.get_pattern(sale))
+ if promotion.match(ppattern):
+ yield promotion
+
+ def get_pattern(self, sale):
+ pool = Pool()
+ Currency = pool.get('currency.currency')
+ Uom = pool.get('product.uom')
+ Sale = pool.get('sale.sale')
+ pattern = {}
+ if self.currency:
+ amount = self.get_sale_amount(Sale(sale.id))
+ pattern['amount'] = Currency.compute(
+ sale.currency, amount, self.currency)
+ if self.unit:
+ quantity = 0
+ for line in sale.lines:
+ if self.is_valid_sale_line(line):
+ quantity += Uom.compute_qty(line.unit, line.quantity,
+ self.unit)
+ pattern['quantity'] = quantity
+ return pattern
+
+ def match(self, pattern):
+ def sign(amount):
+ return Decimal(1).copy_sign(amount)
+ if 'quantity' in pattern:
+ pattern = pattern.copy()
+ if (self.quantity or 0) > pattern.pop('quantity'):
+ return False
+ if 'amount' in pattern:
+ pattern = pattern.copy()
+ amount = pattern.pop('amount')
+ if (sign(self.amount or 0) * sign(amount) >= 0
+ and abs(self.amount or 0) > abs(amount)):
+ return False
+ return super().match(pattern)
+
+ def get_sale_amount(self, sale):
+ if self.untaxed_amount:
+ return sale.untaxed_amount
+ else:
+ return sale.total_amount
+
+ def is_valid_sale_line(self, line):
+
+ def parents(categories):
+ for category in categories:
+ while category:
+ yield category
+ category = category.parent
+
+ if line.quantity <= 0 or line.unit_price <= 0:
+ return False
+ elif self.unit and line.unit.category != self.unit.category:
+ return False
+ elif self.products and line.product not in self.products:
+ return False
+ elif (self.categories
+ and not set(parents(line.product.categories_all)).intersection(
+ self.categories)):
+ return False
+ else:
+ return True
+
+ def apply(self, sale):
+ applied = False
+ for line in sale.lines:
+ if line.type != 'line':
+ continue
+ if not self.is_valid_sale_line(line):
+ continue
+ context = self.get_context_formula(line)
+ new_price = self.get_unit_price(**context)
+ if new_price < 0:
+ new_price = Decimal(0)
+ if line.unit_price >= new_price:
+ line.unit_price = round_price(new_price)
+ line.promotion = self
+ applied = True
+ if applied:
+ sale.lines = sale.lines # Trigger the change
+
+ def get_context_formula(self, sale_line):
+ pool = Pool()
+ Product = pool.get('product.product')
+ if sale_line:
+ with Transaction().set_context(
+ sale_line._get_context_sale_price()):
+ prices = Product.get_sale_price([sale_line.product])
+ unit_price = prices[sale_line.product.id]
+ else:
+ unit_price = Decimal(0)
+ return {
+ 'names': {
+ 'unit_price': unit_price,
+ },
+ }
+
+ def get_unit_price(self, **context):
+ 'Return unit price (as Decimal)'
+ context.setdefault('functions', {})['Decimal'] = Decimal
+ return max(simple_eval(decistmt(self.formula), **context), Decimal(0))
+
+
+class Promotion_Product(ModelSQL):
+ 'Sale Promotion - Product'
+ __name__ = 'sale.promotion-product.product'
+
+ promotion = fields.Many2One('sale.promotion', 'Promotion',
+ required=True, ondelete='CASCADE', select=True)
+ product = fields.Many2One('product.product', 'Product',
+ required=True, ondelete='CASCADE')
+
+
+class Promotion_ProductCategory(ModelSQL):
+ "Sale Promotion - Product Category"
+ __name__ = 'sale.promotion-product.category'
+
+ promotion = fields.Many2One(
+ 'sale.promotion', "Promotion",
+ required=True, ondelete='CASCADE', select=True)
+ category = fields.Many2One(
+ 'product.category', "Category",
+ required=True, ondelete='CASCADE')
diff --git a/modules/sale_promotion/sale.xml b/modules/sale_promotion/sale.xml
new file mode 100644
index 0000000000..4723907788
--- /dev/null
+++ b/modules/sale_promotion/sale.xml
@@ -0,0 +1,84 @@
+
+
+
+
+
+ sale.promotion
+ form
+ promotion_form
+
+
+ sale.promotion
+ tree
+ promotion_list
+
+
+
+ Promotions
+ sale.promotion
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Sale Promotions
+ sale.promotion
+
+
+
+
+ form_relate
+ product.price_list,-1
+
+
+
+
+ User in companies
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/modules/sale_promotion/setup.py b/modules/sale_promotion/setup.py
new file mode 100755
index 0000000000..914f9d039a
--- /dev/null
+++ b/modules/sale_promotion/setup.py
@@ -0,0 +1,149 @@
+#!/usr/bin/env python3
+# This file is part of Tryton. The COPYRIGHT file at the top level of
+# this repository contains the full copyright notices and license terms.
+
+import io
+import os
+import re
+from configparser import ConfigParser
+from setuptools import setup, find_packages
+
+
+def read(fname):
+ return io.open(
+ os.path.join(os.path.dirname(__file__), fname),
+ 'r', encoding='utf-8').read()
+
+
+def get_require_version(name):
+ if minor_version % 2:
+ require = '%s >= %s.%s.dev0, < %s.%s'
+ else:
+ require = '%s >= %s.%s, < %s.%s'
+ require %= (name, major_version, minor_version,
+ major_version, minor_version + 1)
+ return require
+
+
+config = ConfigParser()
+config.read_file(open(os.path.join(os.path.dirname(__file__), 'tryton.cfg')))
+info = dict(config.items('tryton'))
+for key in ('depends', 'extras_depend', 'xml'):
+ if key in info:
+ info[key] = info[key].strip().splitlines()
+version = info.get('version', '0.0.1')
+major_version, minor_version, _ = version.split('.', 2)
+major_version = int(major_version)
+minor_version = int(minor_version)
+name = 'trytond_sale_promotion'
+
+download_url = 'http://downloads.tryton.org/%s.%s/' % (
+ major_version, minor_version)
+if minor_version % 2:
+ version = '%s.%s.dev0' % (major_version, minor_version)
+ download_url = (
+ 'hg+http://hg.tryton.org/modules/%s#egg=%s-%s' % (
+ name[8:], name, version))
+local_version = []
+if os.environ.get('CI_JOB_ID'):
+ local_version.append(os.environ['CI_JOB_ID'])
+else:
+ for build in ['CI_BUILD_NUMBER', 'CI_JOB_NUMBER']:
+ if os.environ.get(build):
+ local_version.append(os.environ[build])
+ else:
+ local_version = []
+ break
+if local_version:
+ version += '+' + '.'.join(local_version)
+
+requires = ['simpleeval']
+for dep in info.get('depends', []):
+ if not re.match(r'(ir|res)(\W|$)', dep):
+ requires.append(get_require_version('trytond_%s' % dep))
+requires.append(get_require_version('trytond'))
+
+tests_require = [get_require_version('proteus')]
+dependency_links = []
+if minor_version % 2:
+ dependency_links.append(
+ 'https://trydevpi.tryton.org/?local_version='
+ + '.'.join(local_version))
+
+setup(name=name,
+ version=version,
+ description='Tryton module for sale promotion',
+ long_description=read('README.rst'),
+ author='Tryton',
+ author_email='bugs@tryton.org',
+ url='http://www.tryton.org/',
+ download_url=download_url,
+ project_urls={
+ "Bug Tracker": 'https://bugs.tryton.org/',
+ "Documentation": 'https://docs.tryton.org/',
+ "Forum": 'https://www.tryton.org/forum',
+ "Source Code": 'https://hg.tryton.org/modules/sale_promotion',
+ },
+ keywords='tryton sale promotion',
+ package_dir={'trytond.modules.sale_promotion': '.'},
+ packages=(
+ ['trytond.modules.sale_promotion']
+ + ['trytond.modules.sale_promotion.%s' % p for p in find_packages()]
+ ),
+ package_data={
+ 'trytond.modules.sale_promotion': (info.get('xml', [])
+ + ['tryton.cfg', 'view/*.xml', 'locale/*.po', 'tests/*.rst']),
+ },
+ classifiers=[
+ 'Development Status :: 5 - Production/Stable',
+ 'Environment :: Plugins',
+ 'Framework :: Tryton',
+ 'Intended Audience :: Developers',
+ 'Intended Audience :: Financial and Insurance Industry',
+ 'Intended Audience :: Legal Industry',
+ 'License :: OSI Approved :: '
+ 'GNU General Public License v3 or later (GPLv3+)',
+ 'Natural Language :: Bulgarian',
+ 'Natural Language :: Catalan',
+ 'Natural Language :: Chinese (Simplified)',
+ 'Natural Language :: Czech',
+ 'Natural Language :: Dutch',
+ 'Natural Language :: English',
+ 'Natural Language :: Finnish',
+ 'Natural Language :: French',
+ 'Natural Language :: German',
+ 'Natural Language :: Hungarian',
+ 'Natural Language :: Indonesian',
+ 'Natural Language :: Italian',
+ 'Natural Language :: Persian',
+ 'Natural Language :: Polish',
+ 'Natural Language :: Portuguese (Brazilian)',
+ 'Natural Language :: Romanian',
+ 'Natural Language :: Russian',
+ 'Natural Language :: Slovenian',
+ 'Natural Language :: Spanish',
+ 'Natural Language :: Turkish',
+ 'Operating System :: OS Independent',
+ 'Programming Language :: Python :: 3',
+ 'Programming Language :: Python :: 3.6',
+ 'Programming Language :: Python :: 3.7',
+ 'Programming Language :: Python :: 3.8',
+ 'Programming Language :: Python :: 3.9',
+ 'Programming Language :: Python :: Implementation :: CPython',
+ 'Programming Language :: Python :: Implementation :: PyPy',
+ 'Topic :: Office/Business',
+ 'Topic :: Office/Business :: Financial :: Accounting',
+ ],
+ license='GPL-3',
+ python_requires='>=3.6',
+ install_requires=requires,
+ dependency_links=dependency_links,
+ zip_safe=False,
+ entry_points="""
+ [trytond.modules]
+ sale_promotion = trytond.modules.sale_promotion
+ """,
+ test_suite='tests',
+ test_loader='trytond.test_loader:Loader',
+ tests_require=tests_require,
+ )
diff --git a/modules/sale_promotion/tests/__init__.py b/modules/sale_promotion/tests/__init__.py
new file mode 100644
index 0000000000..a55c6a6df5
--- /dev/null
+++ b/modules/sale_promotion/tests/__init__.py
@@ -0,0 +1,9 @@
+# This file is part of Tryton. The COPYRIGHT file at the top level of
+# this repository contains the full copyright notices and license terms.
+
+try:
+ from trytond.modules.sale_promotion.tests.test_sale_promotion import suite
+except ImportError:
+ from .test_sale_promotion import suite
+
+__all__ = ['suite']
diff --git a/modules/sale_promotion/tests/scenario_sale_promotion.rst b/modules/sale_promotion/tests/scenario_sale_promotion.rst
new file mode 100644
index 0000000000..1c522666cb
--- /dev/null
+++ b/modules/sale_promotion/tests/scenario_sale_promotion.rst
@@ -0,0 +1,152 @@
+=======================
+Sale Promotion Scenario
+=======================
+
+Imports::
+
+ >>> import datetime
+ >>> from decimal import Decimal
+ >>> from proteus import Model, Wizard
+ >>> from trytond.tests.tools import activate_modules
+ >>> from trytond.modules.company.tests.tools import create_company, \
+ ... get_company
+ >>> from trytond.modules.account.tests.tools import create_chart, \
+ ... get_accounts
+ >>> from trytond.modules.account_invoice.tests.tools import \
+ ... create_payment_term
+
+Activate modules::
+
+ >>> config = activate_modules('sale_promotion')
+
+Create company::
+
+ >>> _ = create_company()
+ >>> company = get_company()
+
+Create chart of accounts::
+
+ >>> _ = create_chart(company)
+ >>> accounts = get_accounts(company)
+ >>> revenue = accounts['revenue']
+
+Create customer::
+
+ >>> Party = Model.get('party.party')
+ >>> customer = Party(name='Customer')
+ >>> customer.save()
+
+Create account category::
+
+ >>> ProductCategory = Model.get('product.category')
+ >>> account_category = ProductCategory(name="Account Category")
+ >>> account_category.accounting = True
+ >>> account_category.account_revenue = revenue
+ >>> account_category.save()
+
+Create products::
+
+ >>> ProductUom = Model.get('product.uom')
+ >>> ProductTemplate = Model.get('product.template')
+ >>> Product = Model.get('product.product')
+ >>> Category = Model.get('product.category')
+
+ >>> category = Category(name="Root")
+ >>> category1 = category.childs.new(name="Child 1")
+ >>> category1b = category1.childs.new(name="Child 1b")
+ >>> category2 = category.childs.new(name="Child 2")
+ >>> category.save()
+ >>> category1, category2 = category.childs
+ >>> category1b, = category1.childs
+
+ >>> unit, = ProductUom.find([('name', '=', 'Unit')])
+ >>> template = ProductTemplate()
+ >>> template.name = 'Product'
+ >>> template.default_uom = unit
+ >>> template.type = 'goods'
+ >>> template.salable = True
+ >>> template.lead_time = datetime.timedelta(0)
+ >>> template.list_price = Decimal('20')
+ >>> template.account_category = account_category
+ >>> template.categories.append(Category(category1b.id))
+ >>> template.save()
+ >>> product1 = Product()
+ >>> product1.template = template
+ >>> product1.save()
+ >>> product2 = Product()
+ >>> product2.template = template
+ >>> product2.save()
+ >>> product3 = Product()
+ >>> product3.template = template
+ >>> product3.save()
+
+ >>> template4, = template.duplicate(default={'categories': [category2.id]})
+ >>> product4 = Product(template4.products[0].id)
+
+Create payment term::
+
+ >>> payment_term = create_payment_term()
+ >>> payment_term.save()
+
+Create Promotion::
+
+ >>> Promotion = Model.get('sale.promotion')
+ >>> promotion = Promotion(name='10% on 10 products 1 or 2')
+ >>> promotion.quantity = 10
+ >>> promotion.unit = unit
+ >>> promotion.products.extend([product1, product2, product4])
+ >>> promotion.categories.append(Category(category1.id))
+ >>> promotion.formula = '0.9 * unit_price'
+ >>> promotion.save()
+
+Sale enough products for promotion::
+
+ >>> Sale = Model.get('sale.sale')
+ >>> sale = Sale()
+ >>> sale.party = customer
+ >>> sale.payment_term = payment_term
+ >>> sale_line = sale.lines.new()
+ >>> sale_line.product = product1
+ >>> sale_line.quantity = 5
+ >>> sale_line = sale.lines.new()
+ >>> sale_line.product = product2
+ >>> sale_line.quantity = 10
+ >>> sale_line = sale.lines.new()
+ >>> sale_line.product = product3
+ >>> sale_line.quantity = 5
+ >>> sale_line = sale.lines.new()
+ >>> sale_line.product = product4
+ >>> sale_line.quantity = 5
+ >>> sale.save()
+ >>> sale.untaxed_amount
+ Decimal('500.00')
+ >>> sale.click('quote')
+ >>> sale.untaxed_amount
+ Decimal('470.00')
+
+Go back to draft reset the original price::
+
+ >>> sale.click('draft')
+ >>> sale.untaxed_amount
+ Decimal('500.00')
+
+Sale not enough products for promotion::
+
+ >>> sale = Sale()
+ >>> sale.party = customer
+ >>> sale.payment_term = payment_term
+ >>> sale_line = sale.lines.new()
+ >>> sale_line.product = product1
+ >>> sale_line.quantity = 5
+ >>> sale_line = sale.lines.new()
+ >>> sale_line.product = product2
+ >>> sale_line.quantity = 3
+ >>> sale_line = sale.lines.new()
+ >>> sale_line.product = product3
+ >>> sale_line.quantity = 10
+ >>> sale.save()
+ >>> sale.untaxed_amount
+ Decimal('360.00')
+ >>> sale.click('quote')
+ >>> sale.untaxed_amount
+ Decimal('360.00')
diff --git a/modules/sale_promotion/tests/scenario_sale_promotion_amount.rst b/modules/sale_promotion/tests/scenario_sale_promotion_amount.rst
new file mode 100644
index 0000000000..13a8b4c0e6
--- /dev/null
+++ b/modules/sale_promotion/tests/scenario_sale_promotion_amount.rst
@@ -0,0 +1,92 @@
+==============================
+Sale Promotion Amount Scenario
+==============================
+
+Imports::
+
+ >>> from decimal import Decimal
+ >>> from proteus import Model
+ >>> from trytond.tests.tools import activate_modules
+ >>> from trytond.modules.company.tests.tools import (
+ ... create_company, get_company)
+
+Activate modules::
+
+ >>> config = activate_modules('sale_promotion')
+
+Create company::
+
+ >>> _ = create_company()
+ >>> company = get_company()
+
+Create customer::
+
+ >>> Party = Model.get('party.party')
+ >>> customer = Party(name='Customer')
+ >>> customer.save()
+
+Create products::
+
+ >>> ProductUom = Model.get('product.uom')
+ >>> ProductTemplate = Model.get('product.template')
+ >>> Product = Model.get('product.product')
+
+ >>> unit, = ProductUom.find([('name', '=', 'Unit')])
+ >>> template = ProductTemplate()
+ >>> template.name = 'Product'
+ >>> template.default_uom = unit
+ >>> template.type = 'goods'
+ >>> template.salable = True
+ >>> template.list_price = Decimal('20')
+ >>> template.save()
+ >>> product1 = Product()
+ >>> product1.template = template
+ >>> product1.save()
+ >>> product2 = Product()
+ >>> product2.template = template
+ >>> product2.save()
+
+Create Promotion::
+
+ >>> Promotion = Model.get('sale.promotion')
+ >>> promotion = Promotion(name='product 2 free')
+ >>> promotion.amount = Decimal('100')
+ >>> promotion.currency = company.currency
+ >>> promotion.products.extend([product2])
+ >>> promotion.formula = '0.0'
+ >>> promotion.save()
+
+Sale enough for promotion::
+
+ >>> Sale = Model.get('sale.sale')
+ >>> sale = Sale()
+ >>> sale.party = customer
+ >>> sale_line = sale.lines.new()
+ >>> sale_line.product = product1
+ >>> sale_line.quantity = 4
+ >>> sale_line = sale.lines.new()
+ >>> sale_line.product = product2
+ >>> sale_line.quantity = 2
+ >>> sale.save()
+ >>> sale.total_amount
+ Decimal('120.00')
+ >>> sale.click('quote')
+ >>> sale.untaxed_amount
+ Decimal('80.00')
+
+Sale not enough for promotion::
+
+ >>> sale = Sale()
+ >>> sale.party = customer
+ >>> sale_line = sale.lines.new()
+ >>> sale_line.product = product1
+ >>> sale_line.quantity = 2
+ >>> sale_line = sale.lines.new()
+ >>> sale_line.product = product2
+ >>> sale_line.quantity = 2
+ >>> sale.save()
+ >>> sale.total_amount
+ Decimal('80.00')
+ >>> sale.click('quote')
+ >>> sale.untaxed_amount
+ Decimal('80.00')
diff --git a/modules/sale_promotion/tests/test_sale_promotion.py b/modules/sale_promotion/tests/test_sale_promotion.py
new file mode 100644
index 0000000000..f01f7f04d2
--- /dev/null
+++ b/modules/sale_promotion/tests/test_sale_promotion.py
@@ -0,0 +1,30 @@
+# This file is part of Tryton. The COPYRIGHT file at the top level of
+# this repository contains the full copyright notices and license terms.
+import unittest
+import doctest
+import trytond.tests.test_tryton
+from trytond.tests.test_tryton import ModuleTestCase
+from trytond.tests.test_tryton import doctest_teardown
+from trytond.tests.test_tryton import doctest_checker
+
+from trytond.modules.company.tests import CompanyTestMixin
+
+
+class SalePromotionTestCase(CompanyTestMixin, ModuleTestCase):
+ 'Test Sale Promotion module'
+ module = 'sale_promotion'
+
+
+def suite():
+ suite = trytond.tests.test_tryton.suite()
+ suite.addTests(unittest.TestLoader().loadTestsFromTestCase(
+ SalePromotionTestCase))
+ suite.addTests(doctest.DocFileSuite('scenario_sale_promotion.rst',
+ tearDown=doctest_teardown, encoding='utf-8',
+ checker=doctest_checker,
+ optionflags=doctest.REPORT_ONLY_FIRST_FAILURE))
+ suite.addTests(doctest.DocFileSuite('scenario_sale_promotion_amount.rst',
+ tearDown=doctest_teardown, encoding='utf-8',
+ checker=doctest_checker,
+ optionflags=doctest.REPORT_ONLY_FIRST_FAILURE))
+ return suite
diff --git a/modules/sale_promotion/tox.ini b/modules/sale_promotion/tox.ini
new file mode 100644
index 0000000000..197496c0cb
--- /dev/null
+++ b/modules/sale_promotion/tox.ini
@@ -0,0 +1,15 @@
+[tox]
+envlist = {py36,py37,py38,py39}-{sqlite,postgresql},pypy3-{sqlite,postgresql}
+
+[testenv]
+commands = {envpython} setup.py test
+deps =
+ {py36,py37,py38,py39}-postgresql: psycopg2 >= 2.5
+ pypy3-postgresql: psycopg2cffi >= 2.5
+ py36-sqlite: sqlitebck
+setenv =
+ sqlite: TRYTOND_DATABASE_URI={env:SQLITE_URI:sqlite://}
+ postgresql: TRYTOND_DATABASE_URI={env:POSTGRESQL_URI:postgresql://}
+ sqlite: DB_NAME={env:SQLITE_NAME::memory:}
+ postgresql: DB_NAME={env:POSTGRESQL_NAME:test}
+install_command = pip install --pre --find-links https://trydevpi.tryton.org/?local_version={env:CI_JOB_ID:{env:CI_BUILD_NUMBER}.{env:CI_JOB_NUMBER}} {opts} {packages}
diff --git a/modules/sale_promotion/tryton.cfg b/modules/sale_promotion/tryton.cfg
new file mode 100644
index 0000000000..ac91434de1
--- /dev/null
+++ b/modules/sale_promotion/tryton.cfg
@@ -0,0 +1,13 @@
+[tryton]
+version=6.0.3
+depends:
+ company
+ ir
+ product
+ product_price_list
+ res
+ sale
+ sale_price_list
+xml:
+ sale.xml
+ message.xml
diff --git a/modules/sale_promotion/view/promotion_form.xml b/modules/sale_promotion/view/promotion_form.xml
new file mode 100644
index 0000000000..cca2cb6c6d
--- /dev/null
+++ b/modules/sale_promotion/view/promotion_form.xml
@@ -0,0 +1,42 @@
+
+
+
diff --git a/modules/sale_promotion/view/promotion_list.xml b/modules/sale_promotion/view/promotion_list.xml
new file mode 100644
index 0000000000..73dadbbcd3
--- /dev/null
+++ b/modules/sale_promotion/view/promotion_list.xml
@@ -0,0 +1,9 @@
+
+
+
+
+
+
+
+
diff --git a/modules/sale_promotion_coupon/.drone.yml b/modules/sale_promotion_coupon/.drone.yml
new file mode 100644
index 0000000000..2049d30a49
--- /dev/null
+++ b/modules/sale_promotion_coupon/.drone.yml
@@ -0,0 +1,68 @@
+clone:
+ hg:
+ image: plugins/hg
+ environment:
+ - HG_SHARE_POOL=/root/.cache/hg
+ volumes:
+ - cache:/root/.cache
+
+pipeline:
+ tox:
+ image: ${IMAGE}
+ environment:
+ - CFLAGS=-O0
+ - DB_CACHE=/cache
+ - TOX_TESTENV_PASSENV=CFLAGS DB_CACHE CI_BUILD_NUMBER CI_JOB_NUMBER CI_JOB_ID
+ - POSTGRESQL_URI=postgresql://postgres@postgresql:5432/
+ commands:
+ - echo "[extensions]" >> /root/.hgrc
+ - echo "hgext.share =" >> /root/.hgrc
+ - echo "[share]" >> /root/.hgrc
+ - echo "pool = /root/.cache/hg" >> /root/.hgrc
+ - pip install tox
+ - tox -e "${TOXENV}-${DATABASE}"
+ volumes:
+ - cache:/root/.cache
+ check_dist:
+ image: ${IMAGE}
+ commands:
+ - pip install twine
+ - python setup.py sdist
+ - twine check dist/*
+
+services:
+ postgresql:
+ image: postgres
+ environment:
+ - POSTGRES_HOST_AUTH_METHOD=trust
+ command: "-c fsync=off -c synchronous_commit=off -c full_page_writes=off"
+ when:
+ matrix:
+ DATABASE: postgresql
+
+matrix:
+ include:
+ - IMAGE: python:3.6
+ TOXENV: py36
+ DATABASE: sqlite
+ - IMAGE: python:3.6
+ TOXENV: py36
+ DATABASE: postgresql
+ - IMAGE: python:3.7
+ TOXENV: py37
+ DATABASE: sqlite
+ - IMAGE: python:3.7
+ TOXENV: py37
+ DATABASE: postgresql
+ - IMAGE: python:3.8
+ TOXENV: py38
+ DATABASE: sqlite
+ - IMAGE: python:3.8
+ TOXENV: py38
+ DATABASE: postgresql
+ - IMAGE: python:3.9
+ TOXENV: py39
+ DATABASE: sqlite
+ - IMAGE: python:3.9
+ TOXENV: py39
+ DATABASE: postgresql
diff --git a/modules/sale_promotion_coupon/.flake8 b/modules/sale_promotion_coupon/.flake8
new file mode 100644
index 0000000000..fa6b4f66d1
--- /dev/null
+++ b/modules/sale_promotion_coupon/.flake8
@@ -0,0 +1,2 @@
+[flake8]
+ignore=E123,E124,E126,E128,E741,W503
diff --git a/modules/sale_promotion_coupon/CHANGELOG b/modules/sale_promotion_coupon/CHANGELOG
new file mode 100644
index 0000000000..a880e51ea8
--- /dev/null
+++ b/modules/sale_promotion_coupon/CHANGELOG
@@ -0,0 +1,22 @@
+Version 6.0.0 - 2021-05-03
+* Bug fixes (see mercurial logs for details)
+
+Version 5.8.0 - 2020-11-02
+* Bug fixes (see mercurial logs for details)
+* Remove support for Python 3.5
+
+Version 5.6.0 - 2020-05-04
+* Bug fixes (see mercurial logs for details)
+
+Version 5.4.0 - 2019-11-04
+* Bug fixes (see mercurial logs for details)
+
+Version 5.2.0 - 2019-05-06
+* Bug fixes (see mercurial logs for details)
+
+Version 5.0.0 - 2018-10-01
+* Bug fixes (see mercurial logs for details)
+* Remove support for Python 2.7
+
+Version 4.8.0 - 2018-04-23
+* Initial release
diff --git a/modules/sale_promotion_coupon/COPYRIGHT b/modules/sale_promotion_coupon/COPYRIGHT
new file mode 100644
index 0000000000..2fac73e8df
--- /dev/null
+++ b/modules/sale_promotion_coupon/COPYRIGHT
@@ -0,0 +1,14 @@
+Copyright (C) 2017-2021 Cédric Krier
+
+This program is free software: you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation, either version 3 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program. If not, see .
diff --git a/modules/sale_promotion_coupon/LICENSE b/modules/sale_promotion_coupon/LICENSE
new file mode 100644
index 0000000000..94a9ed024d
--- /dev/null
+++ b/modules/sale_promotion_coupon/LICENSE
@@ -0,0 +1,674 @@
+ GNU GENERAL PUBLIC LICENSE
+ Version 3, 29 June 2007
+
+ Copyright (C) 2007 Free Software Foundation, Inc.
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+ Preamble
+
+ The GNU General Public License is a free, copyleft license for
+software and other kinds of works.
+
+ The licenses for most software and other practical works are designed
+to take away your freedom to share and change the works. By contrast,
+the GNU General Public License is intended to guarantee your freedom to
+share and change all versions of a program--to make sure it remains free
+software for all its users. We, the Free Software Foundation, use the
+GNU General Public License for most of our software; it applies also to
+any other work released this way by its authors. You can apply it to
+your programs, too.
+
+ When we speak of free software, we are referring to freedom, not
+price. Our General Public Licenses are designed to make sure that you
+have the freedom to distribute copies of free software (and charge for
+them if you wish), that you receive source code or can get it if you
+want it, that you can change the software or use pieces of it in new
+free programs, and that you know you can do these things.
+
+ To protect your rights, we need to prevent others from denying you
+these rights or asking you to surrender the rights. Therefore, you have
+certain responsibilities if you distribute copies of the software, or if
+you modify it: responsibilities to respect the freedom of others.
+
+ For example, if you distribute copies of such a program, whether
+gratis or for a fee, you must pass on to the recipients the same
+freedoms that you received. You must make sure that they, too, receive
+or can get the source code. And you must show them these terms so they
+know their rights.
+
+ Developers that use the GNU GPL protect your rights with two steps:
+(1) assert copyright on the software, and (2) offer you this License
+giving you legal permission to copy, distribute and/or modify it.
+
+ For the developers' and authors' protection, the GPL clearly explains
+that there is no warranty for this free software. For both users' and
+authors' sake, the GPL requires that modified versions be marked as
+changed, so that their problems will not be attributed erroneously to
+authors of previous versions.
+
+ Some devices are designed to deny users access to install or run
+modified versions of the software inside them, although the manufacturer
+can do so. This is fundamentally incompatible with the aim of
+protecting users' freedom to change the software. The systematic
+pattern of such abuse occurs in the area of products for individuals to
+use, which is precisely where it is most unacceptable. Therefore, we
+have designed this version of the GPL to prohibit the practice for those
+products. If such problems arise substantially in other domains, we
+stand ready to extend this provision to those domains in future versions
+of the GPL, as needed to protect the freedom of users.
+
+ Finally, every program is threatened constantly by software patents.
+States should not allow patents to restrict development and use of
+software on general-purpose computers, but in those that do, we wish to
+avoid the special danger that patents applied to a free program could
+make it effectively proprietary. To prevent this, the GPL assures that
+patents cannot be used to render the program non-free.
+
+ The precise terms and conditions for copying, distribution and
+modification follow.
+
+ TERMS AND CONDITIONS
+
+ 0. Definitions.
+
+ "This License" refers to version 3 of the GNU General Public License.
+
+ "Copyright" also means copyright-like laws that apply to other kinds of
+works, such as semiconductor masks.
+
+ "The Program" refers to any copyrightable work licensed under this
+License. Each licensee is addressed as "you". "Licensees" and
+"recipients" may be individuals or organizations.
+
+ To "modify" a work means to copy from or adapt all or part of the work
+in a fashion requiring copyright permission, other than the making of an
+exact copy. The resulting work is called a "modified version" of the
+earlier work or a work "based on" the earlier work.
+
+ A "covered work" means either the unmodified Program or a work based
+on the Program.
+
+ To "propagate" a work means to do anything with it that, without
+permission, would make you directly or secondarily liable for
+infringement under applicable copyright law, except executing it on a
+computer or modifying a private copy. Propagation includes copying,
+distribution (with or without modification), making available to the
+public, and in some countries other activities as well.
+
+ To "convey" a work means any kind of propagation that enables other
+parties to make or receive copies. Mere interaction with a user through
+a computer network, with no transfer of a copy, is not conveying.
+
+ An interactive user interface displays "Appropriate Legal Notices"
+to the extent that it includes a convenient and prominently visible
+feature that (1) displays an appropriate copyright notice, and (2)
+tells the user that there is no warranty for the work (except to the
+extent that warranties are provided), that licensees may convey the
+work under this License, and how to view a copy of this License. If
+the interface presents a list of user commands or options, such as a
+menu, a prominent item in the list meets this criterion.
+
+ 1. Source Code.
+
+ The "source code" for a work means the preferred form of the work
+for making modifications to it. "Object code" means any non-source
+form of a work.
+
+ A "Standard Interface" means an interface that either is an official
+standard defined by a recognized standards body, or, in the case of
+interfaces specified for a particular programming language, one that
+is widely used among developers working in that language.
+
+ The "System Libraries" of an executable work include anything, other
+than the work as a whole, that (a) is included in the normal form of
+packaging a Major Component, but which is not part of that Major
+Component, and (b) serves only to enable use of the work with that
+Major Component, or to implement a Standard Interface for which an
+implementation is available to the public in source code form. A
+"Major Component", in this context, means a major essential component
+(kernel, window system, and so on) of the specific operating system
+(if any) on which the executable work runs, or a compiler used to
+produce the work, or an object code interpreter used to run it.
+
+ The "Corresponding Source" for a work in object code form means all
+the source code needed to generate, install, and (for an executable
+work) run the object code and to modify the work, including scripts to
+control those activities. However, it does not include the work's
+System Libraries, or general-purpose tools or generally available free
+programs which are used unmodified in performing those activities but
+which are not part of the work. For example, Corresponding Source
+includes interface definition files associated with source files for
+the work, and the source code for shared libraries and dynamically
+linked subprograms that the work is specifically designed to require,
+such as by intimate data communication or control flow between those
+subprograms and other parts of the work.
+
+ The Corresponding Source need not include anything that users
+can regenerate automatically from other parts of the Corresponding
+Source.
+
+ The Corresponding Source for a work in source code form is that
+same work.
+
+ 2. Basic Permissions.
+
+ All rights granted under this License are granted for the term of
+copyright on the Program, and are irrevocable provided the stated
+conditions are met. This License explicitly affirms your unlimited
+permission to run the unmodified Program. The output from running a
+covered work is covered by this License only if the output, given its
+content, constitutes a covered work. This License acknowledges your
+rights of fair use or other equivalent, as provided by copyright law.
+
+ You may make, run and propagate covered works that you do not
+convey, without conditions so long as your license otherwise remains
+in force. You may convey covered works to others for the sole purpose
+of having them make modifications exclusively for you, or provide you
+with facilities for running those works, provided that you comply with
+the terms of this License in conveying all material for which you do
+not control copyright. Those thus making or running the covered works
+for you must do so exclusively on your behalf, under your direction
+and control, on terms that prohibit them from making any copies of
+your copyrighted material outside their relationship with you.
+
+ Conveying under any other circumstances is permitted solely under
+the conditions stated below. Sublicensing is not allowed; section 10
+makes it unnecessary.
+
+ 3. Protecting Users' Legal Rights From Anti-Circumvention Law.
+
+ No covered work shall be deemed part of an effective technological
+measure under any applicable law fulfilling obligations under article
+11 of the WIPO copyright treaty adopted on 20 December 1996, or
+similar laws prohibiting or restricting circumvention of such
+measures.
+
+ When you convey a covered work, you waive any legal power to forbid
+circumvention of technological measures to the extent such circumvention
+is effected by exercising rights under this License with respect to
+the covered work, and you disclaim any intention to limit operation or
+modification of the work as a means of enforcing, against the work's
+users, your or third parties' legal rights to forbid circumvention of
+technological measures.
+
+ 4. Conveying Verbatim Copies.
+
+ You may convey verbatim copies of the Program's source code as you
+receive it, in any medium, provided that you conspicuously and
+appropriately publish on each copy an appropriate copyright notice;
+keep intact all notices stating that this License and any
+non-permissive terms added in accord with section 7 apply to the code;
+keep intact all notices of the absence of any warranty; and give all
+recipients a copy of this License along with the Program.
+
+ You may charge any price or no price for each copy that you convey,
+and you may offer support or warranty protection for a fee.
+
+ 5. Conveying Modified Source Versions.
+
+ You may convey a work based on the Program, or the modifications to
+produce it from the Program, in the form of source code under the
+terms of section 4, provided that you also meet all of these conditions:
+
+ a) The work must carry prominent notices stating that you modified
+ it, and giving a relevant date.
+
+ b) The work must carry prominent notices stating that it is
+ released under this License and any conditions added under section
+ 7. This requirement modifies the requirement in section 4 to
+ "keep intact all notices".
+
+ c) You must license the entire work, as a whole, under this
+ License to anyone who comes into possession of a copy. This
+ License will therefore apply, along with any applicable section 7
+ additional terms, to the whole of the work, and all its parts,
+ regardless of how they are packaged. This License gives no
+ permission to license the work in any other way, but it does not
+ invalidate such permission if you have separately received it.
+
+ d) If the work has interactive user interfaces, each must display
+ Appropriate Legal Notices; however, if the Program has interactive
+ interfaces that do not display Appropriate Legal Notices, your
+ work need not make them do so.
+
+ A compilation of a covered work with other separate and independent
+works, which are not by their nature extensions of the covered work,
+and which are not combined with it such as to form a larger program,
+in or on a volume of a storage or distribution medium, is called an
+"aggregate" if the compilation and its resulting copyright are not
+used to limit the access or legal rights of the compilation's users
+beyond what the individual works permit. Inclusion of a covered work
+in an aggregate does not cause this License to apply to the other
+parts of the aggregate.
+
+ 6. Conveying Non-Source Forms.
+
+ You may convey a covered work in object code form under the terms
+of sections 4 and 5, provided that you also convey the
+machine-readable Corresponding Source under the terms of this License,
+in one of these ways:
+
+ a) Convey the object code in, or embodied in, a physical product
+ (including a physical distribution medium), accompanied by the
+ Corresponding Source fixed on a durable physical medium
+ customarily used for software interchange.
+
+ b) Convey the object code in, or embodied in, a physical product
+ (including a physical distribution medium), accompanied by a
+ written offer, valid for at least three years and valid for as
+ long as you offer spare parts or customer support for that product
+ model, to give anyone who possesses the object code either (1) a
+ copy of the Corresponding Source for all the software in the
+ product that is covered by this License, on a durable physical
+ medium customarily used for software interchange, for a price no
+ more than your reasonable cost of physically performing this
+ conveying of source, or (2) access to copy the
+ Corresponding Source from a network server at no charge.
+
+ c) Convey individual copies of the object code with a copy of the
+ written offer to provide the Corresponding Source. This
+ alternative is allowed only occasionally and noncommercially, and
+ only if you received the object code with such an offer, in accord
+ with subsection 6b.
+
+ d) Convey the object code by offering access from a designated
+ place (gratis or for a charge), and offer equivalent access to the
+ Corresponding Source in the same way through the same place at no
+ further charge. You need not require recipients to copy the
+ Corresponding Source along with the object code. If the place to
+ copy the object code is a network server, the Corresponding Source
+ may be on a different server (operated by you or a third party)
+ that supports equivalent copying facilities, provided you maintain
+ clear directions next to the object code saying where to find the
+ Corresponding Source. Regardless of what server hosts the
+ Corresponding Source, you remain obligated to ensure that it is
+ available for as long as needed to satisfy these requirements.
+
+ e) Convey the object code using peer-to-peer transmission, provided
+ you inform other peers where the object code and Corresponding
+ Source of the work are being offered to the general public at no
+ charge under subsection 6d.
+
+ A separable portion of the object code, whose source code is excluded
+from the Corresponding Source as a System Library, need not be
+included in conveying the object code work.
+
+ A "User Product" is either (1) a "consumer product", which means any
+tangible personal property which is normally used for personal, family,
+or household purposes, or (2) anything designed or sold for incorporation
+into a dwelling. In determining whether a product is a consumer product,
+doubtful cases shall be resolved in favor of coverage. For a particular
+product received by a particular user, "normally used" refers to a
+typical or common use of that class of product, regardless of the status
+of the particular user or of the way in which the particular user
+actually uses, or expects or is expected to use, the product. A product
+is a consumer product regardless of whether the product has substantial
+commercial, industrial or non-consumer uses, unless such uses represent
+the only significant mode of use of the product.
+
+ "Installation Information" for a User Product means any methods,
+procedures, authorization keys, or other information required to install
+and execute modified versions of a covered work in that User Product from
+a modified version of its Corresponding Source. The information must
+suffice to ensure that the continued functioning of the modified object
+code is in no case prevented or interfered with solely because
+modification has been made.
+
+ If you convey an object code work under this section in, or with, or
+specifically for use in, a User Product, and the conveying occurs as
+part of a transaction in which the right of possession and use of the
+User Product is transferred to the recipient in perpetuity or for a
+fixed term (regardless of how the transaction is characterized), the
+Corresponding Source conveyed under this section must be accompanied
+by the Installation Information. But this requirement does not apply
+if neither you nor any third party retains the ability to install
+modified object code on the User Product (for example, the work has
+been installed in ROM).
+
+ The requirement to provide Installation Information does not include a
+requirement to continue to provide support service, warranty, or updates
+for a work that has been modified or installed by the recipient, or for
+the User Product in which it has been modified or installed. Access to a
+network may be denied when the modification itself materially and
+adversely affects the operation of the network or violates the rules and
+protocols for communication across the network.
+
+ Corresponding Source conveyed, and Installation Information provided,
+in accord with this section must be in a format that is publicly
+documented (and with an implementation available to the public in
+source code form), and must require no special password or key for
+unpacking, reading or copying.
+
+ 7. Additional Terms.
+
+ "Additional permissions" are terms that supplement the terms of this
+License by making exceptions from one or more of its conditions.
+Additional permissions that are applicable to the entire Program shall
+be treated as though they were included in this License, to the extent
+that they are valid under applicable law. If additional permissions
+apply only to part of the Program, that part may be used separately
+under those permissions, but the entire Program remains governed by
+this License without regard to the additional permissions.
+
+ When you convey a copy of a covered work, you may at your option
+remove any additional permissions from that copy, or from any part of
+it. (Additional permissions may be written to require their own
+removal in certain cases when you modify the work.) You may place
+additional permissions on material, added by you to a covered work,
+for which you have or can give appropriate copyright permission.
+
+ Notwithstanding any other provision of this License, for material you
+add to a covered work, you may (if authorized by the copyright holders of
+that material) supplement the terms of this License with terms:
+
+ a) Disclaiming warranty or limiting liability differently from the
+ terms of sections 15 and 16 of this License; or
+
+ b) Requiring preservation of specified reasonable legal notices or
+ author attributions in that material or in the Appropriate Legal
+ Notices displayed by works containing it; or
+
+ c) Prohibiting misrepresentation of the origin of that material, or
+ requiring that modified versions of such material be marked in
+ reasonable ways as different from the original version; or
+
+ d) Limiting the use for publicity purposes of names of licensors or
+ authors of the material; or
+
+ e) Declining to grant rights under trademark law for use of some
+ trade names, trademarks, or service marks; or
+
+ f) Requiring indemnification of licensors and authors of that
+ material by anyone who conveys the material (or modified versions of
+ it) with contractual assumptions of liability to the recipient, for
+ any liability that these contractual assumptions directly impose on
+ those licensors and authors.
+
+ All other non-permissive additional terms are considered "further
+restrictions" within the meaning of section 10. If the Program as you
+received it, or any part of it, contains a notice stating that it is
+governed by this License along with a term that is a further
+restriction, you may remove that term. If a license document contains
+a further restriction but permits relicensing or conveying under this
+License, you may add to a covered work material governed by the terms
+of that license document, provided that the further restriction does
+not survive such relicensing or conveying.
+
+ If you add terms to a covered work in accord with this section, you
+must place, in the relevant source files, a statement of the
+additional terms that apply to those files, or a notice indicating
+where to find the applicable terms.
+
+ Additional terms, permissive or non-permissive, may be stated in the
+form of a separately written license, or stated as exceptions;
+the above requirements apply either way.
+
+ 8. Termination.
+
+ You may not propagate or modify a covered work except as expressly
+provided under this License. Any attempt otherwise to propagate or
+modify it is void, and will automatically terminate your rights under
+this License (including any patent licenses granted under the third
+paragraph of section 11).
+
+ However, if you cease all violation of this License, then your
+license from a particular copyright holder is reinstated (a)
+provisionally, unless and until the copyright holder explicitly and
+finally terminates your license, and (b) permanently, if the copyright
+holder fails to notify you of the violation by some reasonable means
+prior to 60 days after the cessation.
+
+ Moreover, your license from a particular copyright holder is
+reinstated permanently if the copyright holder notifies you of the
+violation by some reasonable means, this is the first time you have
+received notice of violation of this License (for any work) from that
+copyright holder, and you cure the violation prior to 30 days after
+your receipt of the notice.
+
+ Termination of your rights under this section does not terminate the
+licenses of parties who have received copies or rights from you under
+this License. If your rights have been terminated and not permanently
+reinstated, you do not qualify to receive new licenses for the same
+material under section 10.
+
+ 9. Acceptance Not Required for Having Copies.
+
+ You are not required to accept this License in order to receive or
+run a copy of the Program. Ancillary propagation of a covered work
+occurring solely as a consequence of using peer-to-peer transmission
+to receive a copy likewise does not require acceptance. However,
+nothing other than this License grants you permission to propagate or
+modify any covered work. These actions infringe copyright if you do
+not accept this License. Therefore, by modifying or propagating a
+covered work, you indicate your acceptance of this License to do so.
+
+ 10. Automatic Licensing of Downstream Recipients.
+
+ Each time you convey a covered work, the recipient automatically
+receives a license from the original licensors, to run, modify and
+propagate that work, subject to this License. You are not responsible
+for enforcing compliance by third parties with this License.
+
+ An "entity transaction" is a transaction transferring control of an
+organization, or substantially all assets of one, or subdividing an
+organization, or merging organizations. If propagation of a covered
+work results from an entity transaction, each party to that
+transaction who receives a copy of the work also receives whatever
+licenses to the work the party's predecessor in interest had or could
+give under the previous paragraph, plus a right to possession of the
+Corresponding Source of the work from the predecessor in interest, if
+the predecessor has it or can get it with reasonable efforts.
+
+ You may not impose any further restrictions on the exercise of the
+rights granted or affirmed under this License. For example, you may
+not impose a license fee, royalty, or other charge for exercise of
+rights granted under this License, and you may not initiate litigation
+(including a cross-claim or counterclaim in a lawsuit) alleging that
+any patent claim is infringed by making, using, selling, offering for
+sale, or importing the Program or any portion of it.
+
+ 11. Patents.
+
+ A "contributor" is a copyright holder who authorizes use under this
+License of the Program or a work on which the Program is based. The
+work thus licensed is called the contributor's "contributor version".
+
+ A contributor's "essential patent claims" are all patent claims
+owned or controlled by the contributor, whether already acquired or
+hereafter acquired, that would be infringed by some manner, permitted
+by this License, of making, using, or selling its contributor version,
+but do not include claims that would be infringed only as a
+consequence of further modification of the contributor version. For
+purposes of this definition, "control" includes the right to grant
+patent sublicenses in a manner consistent with the requirements of
+this License.
+
+ Each contributor grants you a non-exclusive, worldwide, royalty-free
+patent license under the contributor's essential patent claims, to
+make, use, sell, offer for sale, import and otherwise run, modify and
+propagate the contents of its contributor version.
+
+ In the following three paragraphs, a "patent license" is any express
+agreement or commitment, however denominated, not to enforce a patent
+(such as an express permission to practice a patent or covenant not to
+sue for patent infringement). To "grant" such a patent license to a
+party means to make such an agreement or commitment not to enforce a
+patent against the party.
+
+ If you convey a covered work, knowingly relying on a patent license,
+and the Corresponding Source of the work is not available for anyone
+to copy, free of charge and under the terms of this License, through a
+publicly available network server or other readily accessible means,
+then you must either (1) cause the Corresponding Source to be so
+available, or (2) arrange to deprive yourself of the benefit of the
+patent license for this particular work, or (3) arrange, in a manner
+consistent with the requirements of this License, to extend the patent
+license to downstream recipients. "Knowingly relying" means you have
+actual knowledge that, but for the patent license, your conveying the
+covered work in a country, or your recipient's use of the covered work
+in a country, would infringe one or more identifiable patents in that
+country that you have reason to believe are valid.
+
+ If, pursuant to or in connection with a single transaction or
+arrangement, you convey, or propagate by procuring conveyance of, a
+covered work, and grant a patent license to some of the parties
+receiving the covered work authorizing them to use, propagate, modify
+or convey a specific copy of the covered work, then the patent license
+you grant is automatically extended to all recipients of the covered
+work and works based on it.
+
+ A patent license is "discriminatory" if it does not include within
+the scope of its coverage, prohibits the exercise of, or is
+conditioned on the non-exercise of one or more of the rights that are
+specifically granted under this License. You may not convey a covered
+work if you are a party to an arrangement with a third party that is
+in the business of distributing software, under which you make payment
+to the third party based on the extent of your activity of conveying
+the work, and under which the third party grants, to any of the
+parties who would receive the covered work from you, a discriminatory
+patent license (a) in connection with copies of the covered work
+conveyed by you (or copies made from those copies), or (b) primarily
+for and in connection with specific products or compilations that
+contain the covered work, unless you entered into that arrangement,
+or that patent license was granted, prior to 28 March 2007.
+
+ Nothing in this License shall be construed as excluding or limiting
+any implied license or other defenses to infringement that may
+otherwise be available to you under applicable patent law.
+
+ 12. No Surrender of Others' Freedom.
+
+ If conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License. If you cannot convey a
+covered work so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you may
+not convey it at all. For example, if you agree to terms that obligate you
+to collect a royalty for further conveying from those to whom you convey
+the Program, the only way you could satisfy both those terms and this
+License would be to refrain entirely from conveying the Program.
+
+ 13. Use with the GNU Affero General Public License.
+
+ Notwithstanding any other provision of this License, you have
+permission to link or combine any covered work with a work licensed
+under version 3 of the GNU Affero General Public License into a single
+combined work, and to convey the resulting work. The terms of this
+License will continue to apply to the part which is the covered work,
+but the special requirements of the GNU Affero General Public License,
+section 13, concerning interaction through a network will apply to the
+combination as such.
+
+ 14. Revised Versions of this License.
+
+ The Free Software Foundation may publish revised and/or new versions of
+the GNU General Public License from time to time. Such new versions will
+be similar in spirit to the present version, but may differ in detail to
+address new problems or concerns.
+
+ Each version is given a distinguishing version number. If the
+Program specifies that a certain numbered version of the GNU General
+Public License "or any later version" applies to it, you have the
+option of following the terms and conditions either of that numbered
+version or of any later version published by the Free Software
+Foundation. If the Program does not specify a version number of the
+GNU General Public License, you may choose any version ever published
+by the Free Software Foundation.
+
+ If the Program specifies that a proxy can decide which future
+versions of the GNU General Public License can be used, that proxy's
+public statement of acceptance of a version permanently authorizes you
+to choose that version for the Program.
+
+ Later license versions may give you additional or different
+permissions. However, no additional obligations are imposed on any
+author or copyright holder as a result of your choosing to follow a
+later version.
+
+ 15. Disclaimer of Warranty.
+
+ THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY
+APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT
+HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY
+OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO,
+THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM
+IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF
+ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
+
+ 16. Limitation of Liability.
+
+ IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS
+THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY
+GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE
+USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF
+DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD
+PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS),
+EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF
+SUCH DAMAGES.
+
+ 17. Interpretation of Sections 15 and 16.
+
+ If the disclaimer of warranty and limitation of liability provided
+above cannot be given local legal effect according to their terms,
+reviewing courts shall apply local law that most closely approximates
+an absolute waiver of all civil liability in connection with the
+Program, unless a warranty or assumption of liability accompanies a
+copy of the Program in return for a fee.
+
+ END OF TERMS AND CONDITIONS
+
+ How to Apply These Terms to Your New Programs
+
+ If you develop a new program, and you want it to be of the greatest
+possible use to the public, the best way to achieve this is to make it
+free software which everyone can redistribute and change under these terms.
+
+ To do so, attach the following notices to the program. It is safest
+to attach them to the start of each source file to most effectively
+state the exclusion of warranty; and each file should have at least
+the "copyright" line and a pointer to where the full notice is found.
+
+
+ Copyright (C)
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see .
+
+Also add information on how to contact you by electronic and paper mail.
+
+ If the program does terminal interaction, make it output a short
+notice like this when it starts in an interactive mode:
+
+ Copyright (C)
+ This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
+ This is free software, and you are welcome to redistribute it
+ under certain conditions; type `show c' for details.
+
+The hypothetical commands `show w' and `show c' should show the appropriate
+parts of the General Public License. Of course, your program's commands
+might be different; for a GUI interface, you would use an "about box".
+
+ You should also get your employer (if you work as a programmer) or school,
+if any, to sign a "copyright disclaimer" for the program, if necessary.
+For more information on this, and how to apply and follow the GNU GPL, see
+.
+
+ The GNU General Public License does not permit incorporating your program
+into proprietary programs. If your program is a subroutine library, you
+may consider it more useful to permit linking proprietary applications with
+the library. If this is what you want to do, use the GNU Lesser General
+Public License instead of this License. But first, please read
+.
diff --git a/modules/sale_promotion_coupon/MANIFEST.in b/modules/sale_promotion_coupon/MANIFEST.in
new file mode 100644
index 0000000000..e88b2348a3
--- /dev/null
+++ b/modules/sale_promotion_coupon/MANIFEST.in
@@ -0,0 +1,5 @@
+include CHANGELOG
+include COPYRIGHT
+include LICENSE
+include README.rst
+include doc/*
diff --git a/modules/sale_promotion_coupon/README.rst b/modules/sale_promotion_coupon/README.rst
new file mode 120000
index 0000000000..176d9c2695
--- /dev/null
+++ b/modules/sale_promotion_coupon/README.rst
@@ -0,0 +1 @@
+doc/index.rst
\ No newline at end of file
diff --git a/modules/sale_promotion_coupon/__init__.py b/modules/sale_promotion_coupon/__init__.py
new file mode 100644
index 0000000000..1be3a33d63
--- /dev/null
+++ b/modules/sale_promotion_coupon/__init__.py
@@ -0,0 +1,22 @@
+# This file is part of Tryton. The COPYRIGHT file at the top level of
+# this repository contains the full copyright notices and license terms.
+
+from trytond.pool import Pool
+
+from . import sale
+
+__all__ = ['register']
+
+
+def register():
+ Pool.register(
+ sale.Promotion,
+ sale.PromotionCoupon,
+ sale.PromotionCouponNumber,
+ sale.Sale,
+ sale.Sale_PromotionCouponNumber,
+ module='sale_promotion_coupon', type_='model')
+ Pool.register(
+ module='sale_promotion_coupon', type_='wizard')
+ Pool.register(
+ module='sale_promotion_coupon', type_='report')
diff --git a/modules/sale_promotion_coupon/doc/index.rst b/modules/sale_promotion_coupon/doc/index.rst
new file mode 100644
index 0000000000..a5b6ba3f6e
--- /dev/null
+++ b/modules/sale_promotion_coupon/doc/index.rst
@@ -0,0 +1,18 @@
+Sale Promotion Coupon Module
+############################
+
+The sale_promotion_coupon module adds coupon to the promotions.
+
+A promotion with coupons will be applied only if a linked coupon has been added
+on the sale.
+
+Promotion Coupon
+****************
+
+It defines the behaviours of a sets of coupon numbers for a promotion:
+
+- *Name*: The name of the coupon.
+- *Promotion*: The promotion to which the coupon is attached.
+- *Number of Use*: How much time a coupon number can be used.
+- *Per Party*: How the usage is counted.
+- *Numbers*: The list of numbers which must be unique.
diff --git a/modules/sale_promotion_coupon/exceptions.py b/modules/sale_promotion_coupon/exceptions.py
new file mode 100644
index 0000000000..ed877fb1b8
--- /dev/null
+++ b/modules/sale_promotion_coupon/exceptions.py
@@ -0,0 +1,7 @@
+# This file is part of Tryton. The COPYRIGHT file at the top level of
+# this repository contains the full copyright notices and license terms.
+from trytond.model.exceptions import ValidationError
+
+
+class DuplicateError(ValidationError):
+ pass
diff --git a/modules/sale_promotion_coupon/locale/bg.po b/modules/sale_promotion_coupon/locale/bg.po
new file mode 100644
index 0000000000..604b66d841
--- /dev/null
+++ b/modules/sale_promotion_coupon/locale/bg.po
@@ -0,0 +1,77 @@
+#
+msgid ""
+msgstr "Content-Type: text/plain; charset=utf-8\n"
+
+msgctxt "field:sale.promotion,coupons:"
+msgid "Coupons"
+msgstr ""
+
+msgctxt "field:sale.promotion.coupon,name:"
+msgid "Name"
+msgstr ""
+
+msgctxt "field:sale.promotion.coupon,number_of_use:"
+msgid "Number of Use"
+msgstr ""
+
+msgctxt "field:sale.promotion.coupon,numbers:"
+msgid "Numbers"
+msgstr ""
+
+msgctxt "field:sale.promotion.coupon,per_party:"
+msgid "Per Party"
+msgstr ""
+
+msgctxt "field:sale.promotion.coupon,promotion:"
+msgid "Promotion"
+msgstr ""
+
+msgctxt "field:sale.promotion.coupon.number,active:"
+msgid "Active"
+msgstr ""
+
+msgctxt "field:sale.promotion.coupon.number,coupon:"
+msgid "Coupon"
+msgstr ""
+
+msgctxt "field:sale.promotion.coupon.number,number:"
+msgid "Number"
+msgstr ""
+
+msgctxt "field:sale.sale,coupons:"
+msgid "Coupons"
+msgstr ""
+
+msgctxt "field:sale.sale-sale.promotion.coupon.number,number:"
+msgid "Number"
+msgstr ""
+
+msgctxt "field:sale.sale-sale.promotion.coupon.number,sale:"
+msgid "Sale"
+msgstr ""
+
+msgctxt "help:sale.promotion.coupon,number_of_use:"
+msgid ""
+"How much times a coupon number can be used.\n"
+"0 or below for no limit."
+msgstr ""
+
+msgctxt "help:sale.promotion.coupon,per_party:"
+msgid "Check to count usage per party."
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_duplicate_numbers"
+msgid "The coupons numbered \"%(numbers)s\" are duplicated."
+msgstr ""
+
+msgctxt "model:sale.promotion.coupon,name:"
+msgid "Promotion Coupon"
+msgstr ""
+
+msgctxt "model:sale.promotion.coupon.number,name:"
+msgid "Promotion Coupon Number"
+msgstr ""
+
+msgctxt "model:sale.sale-sale.promotion.coupon.number,name:"
+msgid "Sale - Promotion Coupon Number"
+msgstr ""
diff --git a/modules/sale_promotion_coupon/locale/ca.po b/modules/sale_promotion_coupon/locale/ca.po
new file mode 100644
index 0000000000..3dedbef384
--- /dev/null
+++ b/modules/sale_promotion_coupon/locale/ca.po
@@ -0,0 +1,79 @@
+#
+msgid ""
+msgstr "Content-Type: text/plain; charset=utf-8\n"
+
+msgctxt "field:sale.promotion,coupons:"
+msgid "Coupons"
+msgstr "Cupons"
+
+msgctxt "field:sale.promotion.coupon,name:"
+msgid "Name"
+msgstr "Nom"
+
+msgctxt "field:sale.promotion.coupon,number_of_use:"
+msgid "Number of Use"
+msgstr "Nombre d'usos"
+
+msgctxt "field:sale.promotion.coupon,numbers:"
+msgid "Numbers"
+msgstr "Números"
+
+msgctxt "field:sale.promotion.coupon,per_party:"
+msgid "Per Party"
+msgstr "Per tercer"
+
+msgctxt "field:sale.promotion.coupon,promotion:"
+msgid "Promotion"
+msgstr "Promoció"
+
+msgctxt "field:sale.promotion.coupon.number,active:"
+msgid "Active"
+msgstr "Actiu"
+
+msgctxt "field:sale.promotion.coupon.number,coupon:"
+msgid "Coupon"
+msgstr "Cupó"
+
+msgctxt "field:sale.promotion.coupon.number,number:"
+msgid "Number"
+msgstr "Número"
+
+msgctxt "field:sale.sale,coupons:"
+msgid "Coupons"
+msgstr "Cupons"
+
+msgctxt "field:sale.sale-sale.promotion.coupon.number,number:"
+msgid "Number"
+msgstr "Número"
+
+msgctxt "field:sale.sale-sale.promotion.coupon.number,sale:"
+msgid "Sale"
+msgstr "Venda"
+
+msgctxt "help:sale.promotion.coupon,number_of_use:"
+msgid ""
+"How much times a coupon number can be used.\n"
+"0 or below for no limit."
+msgstr ""
+"El nombre de vegades que es pot utilitzar el cupó.\n"
+"0 o menys indica sense límit."
+
+msgctxt "help:sale.promotion.coupon,per_party:"
+msgid "Check to count usage per party."
+msgstr "Marca per contar l'ús per tercer."
+
+msgctxt "model:ir.message,text:msg_duplicate_numbers"
+msgid "The coupons numbered \"%(numbers)s\" are duplicated."
+msgstr "El cupons numerats \"%(numbers)s\" estan duplicats."
+
+msgctxt "model:sale.promotion.coupon,name:"
+msgid "Promotion Coupon"
+msgstr "Cupó promocional"
+
+msgctxt "model:sale.promotion.coupon.number,name:"
+msgid "Promotion Coupon Number"
+msgstr "Número cupó promocional"
+
+msgctxt "model:sale.sale-sale.promotion.coupon.number,name:"
+msgid "Sale - Promotion Coupon Number"
+msgstr "Venda - Número de cupó promocional"
diff --git a/modules/sale_promotion_coupon/locale/cs.po b/modules/sale_promotion_coupon/locale/cs.po
new file mode 100644
index 0000000000..604b66d841
--- /dev/null
+++ b/modules/sale_promotion_coupon/locale/cs.po
@@ -0,0 +1,77 @@
+#
+msgid ""
+msgstr "Content-Type: text/plain; charset=utf-8\n"
+
+msgctxt "field:sale.promotion,coupons:"
+msgid "Coupons"
+msgstr ""
+
+msgctxt "field:sale.promotion.coupon,name:"
+msgid "Name"
+msgstr ""
+
+msgctxt "field:sale.promotion.coupon,number_of_use:"
+msgid "Number of Use"
+msgstr ""
+
+msgctxt "field:sale.promotion.coupon,numbers:"
+msgid "Numbers"
+msgstr ""
+
+msgctxt "field:sale.promotion.coupon,per_party:"
+msgid "Per Party"
+msgstr ""
+
+msgctxt "field:sale.promotion.coupon,promotion:"
+msgid "Promotion"
+msgstr ""
+
+msgctxt "field:sale.promotion.coupon.number,active:"
+msgid "Active"
+msgstr ""
+
+msgctxt "field:sale.promotion.coupon.number,coupon:"
+msgid "Coupon"
+msgstr ""
+
+msgctxt "field:sale.promotion.coupon.number,number:"
+msgid "Number"
+msgstr ""
+
+msgctxt "field:sale.sale,coupons:"
+msgid "Coupons"
+msgstr ""
+
+msgctxt "field:sale.sale-sale.promotion.coupon.number,number:"
+msgid "Number"
+msgstr ""
+
+msgctxt "field:sale.sale-sale.promotion.coupon.number,sale:"
+msgid "Sale"
+msgstr ""
+
+msgctxt "help:sale.promotion.coupon,number_of_use:"
+msgid ""
+"How much times a coupon number can be used.\n"
+"0 or below for no limit."
+msgstr ""
+
+msgctxt "help:sale.promotion.coupon,per_party:"
+msgid "Check to count usage per party."
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_duplicate_numbers"
+msgid "The coupons numbered \"%(numbers)s\" are duplicated."
+msgstr ""
+
+msgctxt "model:sale.promotion.coupon,name:"
+msgid "Promotion Coupon"
+msgstr ""
+
+msgctxt "model:sale.promotion.coupon.number,name:"
+msgid "Promotion Coupon Number"
+msgstr ""
+
+msgctxt "model:sale.sale-sale.promotion.coupon.number,name:"
+msgid "Sale - Promotion Coupon Number"
+msgstr ""
diff --git a/modules/sale_promotion_coupon/locale/de.po b/modules/sale_promotion_coupon/locale/de.po
new file mode 100644
index 0000000000..6906f3993a
--- /dev/null
+++ b/modules/sale_promotion_coupon/locale/de.po
@@ -0,0 +1,81 @@
+#
+msgid ""
+msgstr "Content-Type: text/plain; charset=utf-8\n"
+
+msgctxt "field:sale.promotion,coupons:"
+msgid "Coupons"
+msgstr "Coupons"
+
+msgctxt "field:sale.promotion.coupon,name:"
+msgid "Name"
+msgstr "Name"
+
+# For a condensed but talking representation in list view it seems better to
+# put 'Anzahl' at the first place.
+msgctxt "field:sale.promotion.coupon,number_of_use:"
+msgid "Number of Use"
+msgstr "Maximale Anzahl Verwendung"
+
+msgctxt "field:sale.promotion.coupon,numbers:"
+msgid "Numbers"
+msgstr "Nummern"
+
+msgctxt "field:sale.promotion.coupon,per_party:"
+msgid "Per Party"
+msgstr "Pro Partei"
+
+msgctxt "field:sale.promotion.coupon,promotion:"
+msgid "Promotion"
+msgstr "Verkaufsaktion"
+
+msgctxt "field:sale.promotion.coupon.number,active:"
+msgid "Active"
+msgstr "Aktiv"
+
+msgctxt "field:sale.promotion.coupon.number,coupon:"
+msgid "Coupon"
+msgstr "Coupon"
+
+msgctxt "field:sale.promotion.coupon.number,number:"
+msgid "Number"
+msgstr "Nummer"
+
+msgctxt "field:sale.sale,coupons:"
+msgid "Coupons"
+msgstr "Coupons"
+
+msgctxt "field:sale.sale-sale.promotion.coupon.number,number:"
+msgid "Number"
+msgstr "Nummer"
+
+msgctxt "field:sale.sale-sale.promotion.coupon.number,sale:"
+msgid "Sale"
+msgstr "Verkauf"
+
+msgctxt "help:sale.promotion.coupon,number_of_use:"
+msgid ""
+"How much times a coupon number can be used.\n"
+"0 or below for no limit."
+msgstr ""
+"Wie oft eine Coupon-Nummer genutzt werden kann.\n"
+"0 oder weniger für kein Limit."
+
+msgctxt "help:sale.promotion.coupon,per_party:"
+msgid "Check to count usage per party."
+msgstr "Aktivieren um die Anzahl der Verwendungen pro Partei zu zählen."
+
+msgctxt "model:ir.message,text:msg_duplicate_numbers"
+msgid "The coupons numbered \"%(numbers)s\" are duplicated."
+msgstr "Die Coupon Nummern \"%(numbers)s\" sind doppelt."
+
+msgctxt "model:sale.promotion.coupon,name:"
+msgid "Promotion Coupon"
+msgstr "Aktions-Coupon"
+
+msgctxt "model:sale.promotion.coupon.number,name:"
+msgid "Promotion Coupon Number"
+msgstr "Aktions-Coupon-Nummer"
+
+msgctxt "model:sale.sale-sale.promotion.coupon.number,name:"
+msgid "Sale - Promotion Coupon Number"
+msgstr "Verkauf - Aktions-Coupon-Nummer"
diff --git a/modules/sale_promotion_coupon/locale/es.po b/modules/sale_promotion_coupon/locale/es.po
new file mode 100644
index 0000000000..309a14ee74
--- /dev/null
+++ b/modules/sale_promotion_coupon/locale/es.po
@@ -0,0 +1,79 @@
+#
+msgid ""
+msgstr "Content-Type: text/plain; charset=utf-8\n"
+
+msgctxt "field:sale.promotion,coupons:"
+msgid "Coupons"
+msgstr "Cupones"
+
+msgctxt "field:sale.promotion.coupon,name:"
+msgid "Name"
+msgstr "Nombre"
+
+msgctxt "field:sale.promotion.coupon,number_of_use:"
+msgid "Number of Use"
+msgstr "Nombre de usos"
+
+msgctxt "field:sale.promotion.coupon,numbers:"
+msgid "Numbers"
+msgstr "Números"
+
+msgctxt "field:sale.promotion.coupon,per_party:"
+msgid "Per Party"
+msgstr "Por tercero"
+
+msgctxt "field:sale.promotion.coupon,promotion:"
+msgid "Promotion"
+msgstr "Promoción"
+
+msgctxt "field:sale.promotion.coupon.number,active:"
+msgid "Active"
+msgstr "Activo"
+
+msgctxt "field:sale.promotion.coupon.number,coupon:"
+msgid "Coupon"
+msgstr "Cupón"
+
+msgctxt "field:sale.promotion.coupon.number,number:"
+msgid "Number"
+msgstr "Número"
+
+msgctxt "field:sale.sale,coupons:"
+msgid "Coupons"
+msgstr "Cupones"
+
+msgctxt "field:sale.sale-sale.promotion.coupon.number,number:"
+msgid "Number"
+msgstr "Número"
+
+msgctxt "field:sale.sale-sale.promotion.coupon.number,sale:"
+msgid "Sale"
+msgstr "Venta"
+
+msgctxt "help:sale.promotion.coupon,number_of_use:"
+msgid ""
+"How much times a coupon number can be used.\n"
+"0 or below for no limit."
+msgstr ""
+"El número de veces que se puede utilizar el cupón.\n"
+"0 o menos indica sin límite."
+
+msgctxt "help:sale.promotion.coupon,per_party:"
+msgid "Check to count usage per party."
+msgstr "Marcar para contar el uso por tercero."
+
+msgctxt "model:ir.message,text:msg_duplicate_numbers"
+msgid "The coupons numbered \"%(numbers)s\" are duplicated."
+msgstr "Los cupones con numeración \"%(numbers)s\" están duplicados."
+
+msgctxt "model:sale.promotion.coupon,name:"
+msgid "Promotion Coupon"
+msgstr "Cupón promocional"
+
+msgctxt "model:sale.promotion.coupon.number,name:"
+msgid "Promotion Coupon Number"
+msgstr "Número de cupón promocional"
+
+msgctxt "model:sale.sale-sale.promotion.coupon.number,name:"
+msgid "Sale - Promotion Coupon Number"
+msgstr "Venta - Número de cupón promocional"
diff --git a/modules/sale_promotion_coupon/locale/es_419.po b/modules/sale_promotion_coupon/locale/es_419.po
new file mode 100644
index 0000000000..604b66d841
--- /dev/null
+++ b/modules/sale_promotion_coupon/locale/es_419.po
@@ -0,0 +1,77 @@
+#
+msgid ""
+msgstr "Content-Type: text/plain; charset=utf-8\n"
+
+msgctxt "field:sale.promotion,coupons:"
+msgid "Coupons"
+msgstr ""
+
+msgctxt "field:sale.promotion.coupon,name:"
+msgid "Name"
+msgstr ""
+
+msgctxt "field:sale.promotion.coupon,number_of_use:"
+msgid "Number of Use"
+msgstr ""
+
+msgctxt "field:sale.promotion.coupon,numbers:"
+msgid "Numbers"
+msgstr ""
+
+msgctxt "field:sale.promotion.coupon,per_party:"
+msgid "Per Party"
+msgstr ""
+
+msgctxt "field:sale.promotion.coupon,promotion:"
+msgid "Promotion"
+msgstr ""
+
+msgctxt "field:sale.promotion.coupon.number,active:"
+msgid "Active"
+msgstr ""
+
+msgctxt "field:sale.promotion.coupon.number,coupon:"
+msgid "Coupon"
+msgstr ""
+
+msgctxt "field:sale.promotion.coupon.number,number:"
+msgid "Number"
+msgstr ""
+
+msgctxt "field:sale.sale,coupons:"
+msgid "Coupons"
+msgstr ""
+
+msgctxt "field:sale.sale-sale.promotion.coupon.number,number:"
+msgid "Number"
+msgstr ""
+
+msgctxt "field:sale.sale-sale.promotion.coupon.number,sale:"
+msgid "Sale"
+msgstr ""
+
+msgctxt "help:sale.promotion.coupon,number_of_use:"
+msgid ""
+"How much times a coupon number can be used.\n"
+"0 or below for no limit."
+msgstr ""
+
+msgctxt "help:sale.promotion.coupon,per_party:"
+msgid "Check to count usage per party."
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_duplicate_numbers"
+msgid "The coupons numbered \"%(numbers)s\" are duplicated."
+msgstr ""
+
+msgctxt "model:sale.promotion.coupon,name:"
+msgid "Promotion Coupon"
+msgstr ""
+
+msgctxt "model:sale.promotion.coupon.number,name:"
+msgid "Promotion Coupon Number"
+msgstr ""
+
+msgctxt "model:sale.sale-sale.promotion.coupon.number,name:"
+msgid "Sale - Promotion Coupon Number"
+msgstr ""
diff --git a/modules/sale_promotion_coupon/locale/et.po b/modules/sale_promotion_coupon/locale/et.po
new file mode 100644
index 0000000000..92456ba5b4
--- /dev/null
+++ b/modules/sale_promotion_coupon/locale/et.po
@@ -0,0 +1,77 @@
+#
+msgid ""
+msgstr "Content-Type: text/plain; charset=utf-8\n"
+
+msgctxt "field:sale.promotion,coupons:"
+msgid "Coupons"
+msgstr "Kupongid"
+
+msgctxt "field:sale.promotion.coupon,name:"
+msgid "Name"
+msgstr "Nimi"
+
+msgctxt "field:sale.promotion.coupon,number_of_use:"
+msgid "Number of Use"
+msgstr "Kasutuse arv"
+
+msgctxt "field:sale.promotion.coupon,numbers:"
+msgid "Numbers"
+msgstr "Numbrid"
+
+msgctxt "field:sale.promotion.coupon,per_party:"
+msgid "Per Party"
+msgstr "Osapoole kohta"
+
+msgctxt "field:sale.promotion.coupon,promotion:"
+msgid "Promotion"
+msgstr "Soodustus"
+
+msgctxt "field:sale.promotion.coupon.number,active:"
+msgid "Active"
+msgstr "Aktiivne"
+
+msgctxt "field:sale.promotion.coupon.number,coupon:"
+msgid "Coupon"
+msgstr "Kupong"
+
+msgctxt "field:sale.promotion.coupon.number,number:"
+msgid "Number"
+msgstr "Number"
+
+msgctxt "field:sale.sale,coupons:"
+msgid "Coupons"
+msgstr "Kupongid"
+
+msgctxt "field:sale.sale-sale.promotion.coupon.number,number:"
+msgid "Number"
+msgstr "Number"
+
+msgctxt "field:sale.sale-sale.promotion.coupon.number,sale:"
+msgid "Sale"
+msgstr "Müük"
+
+msgctxt "help:sale.promotion.coupon,number_of_use:"
+msgid ""
+"How much times a coupon number can be used.\n"
+"0 or below for no limit."
+msgstr ""
+
+msgctxt "help:sale.promotion.coupon,per_party:"
+msgid "Check to count usage per party."
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_duplicate_numbers"
+msgid "The coupons numbered \"%(numbers)s\" are duplicated."
+msgstr ""
+
+msgctxt "model:sale.promotion.coupon,name:"
+msgid "Promotion Coupon"
+msgstr "Sooduskupong"
+
+msgctxt "model:sale.promotion.coupon.number,name:"
+msgid "Promotion Coupon Number"
+msgstr "Sooduskupongi number"
+
+msgctxt "model:sale.sale-sale.promotion.coupon.number,name:"
+msgid "Sale - Promotion Coupon Number"
+msgstr "Müük - sooduskupongi number"
diff --git a/modules/sale_promotion_coupon/locale/fa.po b/modules/sale_promotion_coupon/locale/fa.po
new file mode 100644
index 0000000000..d0bee77614
--- /dev/null
+++ b/modules/sale_promotion_coupon/locale/fa.po
@@ -0,0 +1,79 @@
+#
+msgid ""
+msgstr "Content-Type: text/plain; charset=utf-8\n"
+
+msgctxt "field:sale.promotion,coupons:"
+msgid "Coupons"
+msgstr "کوپن ها"
+
+msgctxt "field:sale.promotion.coupon,name:"
+msgid "Name"
+msgstr "نام"
+
+msgctxt "field:sale.promotion.coupon,number_of_use:"
+msgid "Number of Use"
+msgstr "تعداد استفاده"
+
+msgctxt "field:sale.promotion.coupon,numbers:"
+msgid "Numbers"
+msgstr "تعداد"
+
+msgctxt "field:sale.promotion.coupon,per_party:"
+msgid "Per Party"
+msgstr "در هر نهاد/سازمان"
+
+msgctxt "field:sale.promotion.coupon,promotion:"
+msgid "Promotion"
+msgstr "تبلیغ و ترویج"
+
+msgctxt "field:sale.promotion.coupon.number,active:"
+msgid "Active"
+msgstr "فعال"
+
+msgctxt "field:sale.promotion.coupon.number,coupon:"
+msgid "Coupon"
+msgstr "کوپن"
+
+msgctxt "field:sale.promotion.coupon.number,number:"
+msgid "Number"
+msgstr "شماره"
+
+msgctxt "field:sale.sale,coupons:"
+msgid "Coupons"
+msgstr "کوپن ها"
+
+msgctxt "field:sale.sale-sale.promotion.coupon.number,number:"
+msgid "Number"
+msgstr "شماره"
+
+msgctxt "field:sale.sale-sale.promotion.coupon.number,sale:"
+msgid "Sale"
+msgstr "فروش"
+
+msgctxt "help:sale.promotion.coupon,number_of_use:"
+msgid ""
+"How much times a coupon number can be used.\n"
+"0 or below for no limit."
+msgstr ""
+"چه مدت زمان یک کوپن باید استفاده شود.\n"
+"0 یا کمتر برای نامحدود."
+
+msgctxt "help:sale.promotion.coupon,per_party:"
+msgid "Check to count usage per party."
+msgstr "تیک بزنید برای شمارش استفاده در هر نهاد/سازمان."
+
+msgctxt "model:ir.message,text:msg_duplicate_numbers"
+msgid "The coupons numbered \"%(numbers)s\" are duplicated."
+msgstr "تعداد کوپن های :\"%s\" دوبرابر شده است."
+
+msgctxt "model:sale.promotion.coupon,name:"
+msgid "Promotion Coupon"
+msgstr "کوپن تبلیغ و ترویج"
+
+msgctxt "model:sale.promotion.coupon.number,name:"
+msgid "Promotion Coupon Number"
+msgstr "شماره کوپن تبلیغ و ترویج"
+
+msgctxt "model:sale.sale-sale.promotion.coupon.number,name:"
+msgid "Sale - Promotion Coupon Number"
+msgstr "فروش - شماره کوپن تبلیغ و ترویج"
diff --git a/modules/sale_promotion_coupon/locale/fi.po b/modules/sale_promotion_coupon/locale/fi.po
new file mode 100644
index 0000000000..604b66d841
--- /dev/null
+++ b/modules/sale_promotion_coupon/locale/fi.po
@@ -0,0 +1,77 @@
+#
+msgid ""
+msgstr "Content-Type: text/plain; charset=utf-8\n"
+
+msgctxt "field:sale.promotion,coupons:"
+msgid "Coupons"
+msgstr ""
+
+msgctxt "field:sale.promotion.coupon,name:"
+msgid "Name"
+msgstr ""
+
+msgctxt "field:sale.promotion.coupon,number_of_use:"
+msgid "Number of Use"
+msgstr ""
+
+msgctxt "field:sale.promotion.coupon,numbers:"
+msgid "Numbers"
+msgstr ""
+
+msgctxt "field:sale.promotion.coupon,per_party:"
+msgid "Per Party"
+msgstr ""
+
+msgctxt "field:sale.promotion.coupon,promotion:"
+msgid "Promotion"
+msgstr ""
+
+msgctxt "field:sale.promotion.coupon.number,active:"
+msgid "Active"
+msgstr ""
+
+msgctxt "field:sale.promotion.coupon.number,coupon:"
+msgid "Coupon"
+msgstr ""
+
+msgctxt "field:sale.promotion.coupon.number,number:"
+msgid "Number"
+msgstr ""
+
+msgctxt "field:sale.sale,coupons:"
+msgid "Coupons"
+msgstr ""
+
+msgctxt "field:sale.sale-sale.promotion.coupon.number,number:"
+msgid "Number"
+msgstr ""
+
+msgctxt "field:sale.sale-sale.promotion.coupon.number,sale:"
+msgid "Sale"
+msgstr ""
+
+msgctxt "help:sale.promotion.coupon,number_of_use:"
+msgid ""
+"How much times a coupon number can be used.\n"
+"0 or below for no limit."
+msgstr ""
+
+msgctxt "help:sale.promotion.coupon,per_party:"
+msgid "Check to count usage per party."
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_duplicate_numbers"
+msgid "The coupons numbered \"%(numbers)s\" are duplicated."
+msgstr ""
+
+msgctxt "model:sale.promotion.coupon,name:"
+msgid "Promotion Coupon"
+msgstr ""
+
+msgctxt "model:sale.promotion.coupon.number,name:"
+msgid "Promotion Coupon Number"
+msgstr ""
+
+msgctxt "model:sale.sale-sale.promotion.coupon.number,name:"
+msgid "Sale - Promotion Coupon Number"
+msgstr ""
diff --git a/modules/sale_promotion_coupon/locale/fr.po b/modules/sale_promotion_coupon/locale/fr.po
new file mode 100644
index 0000000000..8d2ae98934
--- /dev/null
+++ b/modules/sale_promotion_coupon/locale/fr.po
@@ -0,0 +1,79 @@
+#
+msgid ""
+msgstr "Content-Type: text/plain; charset=utf-8\n"
+
+msgctxt "field:sale.promotion,coupons:"
+msgid "Coupons"
+msgstr "Coupons"
+
+msgctxt "field:sale.promotion.coupon,name:"
+msgid "Name"
+msgstr "Nom"
+
+msgctxt "field:sale.promotion.coupon,number_of_use:"
+msgid "Number of Use"
+msgstr "Nombre d'utilisation"
+
+msgctxt "field:sale.promotion.coupon,numbers:"
+msgid "Numbers"
+msgstr "Numéros"
+
+msgctxt "field:sale.promotion.coupon,per_party:"
+msgid "Per Party"
+msgstr "Par tiers"
+
+msgctxt "field:sale.promotion.coupon,promotion:"
+msgid "Promotion"
+msgstr "Promotion"
+
+msgctxt "field:sale.promotion.coupon.number,active:"
+msgid "Active"
+msgstr "Actif"
+
+msgctxt "field:sale.promotion.coupon.number,coupon:"
+msgid "Coupon"
+msgstr "Coupon"
+
+msgctxt "field:sale.promotion.coupon.number,number:"
+msgid "Number"
+msgstr "Numéro"
+
+msgctxt "field:sale.sale,coupons:"
+msgid "Coupons"
+msgstr "Coupons"
+
+msgctxt "field:sale.sale-sale.promotion.coupon.number,number:"
+msgid "Number"
+msgstr "Numéro"
+
+msgctxt "field:sale.sale-sale.promotion.coupon.number,sale:"
+msgid "Sale"
+msgstr "Vente"
+
+msgctxt "help:sale.promotion.coupon,number_of_use:"
+msgid ""
+"How much times a coupon number can be used.\n"
+"0 or below for no limit."
+msgstr ""
+"Combien de fois un numéro de coupon peut être utilisé.\n"
+"0 ou moins pour aucune limite."
+
+msgctxt "help:sale.promotion.coupon,per_party:"
+msgid "Check to count usage per party."
+msgstr "Cocher pour compter l'utilisation par tiers."
+
+msgctxt "model:ir.message,text:msg_duplicate_numbers"
+msgid "The coupons numbered \"%(numbers)s\" are duplicated."
+msgstr "Les coupons numérotés « %(numbers)s » sont en double."
+
+msgctxt "model:sale.promotion.coupon,name:"
+msgid "Promotion Coupon"
+msgstr "Coupon de promotion"
+
+msgctxt "model:sale.promotion.coupon.number,name:"
+msgid "Promotion Coupon Number"
+msgstr "Numéro de coupon de promotion"
+
+msgctxt "model:sale.sale-sale.promotion.coupon.number,name:"
+msgid "Sale - Promotion Coupon Number"
+msgstr "Vente - Numéro de coupon de promotion"
diff --git a/modules/sale_promotion_coupon/locale/hu.po b/modules/sale_promotion_coupon/locale/hu.po
new file mode 100644
index 0000000000..604b66d841
--- /dev/null
+++ b/modules/sale_promotion_coupon/locale/hu.po
@@ -0,0 +1,77 @@
+#
+msgid ""
+msgstr "Content-Type: text/plain; charset=utf-8\n"
+
+msgctxt "field:sale.promotion,coupons:"
+msgid "Coupons"
+msgstr ""
+
+msgctxt "field:sale.promotion.coupon,name:"
+msgid "Name"
+msgstr ""
+
+msgctxt "field:sale.promotion.coupon,number_of_use:"
+msgid "Number of Use"
+msgstr ""
+
+msgctxt "field:sale.promotion.coupon,numbers:"
+msgid "Numbers"
+msgstr ""
+
+msgctxt "field:sale.promotion.coupon,per_party:"
+msgid "Per Party"
+msgstr ""
+
+msgctxt "field:sale.promotion.coupon,promotion:"
+msgid "Promotion"
+msgstr ""
+
+msgctxt "field:sale.promotion.coupon.number,active:"
+msgid "Active"
+msgstr ""
+
+msgctxt "field:sale.promotion.coupon.number,coupon:"
+msgid "Coupon"
+msgstr ""
+
+msgctxt "field:sale.promotion.coupon.number,number:"
+msgid "Number"
+msgstr ""
+
+msgctxt "field:sale.sale,coupons:"
+msgid "Coupons"
+msgstr ""
+
+msgctxt "field:sale.sale-sale.promotion.coupon.number,number:"
+msgid "Number"
+msgstr ""
+
+msgctxt "field:sale.sale-sale.promotion.coupon.number,sale:"
+msgid "Sale"
+msgstr ""
+
+msgctxt "help:sale.promotion.coupon,number_of_use:"
+msgid ""
+"How much times a coupon number can be used.\n"
+"0 or below for no limit."
+msgstr ""
+
+msgctxt "help:sale.promotion.coupon,per_party:"
+msgid "Check to count usage per party."
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_duplicate_numbers"
+msgid "The coupons numbered \"%(numbers)s\" are duplicated."
+msgstr ""
+
+msgctxt "model:sale.promotion.coupon,name:"
+msgid "Promotion Coupon"
+msgstr ""
+
+msgctxt "model:sale.promotion.coupon.number,name:"
+msgid "Promotion Coupon Number"
+msgstr ""
+
+msgctxt "model:sale.sale-sale.promotion.coupon.number,name:"
+msgid "Sale - Promotion Coupon Number"
+msgstr ""
diff --git a/modules/sale_promotion_coupon/locale/id.po b/modules/sale_promotion_coupon/locale/id.po
new file mode 100644
index 0000000000..e0ab6ab2a1
--- /dev/null
+++ b/modules/sale_promotion_coupon/locale/id.po
@@ -0,0 +1,79 @@
+#
+msgid ""
+msgstr "Content-Type: text/plain; charset=utf-8\n"
+
+msgctxt "field:sale.promotion,coupons:"
+msgid "Coupons"
+msgstr ""
+
+msgctxt "field:sale.promotion.coupon,name:"
+msgid "Name"
+msgstr "Nama"
+
+msgctxt "field:sale.promotion.coupon,number_of_use:"
+msgid "Number of Use"
+msgstr ""
+
+msgctxt "field:sale.promotion.coupon,numbers:"
+msgid "Numbers"
+msgstr ""
+
+msgctxt "field:sale.promotion.coupon,per_party:"
+msgid "Per Party"
+msgstr ""
+
+msgctxt "field:sale.promotion.coupon,promotion:"
+msgid "Promotion"
+msgstr ""
+
+msgctxt "field:sale.promotion.coupon.number,active:"
+msgid "Active"
+msgstr "Aktif"
+
+msgctxt "field:sale.promotion.coupon.number,coupon:"
+msgid "Coupon"
+msgstr ""
+
+msgctxt "field:sale.promotion.coupon.number,number:"
+msgid "Number"
+msgstr "Nomor"
+
+msgctxt "field:sale.sale,coupons:"
+msgid "Coupons"
+msgstr "Kupon"
+
+msgctxt "field:sale.sale-sale.promotion.coupon.number,number:"
+msgid "Number"
+msgstr "Nomor"
+
+msgctxt "field:sale.sale-sale.promotion.coupon.number,sale:"
+msgid "Sale"
+msgstr "Penjualan"
+
+msgctxt "help:sale.promotion.coupon,number_of_use:"
+msgid ""
+"How much times a coupon number can be used.\n"
+"0 or below for no limit."
+msgstr ""
+"Berapa kali nomor kupondapat digunakan.\n"
+"0 atau di bawahnya untuk tanpa batas."
+
+msgctxt "help:sale.promotion.coupon,per_party:"
+msgid "Check to count usage per party."
+msgstr "Periksa untuk menghitung penggunaan per pihak."
+
+msgctxt "model:ir.message,text:msg_duplicate_numbers"
+msgid "The coupons numbered \"%(numbers)s\" are duplicated."
+msgstr "Kupon bernomor \"%(numbers)s\" digandakan."
+
+msgctxt "model:sale.promotion.coupon,name:"
+msgid "Promotion Coupon"
+msgstr "Kupon Promosi"
+
+msgctxt "model:sale.promotion.coupon.number,name:"
+msgid "Promotion Coupon Number"
+msgstr "Nomor Kupon Promosi"
+
+msgctxt "model:sale.sale-sale.promotion.coupon.number,name:"
+msgid "Sale - Promotion Coupon Number"
+msgstr "Penjualan - Nomor Kupon Promosi"
diff --git a/modules/sale_promotion_coupon/locale/it.po b/modules/sale_promotion_coupon/locale/it.po
new file mode 100644
index 0000000000..9a383a4c19
--- /dev/null
+++ b/modules/sale_promotion_coupon/locale/it.po
@@ -0,0 +1,77 @@
+#
+msgid ""
+msgstr "Content-Type: text/plain; charset=utf-8\n"
+
+msgctxt "field:sale.promotion,coupons:"
+msgid "Coupons"
+msgstr ""
+
+msgctxt "field:sale.promotion.coupon,name:"
+msgid "Name"
+msgstr "Nome"
+
+msgctxt "field:sale.promotion.coupon,number_of_use:"
+msgid "Number of Use"
+msgstr ""
+
+msgctxt "field:sale.promotion.coupon,numbers:"
+msgid "Numbers"
+msgstr ""
+
+msgctxt "field:sale.promotion.coupon,per_party:"
+msgid "Per Party"
+msgstr ""
+
+msgctxt "field:sale.promotion.coupon,promotion:"
+msgid "Promotion"
+msgstr ""
+
+msgctxt "field:sale.promotion.coupon.number,active:"
+msgid "Active"
+msgstr ""
+
+msgctxt "field:sale.promotion.coupon.number,coupon:"
+msgid "Coupon"
+msgstr ""
+
+msgctxt "field:sale.promotion.coupon.number,number:"
+msgid "Number"
+msgstr "Numero"
+
+msgctxt "field:sale.sale,coupons:"
+msgid "Coupons"
+msgstr ""
+
+msgctxt "field:sale.sale-sale.promotion.coupon.number,number:"
+msgid "Number"
+msgstr "Numero"
+
+msgctxt "field:sale.sale-sale.promotion.coupon.number,sale:"
+msgid "Sale"
+msgstr ""
+
+msgctxt "help:sale.promotion.coupon,number_of_use:"
+msgid ""
+"How much times a coupon number can be used.\n"
+"0 or below for no limit."
+msgstr ""
+
+msgctxt "help:sale.promotion.coupon,per_party:"
+msgid "Check to count usage per party."
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_duplicate_numbers"
+msgid "The coupons numbered \"%(numbers)s\" are duplicated."
+msgstr ""
+
+msgctxt "model:sale.promotion.coupon,name:"
+msgid "Promotion Coupon"
+msgstr ""
+
+msgctxt "model:sale.promotion.coupon.number,name:"
+msgid "Promotion Coupon Number"
+msgstr ""
+
+msgctxt "model:sale.sale-sale.promotion.coupon.number,name:"
+msgid "Sale - Promotion Coupon Number"
+msgstr ""
diff --git a/modules/sale_promotion_coupon/locale/lo.po b/modules/sale_promotion_coupon/locale/lo.po
new file mode 100644
index 0000000000..604b66d841
--- /dev/null
+++ b/modules/sale_promotion_coupon/locale/lo.po
@@ -0,0 +1,77 @@
+#
+msgid ""
+msgstr "Content-Type: text/plain; charset=utf-8\n"
+
+msgctxt "field:sale.promotion,coupons:"
+msgid "Coupons"
+msgstr ""
+
+msgctxt "field:sale.promotion.coupon,name:"
+msgid "Name"
+msgstr ""
+
+msgctxt "field:sale.promotion.coupon,number_of_use:"
+msgid "Number of Use"
+msgstr ""
+
+msgctxt "field:sale.promotion.coupon,numbers:"
+msgid "Numbers"
+msgstr ""
+
+msgctxt "field:sale.promotion.coupon,per_party:"
+msgid "Per Party"
+msgstr ""
+
+msgctxt "field:sale.promotion.coupon,promotion:"
+msgid "Promotion"
+msgstr ""
+
+msgctxt "field:sale.promotion.coupon.number,active:"
+msgid "Active"
+msgstr ""
+
+msgctxt "field:sale.promotion.coupon.number,coupon:"
+msgid "Coupon"
+msgstr ""
+
+msgctxt "field:sale.promotion.coupon.number,number:"
+msgid "Number"
+msgstr ""
+
+msgctxt "field:sale.sale,coupons:"
+msgid "Coupons"
+msgstr ""
+
+msgctxt "field:sale.sale-sale.promotion.coupon.number,number:"
+msgid "Number"
+msgstr ""
+
+msgctxt "field:sale.sale-sale.promotion.coupon.number,sale:"
+msgid "Sale"
+msgstr ""
+
+msgctxt "help:sale.promotion.coupon,number_of_use:"
+msgid ""
+"How much times a coupon number can be used.\n"
+"0 or below for no limit."
+msgstr ""
+
+msgctxt "help:sale.promotion.coupon,per_party:"
+msgid "Check to count usage per party."
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_duplicate_numbers"
+msgid "The coupons numbered \"%(numbers)s\" are duplicated."
+msgstr ""
+
+msgctxt "model:sale.promotion.coupon,name:"
+msgid "Promotion Coupon"
+msgstr ""
+
+msgctxt "model:sale.promotion.coupon.number,name:"
+msgid "Promotion Coupon Number"
+msgstr ""
+
+msgctxt "model:sale.sale-sale.promotion.coupon.number,name:"
+msgid "Sale - Promotion Coupon Number"
+msgstr ""
diff --git a/modules/sale_promotion_coupon/locale/lt.po b/modules/sale_promotion_coupon/locale/lt.po
new file mode 100644
index 0000000000..33c2bdceea
--- /dev/null
+++ b/modules/sale_promotion_coupon/locale/lt.po
@@ -0,0 +1,77 @@
+#
+msgid ""
+msgstr "Content-Type: text/plain; charset=utf-8\n"
+
+msgctxt "field:sale.promotion,coupons:"
+msgid "Coupons"
+msgstr ""
+
+msgctxt "field:sale.promotion.coupon,name:"
+msgid "Name"
+msgstr ""
+
+msgctxt "field:sale.promotion.coupon,number_of_use:"
+msgid "Number of Use"
+msgstr ""
+
+msgctxt "field:sale.promotion.coupon,numbers:"
+msgid "Numbers"
+msgstr ""
+
+msgctxt "field:sale.promotion.coupon,per_party:"
+msgid "Per Party"
+msgstr "Kontrahentui"
+
+msgctxt "field:sale.promotion.coupon,promotion:"
+msgid "Promotion"
+msgstr ""
+
+msgctxt "field:sale.promotion.coupon.number,active:"
+msgid "Active"
+msgstr ""
+
+msgctxt "field:sale.promotion.coupon.number,coupon:"
+msgid "Coupon"
+msgstr ""
+
+msgctxt "field:sale.promotion.coupon.number,number:"
+msgid "Number"
+msgstr ""
+
+msgctxt "field:sale.sale,coupons:"
+msgid "Coupons"
+msgstr ""
+
+msgctxt "field:sale.sale-sale.promotion.coupon.number,number:"
+msgid "Number"
+msgstr ""
+
+msgctxt "field:sale.sale-sale.promotion.coupon.number,sale:"
+msgid "Sale"
+msgstr ""
+
+msgctxt "help:sale.promotion.coupon,number_of_use:"
+msgid ""
+"How much times a coupon number can be used.\n"
+"0 or below for no limit."
+msgstr ""
+
+msgctxt "help:sale.promotion.coupon,per_party:"
+msgid "Check to count usage per party."
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_duplicate_numbers"
+msgid "The coupons numbered \"%(numbers)s\" are duplicated."
+msgstr ""
+
+msgctxt "model:sale.promotion.coupon,name:"
+msgid "Promotion Coupon"
+msgstr ""
+
+msgctxt "model:sale.promotion.coupon.number,name:"
+msgid "Promotion Coupon Number"
+msgstr ""
+
+msgctxt "model:sale.sale-sale.promotion.coupon.number,name:"
+msgid "Sale - Promotion Coupon Number"
+msgstr ""
diff --git a/modules/sale_promotion_coupon/locale/nl.po b/modules/sale_promotion_coupon/locale/nl.po
new file mode 100644
index 0000000000..396458308c
--- /dev/null
+++ b/modules/sale_promotion_coupon/locale/nl.po
@@ -0,0 +1,79 @@
+#
+msgid ""
+msgstr "Content-Type: text/plain; charset=utf-8\n"
+
+msgctxt "field:sale.promotion,coupons:"
+msgid "Coupons"
+msgstr "Bonnen"
+
+msgctxt "field:sale.promotion.coupon,name:"
+msgid "Name"
+msgstr "Naam"
+
+msgctxt "field:sale.promotion.coupon,number_of_use:"
+msgid "Number of Use"
+msgstr "aantal gebruik"
+
+msgctxt "field:sale.promotion.coupon,numbers:"
+msgid "Numbers"
+msgstr "Nummers"
+
+msgctxt "field:sale.promotion.coupon,per_party:"
+msgid "Per Party"
+msgstr "Per relatie"
+
+msgctxt "field:sale.promotion.coupon,promotion:"
+msgid "Promotion"
+msgstr "Promotie"
+
+msgctxt "field:sale.promotion.coupon.number,active:"
+msgid "Active"
+msgstr "Aktief"
+
+msgctxt "field:sale.promotion.coupon.number,coupon:"
+msgid "Coupon"
+msgstr "Bon"
+
+msgctxt "field:sale.promotion.coupon.number,number:"
+msgid "Number"
+msgstr "Nummer"
+
+msgctxt "field:sale.sale,coupons:"
+msgid "Coupons"
+msgstr "Bonnen"
+
+msgctxt "field:sale.sale-sale.promotion.coupon.number,number:"
+msgid "Number"
+msgstr "Nummer"
+
+msgctxt "field:sale.sale-sale.promotion.coupon.number,sale:"
+msgid "Sale"
+msgstr "verkoop"
+
+msgctxt "help:sale.promotion.coupon,number_of_use:"
+msgid ""
+"How much times a coupon number can be used.\n"
+"0 or below for no limit."
+msgstr ""
+"Hoe vaak kan een couponnummer gebruikt worden.\n"
+"0 of lager voor geen limiet."
+
+msgctxt "help:sale.promotion.coupon,per_party:"
+msgid "Check to count usage per party."
+msgstr "Vink aan om het gebruik per relatie te tellen."
+
+msgctxt "model:ir.message,text:msg_duplicate_numbers"
+msgid "The coupons numbered \"%(numbers)s\" are duplicated."
+msgstr "De couponnummers \"%(numbers)s\" zijn gedupliceerd."
+
+msgctxt "model:sale.promotion.coupon,name:"
+msgid "Promotion Coupon"
+msgstr "Promotiecoupon"
+
+msgctxt "model:sale.promotion.coupon.number,name:"
+msgid "Promotion Coupon Number"
+msgstr "Promotie coupon nummer"
+
+msgctxt "model:sale.sale-sale.promotion.coupon.number,name:"
+msgid "Sale - Promotion Coupon Number"
+msgstr "Verkoop - Promotiecouponnummer"
diff --git a/modules/sale_promotion_coupon/locale/pl.po b/modules/sale_promotion_coupon/locale/pl.po
new file mode 100644
index 0000000000..604b66d841
--- /dev/null
+++ b/modules/sale_promotion_coupon/locale/pl.po
@@ -0,0 +1,77 @@
+#
+msgid ""
+msgstr "Content-Type: text/plain; charset=utf-8\n"
+
+msgctxt "field:sale.promotion,coupons:"
+msgid "Coupons"
+msgstr ""
+
+msgctxt "field:sale.promotion.coupon,name:"
+msgid "Name"
+msgstr ""
+
+msgctxt "field:sale.promotion.coupon,number_of_use:"
+msgid "Number of Use"
+msgstr ""
+
+msgctxt "field:sale.promotion.coupon,numbers:"
+msgid "Numbers"
+msgstr ""
+
+msgctxt "field:sale.promotion.coupon,per_party:"
+msgid "Per Party"
+msgstr ""
+
+msgctxt "field:sale.promotion.coupon,promotion:"
+msgid "Promotion"
+msgstr ""
+
+msgctxt "field:sale.promotion.coupon.number,active:"
+msgid "Active"
+msgstr ""
+
+msgctxt "field:sale.promotion.coupon.number,coupon:"
+msgid "Coupon"
+msgstr ""
+
+msgctxt "field:sale.promotion.coupon.number,number:"
+msgid "Number"
+msgstr ""
+
+msgctxt "field:sale.sale,coupons:"
+msgid "Coupons"
+msgstr ""
+
+msgctxt "field:sale.sale-sale.promotion.coupon.number,number:"
+msgid "Number"
+msgstr ""
+
+msgctxt "field:sale.sale-sale.promotion.coupon.number,sale:"
+msgid "Sale"
+msgstr ""
+
+msgctxt "help:sale.promotion.coupon,number_of_use:"
+msgid ""
+"How much times a coupon number can be used.\n"
+"0 or below for no limit."
+msgstr ""
+
+msgctxt "help:sale.promotion.coupon,per_party:"
+msgid "Check to count usage per party."
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_duplicate_numbers"
+msgid "The coupons numbered \"%(numbers)s\" are duplicated."
+msgstr ""
+
+msgctxt "model:sale.promotion.coupon,name:"
+msgid "Promotion Coupon"
+msgstr ""
+
+msgctxt "model:sale.promotion.coupon.number,name:"
+msgid "Promotion Coupon Number"
+msgstr ""
+
+msgctxt "model:sale.sale-sale.promotion.coupon.number,name:"
+msgid "Sale - Promotion Coupon Number"
+msgstr ""
diff --git a/modules/sale_promotion_coupon/locale/pt.po b/modules/sale_promotion_coupon/locale/pt.po
new file mode 100644
index 0000000000..604b66d841
--- /dev/null
+++ b/modules/sale_promotion_coupon/locale/pt.po
@@ -0,0 +1,77 @@
+#
+msgid ""
+msgstr "Content-Type: text/plain; charset=utf-8\n"
+
+msgctxt "field:sale.promotion,coupons:"
+msgid "Coupons"
+msgstr ""
+
+msgctxt "field:sale.promotion.coupon,name:"
+msgid "Name"
+msgstr ""
+
+msgctxt "field:sale.promotion.coupon,number_of_use:"
+msgid "Number of Use"
+msgstr ""
+
+msgctxt "field:sale.promotion.coupon,numbers:"
+msgid "Numbers"
+msgstr ""
+
+msgctxt "field:sale.promotion.coupon,per_party:"
+msgid "Per Party"
+msgstr ""
+
+msgctxt "field:sale.promotion.coupon,promotion:"
+msgid "Promotion"
+msgstr ""
+
+msgctxt "field:sale.promotion.coupon.number,active:"
+msgid "Active"
+msgstr ""
+
+msgctxt "field:sale.promotion.coupon.number,coupon:"
+msgid "Coupon"
+msgstr ""
+
+msgctxt "field:sale.promotion.coupon.number,number:"
+msgid "Number"
+msgstr ""
+
+msgctxt "field:sale.sale,coupons:"
+msgid "Coupons"
+msgstr ""
+
+msgctxt "field:sale.sale-sale.promotion.coupon.number,number:"
+msgid "Number"
+msgstr ""
+
+msgctxt "field:sale.sale-sale.promotion.coupon.number,sale:"
+msgid "Sale"
+msgstr ""
+
+msgctxt "help:sale.promotion.coupon,number_of_use:"
+msgid ""
+"How much times a coupon number can be used.\n"
+"0 or below for no limit."
+msgstr ""
+
+msgctxt "help:sale.promotion.coupon,per_party:"
+msgid "Check to count usage per party."
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_duplicate_numbers"
+msgid "The coupons numbered \"%(numbers)s\" are duplicated."
+msgstr ""
+
+msgctxt "model:sale.promotion.coupon,name:"
+msgid "Promotion Coupon"
+msgstr ""
+
+msgctxt "model:sale.promotion.coupon.number,name:"
+msgid "Promotion Coupon Number"
+msgstr ""
+
+msgctxt "model:sale.sale-sale.promotion.coupon.number,name:"
+msgid "Sale - Promotion Coupon Number"
+msgstr ""
diff --git a/modules/sale_promotion_coupon/locale/ro.po b/modules/sale_promotion_coupon/locale/ro.po
new file mode 100644
index 0000000000..604b66d841
--- /dev/null
+++ b/modules/sale_promotion_coupon/locale/ro.po
@@ -0,0 +1,77 @@
+#
+msgid ""
+msgstr "Content-Type: text/plain; charset=utf-8\n"
+
+msgctxt "field:sale.promotion,coupons:"
+msgid "Coupons"
+msgstr ""
+
+msgctxt "field:sale.promotion.coupon,name:"
+msgid "Name"
+msgstr ""
+
+msgctxt "field:sale.promotion.coupon,number_of_use:"
+msgid "Number of Use"
+msgstr ""
+
+msgctxt "field:sale.promotion.coupon,numbers:"
+msgid "Numbers"
+msgstr ""
+
+msgctxt "field:sale.promotion.coupon,per_party:"
+msgid "Per Party"
+msgstr ""
+
+msgctxt "field:sale.promotion.coupon,promotion:"
+msgid "Promotion"
+msgstr ""
+
+msgctxt "field:sale.promotion.coupon.number,active:"
+msgid "Active"
+msgstr ""
+
+msgctxt "field:sale.promotion.coupon.number,coupon:"
+msgid "Coupon"
+msgstr ""
+
+msgctxt "field:sale.promotion.coupon.number,number:"
+msgid "Number"
+msgstr ""
+
+msgctxt "field:sale.sale,coupons:"
+msgid "Coupons"
+msgstr ""
+
+msgctxt "field:sale.sale-sale.promotion.coupon.number,number:"
+msgid "Number"
+msgstr ""
+
+msgctxt "field:sale.sale-sale.promotion.coupon.number,sale:"
+msgid "Sale"
+msgstr ""
+
+msgctxt "help:sale.promotion.coupon,number_of_use:"
+msgid ""
+"How much times a coupon number can be used.\n"
+"0 or below for no limit."
+msgstr ""
+
+msgctxt "help:sale.promotion.coupon,per_party:"
+msgid "Check to count usage per party."
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_duplicate_numbers"
+msgid "The coupons numbered \"%(numbers)s\" are duplicated."
+msgstr ""
+
+msgctxt "model:sale.promotion.coupon,name:"
+msgid "Promotion Coupon"
+msgstr ""
+
+msgctxt "model:sale.promotion.coupon.number,name:"
+msgid "Promotion Coupon Number"
+msgstr ""
+
+msgctxt "model:sale.sale-sale.promotion.coupon.number,name:"
+msgid "Sale - Promotion Coupon Number"
+msgstr ""
diff --git a/modules/sale_promotion_coupon/locale/ru.po b/modules/sale_promotion_coupon/locale/ru.po
new file mode 100644
index 0000000000..604b66d841
--- /dev/null
+++ b/modules/sale_promotion_coupon/locale/ru.po
@@ -0,0 +1,77 @@
+#
+msgid ""
+msgstr "Content-Type: text/plain; charset=utf-8\n"
+
+msgctxt "field:sale.promotion,coupons:"
+msgid "Coupons"
+msgstr ""
+
+msgctxt "field:sale.promotion.coupon,name:"
+msgid "Name"
+msgstr ""
+
+msgctxt "field:sale.promotion.coupon,number_of_use:"
+msgid "Number of Use"
+msgstr ""
+
+msgctxt "field:sale.promotion.coupon,numbers:"
+msgid "Numbers"
+msgstr ""
+
+msgctxt "field:sale.promotion.coupon,per_party:"
+msgid "Per Party"
+msgstr ""
+
+msgctxt "field:sale.promotion.coupon,promotion:"
+msgid "Promotion"
+msgstr ""
+
+msgctxt "field:sale.promotion.coupon.number,active:"
+msgid "Active"
+msgstr ""
+
+msgctxt "field:sale.promotion.coupon.number,coupon:"
+msgid "Coupon"
+msgstr ""
+
+msgctxt "field:sale.promotion.coupon.number,number:"
+msgid "Number"
+msgstr ""
+
+msgctxt "field:sale.sale,coupons:"
+msgid "Coupons"
+msgstr ""
+
+msgctxt "field:sale.sale-sale.promotion.coupon.number,number:"
+msgid "Number"
+msgstr ""
+
+msgctxt "field:sale.sale-sale.promotion.coupon.number,sale:"
+msgid "Sale"
+msgstr ""
+
+msgctxt "help:sale.promotion.coupon,number_of_use:"
+msgid ""
+"How much times a coupon number can be used.\n"
+"0 or below for no limit."
+msgstr ""
+
+msgctxt "help:sale.promotion.coupon,per_party:"
+msgid "Check to count usage per party."
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_duplicate_numbers"
+msgid "The coupons numbered \"%(numbers)s\" are duplicated."
+msgstr ""
+
+msgctxt "model:sale.promotion.coupon,name:"
+msgid "Promotion Coupon"
+msgstr ""
+
+msgctxt "model:sale.promotion.coupon.number,name:"
+msgid "Promotion Coupon Number"
+msgstr ""
+
+msgctxt "model:sale.sale-sale.promotion.coupon.number,name:"
+msgid "Sale - Promotion Coupon Number"
+msgstr ""
diff --git a/modules/sale_promotion_coupon/locale/sl.po b/modules/sale_promotion_coupon/locale/sl.po
new file mode 100644
index 0000000000..604b66d841
--- /dev/null
+++ b/modules/sale_promotion_coupon/locale/sl.po
@@ -0,0 +1,77 @@
+#
+msgid ""
+msgstr "Content-Type: text/plain; charset=utf-8\n"
+
+msgctxt "field:sale.promotion,coupons:"
+msgid "Coupons"
+msgstr ""
+
+msgctxt "field:sale.promotion.coupon,name:"
+msgid "Name"
+msgstr ""
+
+msgctxt "field:sale.promotion.coupon,number_of_use:"
+msgid "Number of Use"
+msgstr ""
+
+msgctxt "field:sale.promotion.coupon,numbers:"
+msgid "Numbers"
+msgstr ""
+
+msgctxt "field:sale.promotion.coupon,per_party:"
+msgid "Per Party"
+msgstr ""
+
+msgctxt "field:sale.promotion.coupon,promotion:"
+msgid "Promotion"
+msgstr ""
+
+msgctxt "field:sale.promotion.coupon.number,active:"
+msgid "Active"
+msgstr ""
+
+msgctxt "field:sale.promotion.coupon.number,coupon:"
+msgid "Coupon"
+msgstr ""
+
+msgctxt "field:sale.promotion.coupon.number,number:"
+msgid "Number"
+msgstr ""
+
+msgctxt "field:sale.sale,coupons:"
+msgid "Coupons"
+msgstr ""
+
+msgctxt "field:sale.sale-sale.promotion.coupon.number,number:"
+msgid "Number"
+msgstr ""
+
+msgctxt "field:sale.sale-sale.promotion.coupon.number,sale:"
+msgid "Sale"
+msgstr ""
+
+msgctxt "help:sale.promotion.coupon,number_of_use:"
+msgid ""
+"How much times a coupon number can be used.\n"
+"0 or below for no limit."
+msgstr ""
+
+msgctxt "help:sale.promotion.coupon,per_party:"
+msgid "Check to count usage per party."
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_duplicate_numbers"
+msgid "The coupons numbered \"%(numbers)s\" are duplicated."
+msgstr ""
+
+msgctxt "model:sale.promotion.coupon,name:"
+msgid "Promotion Coupon"
+msgstr ""
+
+msgctxt "model:sale.promotion.coupon.number,name:"
+msgid "Promotion Coupon Number"
+msgstr ""
+
+msgctxt "model:sale.sale-sale.promotion.coupon.number,name:"
+msgid "Sale - Promotion Coupon Number"
+msgstr ""
diff --git a/modules/sale_promotion_coupon/locale/tr.po b/modules/sale_promotion_coupon/locale/tr.po
new file mode 100644
index 0000000000..604b66d841
--- /dev/null
+++ b/modules/sale_promotion_coupon/locale/tr.po
@@ -0,0 +1,77 @@
+#
+msgid ""
+msgstr "Content-Type: text/plain; charset=utf-8\n"
+
+msgctxt "field:sale.promotion,coupons:"
+msgid "Coupons"
+msgstr ""
+
+msgctxt "field:sale.promotion.coupon,name:"
+msgid "Name"
+msgstr ""
+
+msgctxt "field:sale.promotion.coupon,number_of_use:"
+msgid "Number of Use"
+msgstr ""
+
+msgctxt "field:sale.promotion.coupon,numbers:"
+msgid "Numbers"
+msgstr ""
+
+msgctxt "field:sale.promotion.coupon,per_party:"
+msgid "Per Party"
+msgstr ""
+
+msgctxt "field:sale.promotion.coupon,promotion:"
+msgid "Promotion"
+msgstr ""
+
+msgctxt "field:sale.promotion.coupon.number,active:"
+msgid "Active"
+msgstr ""
+
+msgctxt "field:sale.promotion.coupon.number,coupon:"
+msgid "Coupon"
+msgstr ""
+
+msgctxt "field:sale.promotion.coupon.number,number:"
+msgid "Number"
+msgstr ""
+
+msgctxt "field:sale.sale,coupons:"
+msgid "Coupons"
+msgstr ""
+
+msgctxt "field:sale.sale-sale.promotion.coupon.number,number:"
+msgid "Number"
+msgstr ""
+
+msgctxt "field:sale.sale-sale.promotion.coupon.number,sale:"
+msgid "Sale"
+msgstr ""
+
+msgctxt "help:sale.promotion.coupon,number_of_use:"
+msgid ""
+"How much times a coupon number can be used.\n"
+"0 or below for no limit."
+msgstr ""
+
+msgctxt "help:sale.promotion.coupon,per_party:"
+msgid "Check to count usage per party."
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_duplicate_numbers"
+msgid "The coupons numbered \"%(numbers)s\" are duplicated."
+msgstr ""
+
+msgctxt "model:sale.promotion.coupon,name:"
+msgid "Promotion Coupon"
+msgstr ""
+
+msgctxt "model:sale.promotion.coupon.number,name:"
+msgid "Promotion Coupon Number"
+msgstr ""
+
+msgctxt "model:sale.sale-sale.promotion.coupon.number,name:"
+msgid "Sale - Promotion Coupon Number"
+msgstr ""
diff --git a/modules/sale_promotion_coupon/locale/zh_CN.po b/modules/sale_promotion_coupon/locale/zh_CN.po
new file mode 100644
index 0000000000..604b66d841
--- /dev/null
+++ b/modules/sale_promotion_coupon/locale/zh_CN.po
@@ -0,0 +1,77 @@
+#
+msgid ""
+msgstr "Content-Type: text/plain; charset=utf-8\n"
+
+msgctxt "field:sale.promotion,coupons:"
+msgid "Coupons"
+msgstr ""
+
+msgctxt "field:sale.promotion.coupon,name:"
+msgid "Name"
+msgstr ""
+
+msgctxt "field:sale.promotion.coupon,number_of_use:"
+msgid "Number of Use"
+msgstr ""
+
+msgctxt "field:sale.promotion.coupon,numbers:"
+msgid "Numbers"
+msgstr ""
+
+msgctxt "field:sale.promotion.coupon,per_party:"
+msgid "Per Party"
+msgstr ""
+
+msgctxt "field:sale.promotion.coupon,promotion:"
+msgid "Promotion"
+msgstr ""
+
+msgctxt "field:sale.promotion.coupon.number,active:"
+msgid "Active"
+msgstr ""
+
+msgctxt "field:sale.promotion.coupon.number,coupon:"
+msgid "Coupon"
+msgstr ""
+
+msgctxt "field:sale.promotion.coupon.number,number:"
+msgid "Number"
+msgstr ""
+
+msgctxt "field:sale.sale,coupons:"
+msgid "Coupons"
+msgstr ""
+
+msgctxt "field:sale.sale-sale.promotion.coupon.number,number:"
+msgid "Number"
+msgstr ""
+
+msgctxt "field:sale.sale-sale.promotion.coupon.number,sale:"
+msgid "Sale"
+msgstr ""
+
+msgctxt "help:sale.promotion.coupon,number_of_use:"
+msgid ""
+"How much times a coupon number can be used.\n"
+"0 or below for no limit."
+msgstr ""
+
+msgctxt "help:sale.promotion.coupon,per_party:"
+msgid "Check to count usage per party."
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_duplicate_numbers"
+msgid "The coupons numbered \"%(numbers)s\" are duplicated."
+msgstr ""
+
+msgctxt "model:sale.promotion.coupon,name:"
+msgid "Promotion Coupon"
+msgstr ""
+
+msgctxt "model:sale.promotion.coupon.number,name:"
+msgid "Promotion Coupon Number"
+msgstr ""
+
+msgctxt "model:sale.sale-sale.promotion.coupon.number,name:"
+msgid "Sale - Promotion Coupon Number"
+msgstr ""
diff --git a/modules/sale_promotion_coupon/message.xml b/modules/sale_promotion_coupon/message.xml
new file mode 100644
index 0000000000..040c2432ac
--- /dev/null
+++ b/modules/sale_promotion_coupon/message.xml
@@ -0,0 +1,10 @@
+
+
+
+
+
+ The coupons numbered "%(numbers)s" are duplicated.
+
+
+
diff --git a/modules/sale_promotion_coupon/sale.py b/modules/sale_promotion_coupon/sale.py
new file mode 100644
index 0000000000..ec79127323
--- /dev/null
+++ b/modules/sale_promotion_coupon/sale.py
@@ -0,0 +1,209 @@
+# This file is part of Tryton. The COPYRIGHT file at the top level of
+# this repository contains the full copyright notices and license terms.
+from sql import Literal
+from sql.aggregate import Count
+from sql.conditionals import Case, Coalesce
+
+from trytond.i18n import gettext
+from trytond.model import (
+ ModelSQL, ModelView, Workflow, fields, DeactivableMixin)
+from trytond.pool import PoolMeta, Pool
+from trytond.pyson import Eval
+from trytond.tools import grouped_slice, reduce_ids
+from trytond.transaction import Transaction
+
+from .exceptions import DuplicateError
+
+
+class Promotion(metaclass=PoolMeta):
+ __name__ = 'sale.promotion'
+
+ coupons = fields.One2Many('sale.promotion.coupon', 'promotion', "Coupons")
+
+ def get_pattern(self, sale):
+ pattern = super(Promotion, self).get_pattern(sale)
+ if sale.coupons:
+ pattern['coupons'] = [c.coupon.id for c in sale.coupons]
+ return pattern
+
+ def match(self, pattern):
+ if self.coupons:
+ pattern = pattern.copy()
+ coupons = pattern.pop('coupons', [])
+ if not set(coupons).intersection({c.id for c in self.coupons}):
+ return False
+ return super(Promotion, self).match(pattern)
+
+
+class PromotionCoupon(ModelSQL, ModelView):
+ "Promotion Coupon"
+ __name__ = 'sale.promotion.coupon'
+
+ name = fields.Char("Name", required=True)
+ number_of_use = fields.Integer(
+ "Number of Use", required=True,
+ help="How much times a coupon number can be used.\n"
+ "0 or below for no limit.")
+ per_party = fields.Boolean(
+ "Per Party", help="Check to count usage per party.")
+ numbers = fields.One2Many(
+ 'sale.promotion.coupon.number', 'coupon', "Numbers")
+ promotion = fields.Many2One('sale.promotion', "Promotion", required=True)
+
+ @classmethod
+ def __setup__(cls):
+ super().__setup__()
+ cls.__access__.add('promotion')
+
+ @classmethod
+ def default_number_of_use(cls):
+ return 0
+
+ @classmethod
+ def default_per_party(cls):
+ return False
+
+
+class PromotionCouponNumber(DeactivableMixin, ModelSQL, ModelView):
+ "Promotion Coupon Number"
+ __name__ = 'sale.promotion.coupon.number'
+ _rec_name = 'number'
+
+ number = fields.Char("Number", required=True)
+ coupon = fields.Many2One(
+ 'sale.promotion.coupon', "Coupon", select=True, required=True)
+
+ @classmethod
+ def __setup__(cls):
+ super(PromotionCouponNumber, cls).__setup__()
+ cls.__access__.add('coupon')
+ cls.active = fields.Function(
+ fields.Boolean("Active"), 'get_active', searcher='search_active')
+
+ @classmethod
+ def _active_query(cls):
+ pool = Pool()
+ Coupon = pool.get('sale.promotion.coupon')
+ Sale = pool.get('sale.sale')
+ Sale_Number = pool.get('sale.sale-sale.promotion.coupon.number')
+ table = cls.__table__()
+ coupon = Coupon.__table__()
+ sale = Sale.__table__()
+ sale_number = Sale_Number.__table__()
+ context = Transaction().context
+ party = context.get('party')
+
+ query = (table
+ .join(sale_number, 'LEFT',
+ condition=table.id == sale_number.number)
+ .join(coupon, condition=table.coupon == coupon.id))
+
+ if party:
+ query = query.join(sale, 'LEFT',
+ condition=(sale_number.sale == sale.id)
+ & (sale.party == party))
+ active = Case(
+ ((coupon.number_of_use > 0) & (coupon.per_party),
+ Count(sale.id) < coupon.number_of_use),
+ ((coupon.number_of_use > 0)
+ & ~Coalesce(coupon.per_party, False),
+ Count(sale_number.sale) < coupon.number_of_use),
+ else_=Literal(True))
+ else:
+ active = Case(
+ ((coupon.number_of_use > 0)
+ & ~Coalesce(coupon.per_party, False),
+ Count(sale_number.sale) < coupon.number_of_use),
+ else_=Literal(True))
+
+ query = query.select(
+ group_by=[table.id, coupon.number_of_use, coupon.per_party])
+ return query, table, active
+
+ @classmethod
+ def get_active(cls, numbers, name):
+ cursor = Transaction().connection.cursor()
+
+ query, table, active = cls._active_query()
+ query.columns = [table.id, active]
+
+ result = {}
+ for sub_numbers in grouped_slice(numbers):
+ query.where = reduce_ids(table.id, map(int, sub_numbers))
+ cursor.execute(*query)
+ result.update(dict(cursor))
+ return result
+
+ @classmethod
+ def search_active(cls, name, clause):
+ _, operator, value = clause
+ Operator = fields.SQL_OPERATORS[operator]
+
+ query, table, active = cls._active_query()
+ query.columns = [table.id]
+ query.having = Operator(active, value)
+ return [('id', 'in', query)]
+
+ @classmethod
+ def validate(cls, numbers):
+ super(PromotionCouponNumber, cls).validate(numbers)
+ cls.check_unique(numbers)
+
+ @classmethod
+ def check_unique(cls, numbers):
+ duplicates = []
+ for sub_numbers in grouped_slice(numbers):
+ domain = ['OR']
+ for number in sub_numbers:
+ domain.append([
+ ('number', '=', number.number),
+ ('id', '!=', number.id),
+ ('coupon.promotion.company', '=',
+ number.coupon.promotion.company.id),
+ ])
+ duplicates.extend(cls.search(domain))
+ if duplicates:
+ numbers = ', '.join(n.number for n in duplicates[:5])
+ if len(duplicates) > 5:
+ numbers += '...'
+ raise DuplicateError(
+ gettext('sale_promotion_coupon.msg_duplicate_numbers',
+ numbers=numbers))
+
+
+class Sale(metaclass=PoolMeta):
+ __name__ = 'sale.sale'
+
+ coupons = fields.Many2Many(
+ 'sale.sale-sale.promotion.coupon.number', 'sale', 'number', "Coupons",
+ domain=[
+ ('coupon.promotion.company', '=', Eval('company', -1)),
+ ],
+ context={
+ 'party': Eval('party', -1),
+ },
+ states={
+ 'readonly': Eval('state') != 'draft',
+ },
+ depends=['state', 'company', 'party'])
+
+ @classmethod
+ @ModelView.button
+ @Workflow.transition('cancelled')
+ def cancel(cls, sales):
+ for sale in sales:
+ if sale.coupons:
+ sale.coupons = []
+ cls.save(sales)
+ super(Sale, cls).cancel(sales)
+
+
+class Sale_PromotionCouponNumber(ModelSQL):
+ "Sale - Promotion Coupon Number"
+ __name__ = 'sale.sale-sale.promotion.coupon.number'
+
+ sale = fields.Many2One(
+ 'sale.sale', "Sale", required=True, select=True, ondelete='CASCADE')
+ number = fields.Many2One(
+ 'sale.promotion.coupon.number', "Number",
+ required=True, ondelete='RESTRICT')
diff --git a/modules/sale_promotion_coupon/sale.xml b/modules/sale_promotion_coupon/sale.xml
new file mode 100644
index 0000000000..8ed4bee467
--- /dev/null
+++ b/modules/sale_promotion_coupon/sale.xml
@@ -0,0 +1,40 @@
+
+
+
+
+
+ sale.promotion
+
+ promotion_form
+
+
+
+ sale.promotion.coupon
+ form
+ coupon_form
+
+
+ sale.promotion.coupon
+ tree
+ coupon_list
+
+
+
+ sale.promotion.coupon.number
+ form
+ coupon_number_form
+
+
+ sale.promotion.coupon.number
+ tree
+ coupon_number_list
+
+
+
+ sale.sale
+
+ sale_form
+
+
+
diff --git a/modules/sale_promotion_coupon/setup.py b/modules/sale_promotion_coupon/setup.py
new file mode 100755
index 0000000000..feb6b805b8
--- /dev/null
+++ b/modules/sale_promotion_coupon/setup.py
@@ -0,0 +1,148 @@
+#!/usr/bin/env python3
+# This file is part of Tryton. The COPYRIGHT file at the top level of
+# this repository contains the full copyright notices and license terms.
+
+import re
+import os
+import io
+from configparser import ConfigParser
+from setuptools import setup, find_packages
+
+
+def read(fname):
+ return io.open(
+ os.path.join(os.path.dirname(__file__), fname),
+ 'r', encoding='utf-8').read()
+
+
+def get_require_version(name):
+ if minor_version % 2:
+ require = '%s >= %s.%s.dev0, < %s.%s'
+ else:
+ require = '%s >= %s.%s, < %s.%s'
+ require %= (name, major_version, minor_version,
+ major_version, minor_version + 1)
+ return require
+
+
+config = ConfigParser()
+config.read_file(open(os.path.join(os.path.dirname(__file__), 'tryton.cfg')))
+info = dict(config.items('tryton'))
+for key in ('depends', 'extras_depend', 'xml'):
+ if key in info:
+ info[key] = info[key].strip().splitlines()
+version = info.get('version', '0.0.1')
+major_version, minor_version, _ = version.split('.', 2)
+major_version = int(major_version)
+minor_version = int(minor_version)
+name = 'trytond_sale_promotion_coupon'
+
+download_url = 'http://downloads.tryton.org/%s.%s/' % (
+ major_version, minor_version)
+if minor_version % 2:
+ version = '%s.%s.dev0' % (major_version, minor_version)
+ download_url = (
+ 'hg+http://hg.tryton.org/modules/%s#egg=%s-%s' % (
+ name[8:], name, version))
+local_version = []
+if os.environ.get('CI_JOB_ID'):
+ local_version.append(os.environ['CI_JOB_ID'])
+else:
+ for build in ['CI_BUILD_NUMBER', 'CI_JOB_NUMBER']:
+ if os.environ.get(build):
+ local_version.append(os.environ[build])
+ else:
+ local_version = []
+ break
+if local_version:
+ version += '+' + '.'.join(local_version)
+
+requires = []
+for dep in info.get('depends', []):
+ if not re.match(r'(ir|res)(\W|$)', dep):
+ requires.append(get_require_version('trytond_%s' % dep))
+requires.append(get_require_version('trytond'))
+
+tests_require = [get_require_version('proteus')]
+dependency_links = []
+if minor_version % 2:
+ dependency_links.append(
+ 'https://trydevpi.tryton.org/?local_version='
+ + '.'.join(local_version))
+
+setup(name=name,
+ version=version,
+ description='Tryton module for sale promotion coupon',
+ long_description=read('README.rst'),
+ author='Tryton',
+ author_email='bugs@tryton.org',
+ url='http://www.tryton.org/',
+ download_url=download_url,
+ project_urls={
+ "Bug Tracker": 'https://bugs.tryton.org/',
+ "Documentation": 'https://docs.tryton.org/',
+ "Forum": 'https://www.tryton.org/forum',
+ "Source Code": 'https://hg.tryton.org/modules/sale_promotion_coupon',
+ },
+ keywords='tryton sale promotion coupon',
+ package_dir={'trytond.modules.sale_promotion_coupon': '.'},
+ packages=(
+ ['trytond.modules.sale_promotion_coupon']
+ + ['trytond.modules.sale_promotion_coupon.%s' % p
+ for p in find_packages()]
+ ),
+ package_data={
+ 'trytond.modules.sale_promotion_coupon': (info.get('xml', [])
+ + ['tryton.cfg', 'view/*.xml', 'locale/*.po', '*.fodt',
+ 'icons/*.svg', 'tests/*.rst']),
+ },
+ classifiers=[
+ 'Development Status :: 5 - Production/Stable',
+ 'Environment :: Plugins',
+ 'Framework :: Tryton',
+ 'Intended Audience :: Developers',
+ 'Intended Audience :: Financial and Insurance Industry',
+ 'Intended Audience :: Legal Industry',
+ 'License :: OSI Approved :: '
+ 'GNU General Public License v3 or later (GPLv3+)',
+ 'Natural Language :: Bulgarian',
+ 'Natural Language :: Catalan',
+ 'Natural Language :: Czech',
+ 'Natural Language :: Dutch',
+ 'Natural Language :: English',
+ 'Natural Language :: Finnish',
+ 'Natural Language :: French',
+ 'Natural Language :: German',
+ 'Natural Language :: Hungarian',
+ 'Natural Language :: Indonesian',
+ 'Natural Language :: Italian',
+ 'Natural Language :: Persian',
+ 'Natural Language :: Portuguese (Brazilian)',
+ 'Natural Language :: Romanian',
+ 'Natural Language :: Russian',
+ 'Natural Language :: Slovenian',
+ 'Natural Language :: Spanish',
+ 'Natural Language :: Turkish',
+ 'Operating System :: OS Independent',
+ 'Programming Language :: Python :: 3',
+ 'Programming Language :: Python :: 3.6',
+ 'Programming Language :: Python :: 3.7',
+ 'Programming Language :: Python :: 3.8',
+ 'Programming Language :: Python :: 3.9',
+ 'Programming Language :: Python :: Implementation :: CPython',
+ 'Programming Language :: Python :: Implementation :: PyPy',
+ 'Topic :: Office/Business',
+ ],
+ license='GPL-3',
+ python_requires='>=3.6',
+ install_requires=requires,
+ dependency_links=dependency_links,
+ zip_safe=False,
+ entry_points="""
+ [trytond.modules]
+ sale_promotion_coupon = trytond.modules.sale_promotion_coupon
+ """,
+ test_suite='tests',
+ test_loader='trytond.test_loader:Loader',
+ tests_require=tests_require,
+ )
diff --git a/modules/sale_promotion_coupon/tests/__init__.py b/modules/sale_promotion_coupon/tests/__init__.py
new file mode 100644
index 0000000000..8d58e5d176
--- /dev/null
+++ b/modules/sale_promotion_coupon/tests/__init__.py
@@ -0,0 +1,9 @@
+# This file is part of Tryton. The COPYRIGHT file at the top level of
+# this repository contains the full copyright notices and license terms.
+
+try:
+ from trytond.modules.sale_promotion_coupon.tests.test_sale_promotion_coupon import suite # noqa: E501
+except ImportError:
+ from .test_sale_promotion_coupon import suite
+
+__all__ = ['suite']
diff --git a/modules/sale_promotion_coupon/tests/scenario_sale_promotion_coupon.rst b/modules/sale_promotion_coupon/tests/scenario_sale_promotion_coupon.rst
new file mode 100644
index 0000000000..146b5914f7
--- /dev/null
+++ b/modules/sale_promotion_coupon/tests/scenario_sale_promotion_coupon.rst
@@ -0,0 +1,130 @@
+==============================
+Sale Promotion Coupon Scenario
+==============================
+
+Imports::
+
+ >>> from decimal import Decimal
+ >>> from proteus import Model, Wizard
+ >>> from trytond.tests.tools import activate_modules
+ >>> from trytond.modules.company.tests.tools import create_company, \
+ ... get_company
+ >>> from trytond.modules.account.tests.tools import create_chart, \
+ ... get_accounts
+
+Activate modules::
+
+ >>> config = activate_modules('sale_promotion_coupon')
+
+Create company::
+
+ >>> _ = create_company()
+ >>> company = get_company()
+
+Create chart of accounts::
+
+ >>> _ = create_chart(company)
+ >>> accounts = get_accounts(company)
+ >>> revenue = accounts['revenue']
+
+Create customer::
+
+ >>> Party = Model.get('party.party')
+ >>> customer = Party(name='Customer')
+ >>> customer.save()
+
+Create account category::
+
+ >>> ProductCategory = Model.get('product.category')
+ >>> account_category = ProductCategory(name="Account Category")
+ >>> account_category.accounting = True
+ >>> account_category.account_revenue = revenue
+ >>> account_category.save()
+
+Create products::
+
+ >>> ProductUom = Model.get('product.uom')
+ >>> ProductTemplate = Model.get('product.template')
+ >>> Product = Model.get('product.product')
+ >>> unit, = ProductUom.find([('name', '=', 'Unit')])
+ >>> template = ProductTemplate()
+ >>> template.name = 'Product'
+ >>> template.default_uom = unit
+ >>> template.type = 'goods'
+ >>> template.salable = True
+ >>> template.list_price = Decimal('20')
+ >>> template.account_category = account_category
+ >>> template.save()
+ >>> product, = template.products
+
+Create Promotion with coupon::
+
+ >>> Promotion = Model.get('sale.promotion')
+ >>> promotion = Promotion(name="10%")
+ >>> promotion.formula = '0.9 * unit_price'
+ >>> coupon = promotion.coupons.new(name="Promo")
+ >>> coupon.number_of_use = 0
+ >>> number = coupon.numbers.new(number="CODE10")
+ >>> promotion.save()
+
+Sale without promotion coupon::
+
+ >>> Sale = Model.get('sale.sale')
+ >>> sale = Sale()
+ >>> sale.party = customer
+ >>> sale_line = sale.lines.new()
+ >>> sale_line.product = product
+ >>> sale_line.quantity = 5
+ >>> sale.save()
+ >>> sale.untaxed_amount
+ Decimal('100.00')
+ >>> sale.click('quote')
+ >>> sale.untaxed_amount
+ Decimal('100.00')
+
+Add promotion coupon to the sale::
+
+ >>> sale.click('draft')
+ >>> sale.coupons.extend(sale.coupons.find([('rec_name', '=', 'CODE10')]))
+ >>> len(sale.coupons)
+ 1
+ >>> sale.save()
+ >>> sale.untaxed_amount
+ Decimal('100.00')
+ >>> sale.click('quote')
+ >>> sale.untaxed_amount
+ Decimal('90.00')
+
+Check coupon inactive after usage::
+
+ >>> Number = Model.get('sale.promotion.coupon.number')
+ >>> coupon, = promotion.coupons
+
+ >>> number, = Number.find([('rec_name', '=', 'CODE10')])
+ >>> bool(number.active)
+ True
+
+ >>> with config.set_context(party=customer.id):
+ ... number_party, = Number.find([('rec_name', '=', 'CODE10')])
+ >>> bool(number_party.active)
+ True
+
+ >>> coupon.number_of_use = 1
+ >>> coupon.save()
+ >>> number.reload()
+ >>> bool(number.active)
+ False
+ >>> Number.find([('rec_name', '=', 'CODE10')])
+ []
+ >>> number_party.reload()
+ >>> bool(number_party.active)
+ False
+ >>> with config.set_context(party=customer.id):
+ ... Number.find([('rec_name', '=', 'CODE10')])
+ []
+
+Cancel sale remove the coupons::
+
+ >>> sale.click('cancel')
+ >>> len(sale.coupons)
+ 0
diff --git a/modules/sale_promotion_coupon/tests/test_sale_promotion_coupon.py b/modules/sale_promotion_coupon/tests/test_sale_promotion_coupon.py
new file mode 100644
index 0000000000..3fc3fbc63b
--- /dev/null
+++ b/modules/sale_promotion_coupon/tests/test_sale_promotion_coupon.py
@@ -0,0 +1,28 @@
+# This file is part of Tryton. The COPYRIGHT file at the top level of
+# this repository contains the full copyright notices and license terms.
+
+import unittest
+
+import doctest
+
+from trytond.tests.test_tryton import ModuleTestCase
+from trytond.tests.test_tryton import suite as test_suite
+from trytond.tests.test_tryton import doctest_teardown
+from trytond.tests.test_tryton import doctest_checker
+
+
+class SalePromotionCouponTestCase(ModuleTestCase):
+ 'Test Sale Promotion Coupon module'
+ module = 'sale_promotion_coupon'
+
+
+def suite():
+ suite = test_suite()
+ suite.addTests(unittest.TestLoader().loadTestsFromTestCase(
+ SalePromotionCouponTestCase))
+ suite.addTests(doctest.DocFileSuite(
+ 'scenario_sale_promotion_coupon.rst',
+ tearDown=doctest_teardown, encoding='utf-8',
+ checker=doctest_checker,
+ optionflags=doctest.REPORT_ONLY_FIRST_FAILURE))
+ return suite
diff --git a/modules/sale_promotion_coupon/tox.ini b/modules/sale_promotion_coupon/tox.ini
new file mode 100644
index 0000000000..197496c0cb
--- /dev/null
+++ b/modules/sale_promotion_coupon/tox.ini
@@ -0,0 +1,15 @@
+[tox]
+envlist = {py36,py37,py38,py39}-{sqlite,postgresql},pypy3-{sqlite,postgresql}
+
+[testenv]
+commands = {envpython} setup.py test
+deps =
+ {py36,py37,py38,py39}-postgresql: psycopg2 >= 2.5
+ pypy3-postgresql: psycopg2cffi >= 2.5
+ py36-sqlite: sqlitebck
+setenv =
+ sqlite: TRYTOND_DATABASE_URI={env:SQLITE_URI:sqlite://}
+ postgresql: TRYTOND_DATABASE_URI={env:POSTGRESQL_URI:postgresql://}
+ sqlite: DB_NAME={env:SQLITE_NAME::memory:}
+ postgresql: DB_NAME={env:POSTGRESQL_NAME:test}
+install_command = pip install --pre --find-links https://trydevpi.tryton.org/?local_version={env:CI_JOB_ID:{env:CI_BUILD_NUMBER}.{env:CI_JOB_NUMBER}} {opts} {packages}
diff --git a/modules/sale_promotion_coupon/tryton.cfg b/modules/sale_promotion_coupon/tryton.cfg
new file mode 100644
index 0000000000..256479378e
--- /dev/null
+++ b/modules/sale_promotion_coupon/tryton.cfg
@@ -0,0 +1,9 @@
+[tryton]
+version=6.0.1
+depends:
+ ir
+ sale
+ sale_promotion
+xml:
+ sale.xml
+ message.xml
diff --git a/modules/sale_promotion_coupon/view/coupon_form.xml b/modules/sale_promotion_coupon/view/coupon_form.xml
new file mode 100644
index 0000000000..4bdf45ed98
--- /dev/null
+++ b/modules/sale_promotion_coupon/view/coupon_form.xml
@@ -0,0 +1,14 @@
+
+
+
diff --git a/modules/sale_promotion_coupon/view/coupon_list.xml b/modules/sale_promotion_coupon/view/coupon_list.xml
new file mode 100644
index 0000000000..a793418ae1
--- /dev/null
+++ b/modules/sale_promotion_coupon/view/coupon_list.xml
@@ -0,0 +1,9 @@
+
+
+
+
+
+
+
+
diff --git a/modules/sale_promotion_coupon/view/coupon_number_form.xml b/modules/sale_promotion_coupon/view/coupon_number_form.xml
new file mode 100644
index 0000000000..554b129bb2
--- /dev/null
+++ b/modules/sale_promotion_coupon/view/coupon_number_form.xml
@@ -0,0 +1,11 @@
+
+
+
diff --git a/modules/sale_promotion_coupon/view/coupon_number_list.xml b/modules/sale_promotion_coupon/view/coupon_number_list.xml
new file mode 100644
index 0000000000..bfcaf77d9c
--- /dev/null
+++ b/modules/sale_promotion_coupon/view/coupon_number_list.xml
@@ -0,0 +1,7 @@
+
+
+
+
+
+
diff --git a/modules/sale_promotion_coupon/view/promotion_form.xml b/modules/sale_promotion_coupon/view/promotion_form.xml
new file mode 100644
index 0000000000..1310dad85a
--- /dev/null
+++ b/modules/sale_promotion_coupon/view/promotion_form.xml
@@ -0,0 +1,8 @@
+
+
+
+
+
+
+
diff --git a/modules/sale_promotion_coupon/view/sale_form.xml b/modules/sale_promotion_coupon/view/sale_form.xml
new file mode 100644
index 0000000000..63aab17399
--- /dev/null
+++ b/modules/sale_promotion_coupon/view/sale_form.xml
@@ -0,0 +1,10 @@
+
+
+
+
+
+
+
+
+
diff --git a/modules/sale_secondary_unit/.drone.yml b/modules/sale_secondary_unit/.drone.yml
new file mode 100644
index 0000000000..2049d30a49
--- /dev/null
+++ b/modules/sale_secondary_unit/.drone.yml
@@ -0,0 +1,68 @@
+clone:
+ hg:
+ image: plugins/hg
+ environment:
+ - HG_SHARE_POOL=/root/.cache/hg
+ volumes:
+ - cache:/root/.cache
+
+pipeline:
+ tox:
+ image: ${IMAGE}
+ environment:
+ - CFLAGS=-O0
+ - DB_CACHE=/cache
+ - TOX_TESTENV_PASSENV=CFLAGS DB_CACHE CI_BUILD_NUMBER CI_JOB_NUMBER CI_JOB_ID
+ - POSTGRESQL_URI=postgresql://postgres@postgresql:5432/
+ commands:
+ - echo "[extensions]" >> /root/.hgrc
+ - echo "hgext.share =" >> /root/.hgrc
+ - echo "[share]" >> /root/.hgrc
+ - echo "pool = /root/.cache/hg" >> /root/.hgrc
+ - pip install tox
+ - tox -e "${TOXENV}-${DATABASE}"
+ volumes:
+ - cache:/root/.cache
+ check_dist:
+ image: ${IMAGE}
+ commands:
+ - pip install twine
+ - python setup.py sdist
+ - twine check dist/*
+
+services:
+ postgresql:
+ image: postgres
+ environment:
+ - POSTGRES_HOST_AUTH_METHOD=trust
+ command: "-c fsync=off -c synchronous_commit=off -c full_page_writes=off"
+ when:
+ matrix:
+ DATABASE: postgresql
+
+matrix:
+ include:
+ - IMAGE: python:3.6
+ TOXENV: py36
+ DATABASE: sqlite
+ - IMAGE: python:3.6
+ TOXENV: py36
+ DATABASE: postgresql
+ - IMAGE: python:3.7
+ TOXENV: py37
+ DATABASE: sqlite
+ - IMAGE: python:3.7
+ TOXENV: py37
+ DATABASE: postgresql
+ - IMAGE: python:3.8
+ TOXENV: py38
+ DATABASE: sqlite
+ - IMAGE: python:3.8
+ TOXENV: py38
+ DATABASE: postgresql
+ - IMAGE: python:3.9
+ TOXENV: py39
+ DATABASE: sqlite
+ - IMAGE: python:3.9
+ TOXENV: py39
+ DATABASE: postgresql
diff --git a/modules/sale_secondary_unit/.flake8 b/modules/sale_secondary_unit/.flake8
new file mode 100644
index 0000000000..fa6b4f66d1
--- /dev/null
+++ b/modules/sale_secondary_unit/.flake8
@@ -0,0 +1,2 @@
+[flake8]
+ignore=E123,E124,E126,E128,E741,W503
diff --git a/modules/sale_secondary_unit/CHANGELOG b/modules/sale_secondary_unit/CHANGELOG
new file mode 100644
index 0000000000..aa4a76f66d
--- /dev/null
+++ b/modules/sale_secondary_unit/CHANGELOG
@@ -0,0 +1,12 @@
+Version 6.0.0 - 2021-05-03
+* Bug fixes (see mercurial logs for details)
+
+Version 5.8.0 - 2020-11-02
+* Bug fixes (see mercurial logs for details)
+* Remove support for Python 3.5
+
+Version 5.6.0 - 2020-05-04
+* Bug fixes (see mercurial logs for details)
+
+Version 5.4.0 - 2019-11-04
+* Initial release
diff --git a/modules/sale_secondary_unit/COPYRIGHT b/modules/sale_secondary_unit/COPYRIGHT
new file mode 100644
index 0000000000..4721946c3e
--- /dev/null
+++ b/modules/sale_secondary_unit/COPYRIGHT
@@ -0,0 +1,15 @@
+Copyright (C) 2019-2021 Cédric Krier
+Copyright (C) 2019-2021 B2CK
+
+This program is free software: you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation, either version 3 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program. If not, see .
diff --git a/modules/sale_secondary_unit/LICENSE b/modules/sale_secondary_unit/LICENSE
new file mode 100644
index 0000000000..94a9ed024d
--- /dev/null
+++ b/modules/sale_secondary_unit/LICENSE
@@ -0,0 +1,674 @@
+ GNU GENERAL PUBLIC LICENSE
+ Version 3, 29 June 2007
+
+ Copyright (C) 2007 Free Software Foundation, Inc.
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+ Preamble
+
+ The GNU General Public License is a free, copyleft license for
+software and other kinds of works.
+
+ The licenses for most software and other practical works are designed
+to take away your freedom to share and change the works. By contrast,
+the GNU General Public License is intended to guarantee your freedom to
+share and change all versions of a program--to make sure it remains free
+software for all its users. We, the Free Software Foundation, use the
+GNU General Public License for most of our software; it applies also to
+any other work released this way by its authors. You can apply it to
+your programs, too.
+
+ When we speak of free software, we are referring to freedom, not
+price. Our General Public Licenses are designed to make sure that you
+have the freedom to distribute copies of free software (and charge for
+them if you wish), that you receive source code or can get it if you
+want it, that you can change the software or use pieces of it in new
+free programs, and that you know you can do these things.
+
+ To protect your rights, we need to prevent others from denying you
+these rights or asking you to surrender the rights. Therefore, you have
+certain responsibilities if you distribute copies of the software, or if
+you modify it: responsibilities to respect the freedom of others.
+
+ For example, if you distribute copies of such a program, whether
+gratis or for a fee, you must pass on to the recipients the same
+freedoms that you received. You must make sure that they, too, receive
+or can get the source code. And you must show them these terms so they
+know their rights.
+
+ Developers that use the GNU GPL protect your rights with two steps:
+(1) assert copyright on the software, and (2) offer you this License
+giving you legal permission to copy, distribute and/or modify it.
+
+ For the developers' and authors' protection, the GPL clearly explains
+that there is no warranty for this free software. For both users' and
+authors' sake, the GPL requires that modified versions be marked as
+changed, so that their problems will not be attributed erroneously to
+authors of previous versions.
+
+ Some devices are designed to deny users access to install or run
+modified versions of the software inside them, although the manufacturer
+can do so. This is fundamentally incompatible with the aim of
+protecting users' freedom to change the software. The systematic
+pattern of such abuse occurs in the area of products for individuals to
+use, which is precisely where it is most unacceptable. Therefore, we
+have designed this version of the GPL to prohibit the practice for those
+products. If such problems arise substantially in other domains, we
+stand ready to extend this provision to those domains in future versions
+of the GPL, as needed to protect the freedom of users.
+
+ Finally, every program is threatened constantly by software patents.
+States should not allow patents to restrict development and use of
+software on general-purpose computers, but in those that do, we wish to
+avoid the special danger that patents applied to a free program could
+make it effectively proprietary. To prevent this, the GPL assures that
+patents cannot be used to render the program non-free.
+
+ The precise terms and conditions for copying, distribution and
+modification follow.
+
+ TERMS AND CONDITIONS
+
+ 0. Definitions.
+
+ "This License" refers to version 3 of the GNU General Public License.
+
+ "Copyright" also means copyright-like laws that apply to other kinds of
+works, such as semiconductor masks.
+
+ "The Program" refers to any copyrightable work licensed under this
+License. Each licensee is addressed as "you". "Licensees" and
+"recipients" may be individuals or organizations.
+
+ To "modify" a work means to copy from or adapt all or part of the work
+in a fashion requiring copyright permission, other than the making of an
+exact copy. The resulting work is called a "modified version" of the
+earlier work or a work "based on" the earlier work.
+
+ A "covered work" means either the unmodified Program or a work based
+on the Program.
+
+ To "propagate" a work means to do anything with it that, without
+permission, would make you directly or secondarily liable for
+infringement under applicable copyright law, except executing it on a
+computer or modifying a private copy. Propagation includes copying,
+distribution (with or without modification), making available to the
+public, and in some countries other activities as well.
+
+ To "convey" a work means any kind of propagation that enables other
+parties to make or receive copies. Mere interaction with a user through
+a computer network, with no transfer of a copy, is not conveying.
+
+ An interactive user interface displays "Appropriate Legal Notices"
+to the extent that it includes a convenient and prominently visible
+feature that (1) displays an appropriate copyright notice, and (2)
+tells the user that there is no warranty for the work (except to the
+extent that warranties are provided), that licensees may convey the
+work under this License, and how to view a copy of this License. If
+the interface presents a list of user commands or options, such as a
+menu, a prominent item in the list meets this criterion.
+
+ 1. Source Code.
+
+ The "source code" for a work means the preferred form of the work
+for making modifications to it. "Object code" means any non-source
+form of a work.
+
+ A "Standard Interface" means an interface that either is an official
+standard defined by a recognized standards body, or, in the case of
+interfaces specified for a particular programming language, one that
+is widely used among developers working in that language.
+
+ The "System Libraries" of an executable work include anything, other
+than the work as a whole, that (a) is included in the normal form of
+packaging a Major Component, but which is not part of that Major
+Component, and (b) serves only to enable use of the work with that
+Major Component, or to implement a Standard Interface for which an
+implementation is available to the public in source code form. A
+"Major Component", in this context, means a major essential component
+(kernel, window system, and so on) of the specific operating system
+(if any) on which the executable work runs, or a compiler used to
+produce the work, or an object code interpreter used to run it.
+
+ The "Corresponding Source" for a work in object code form means all
+the source code needed to generate, install, and (for an executable
+work) run the object code and to modify the work, including scripts to
+control those activities. However, it does not include the work's
+System Libraries, or general-purpose tools or generally available free
+programs which are used unmodified in performing those activities but
+which are not part of the work. For example, Corresponding Source
+includes interface definition files associated with source files for
+the work, and the source code for shared libraries and dynamically
+linked subprograms that the work is specifically designed to require,
+such as by intimate data communication or control flow between those
+subprograms and other parts of the work.
+
+ The Corresponding Source need not include anything that users
+can regenerate automatically from other parts of the Corresponding
+Source.
+
+ The Corresponding Source for a work in source code form is that
+same work.
+
+ 2. Basic Permissions.
+
+ All rights granted under this License are granted for the term of
+copyright on the Program, and are irrevocable provided the stated
+conditions are met. This License explicitly affirms your unlimited
+permission to run the unmodified Program. The output from running a
+covered work is covered by this License only if the output, given its
+content, constitutes a covered work. This License acknowledges your
+rights of fair use or other equivalent, as provided by copyright law.
+
+ You may make, run and propagate covered works that you do not
+convey, without conditions so long as your license otherwise remains
+in force. You may convey covered works to others for the sole purpose
+of having them make modifications exclusively for you, or provide you
+with facilities for running those works, provided that you comply with
+the terms of this License in conveying all material for which you do
+not control copyright. Those thus making or running the covered works
+for you must do so exclusively on your behalf, under your direction
+and control, on terms that prohibit them from making any copies of
+your copyrighted material outside their relationship with you.
+
+ Conveying under any other circumstances is permitted solely under
+the conditions stated below. Sublicensing is not allowed; section 10
+makes it unnecessary.
+
+ 3. Protecting Users' Legal Rights From Anti-Circumvention Law.
+
+ No covered work shall be deemed part of an effective technological
+measure under any applicable law fulfilling obligations under article
+11 of the WIPO copyright treaty adopted on 20 December 1996, or
+similar laws prohibiting or restricting circumvention of such
+measures.
+
+ When you convey a covered work, you waive any legal power to forbid
+circumvention of technological measures to the extent such circumvention
+is effected by exercising rights under this License with respect to
+the covered work, and you disclaim any intention to limit operation or
+modification of the work as a means of enforcing, against the work's
+users, your or third parties' legal rights to forbid circumvention of
+technological measures.
+
+ 4. Conveying Verbatim Copies.
+
+ You may convey verbatim copies of the Program's source code as you
+receive it, in any medium, provided that you conspicuously and
+appropriately publish on each copy an appropriate copyright notice;
+keep intact all notices stating that this License and any
+non-permissive terms added in accord with section 7 apply to the code;
+keep intact all notices of the absence of any warranty; and give all
+recipients a copy of this License along with the Program.
+
+ You may charge any price or no price for each copy that you convey,
+and you may offer support or warranty protection for a fee.
+
+ 5. Conveying Modified Source Versions.
+
+ You may convey a work based on the Program, or the modifications to
+produce it from the Program, in the form of source code under the
+terms of section 4, provided that you also meet all of these conditions:
+
+ a) The work must carry prominent notices stating that you modified
+ it, and giving a relevant date.
+
+ b) The work must carry prominent notices stating that it is
+ released under this License and any conditions added under section
+ 7. This requirement modifies the requirement in section 4 to
+ "keep intact all notices".
+
+ c) You must license the entire work, as a whole, under this
+ License to anyone who comes into possession of a copy. This
+ License will therefore apply, along with any applicable section 7
+ additional terms, to the whole of the work, and all its parts,
+ regardless of how they are packaged. This License gives no
+ permission to license the work in any other way, but it does not
+ invalidate such permission if you have separately received it.
+
+ d) If the work has interactive user interfaces, each must display
+ Appropriate Legal Notices; however, if the Program has interactive
+ interfaces that do not display Appropriate Legal Notices, your
+ work need not make them do so.
+
+ A compilation of a covered work with other separate and independent
+works, which are not by their nature extensions of the covered work,
+and which are not combined with it such as to form a larger program,
+in or on a volume of a storage or distribution medium, is called an
+"aggregate" if the compilation and its resulting copyright are not
+used to limit the access or legal rights of the compilation's users
+beyond what the individual works permit. Inclusion of a covered work
+in an aggregate does not cause this License to apply to the other
+parts of the aggregate.
+
+ 6. Conveying Non-Source Forms.
+
+ You may convey a covered work in object code form under the terms
+of sections 4 and 5, provided that you also convey the
+machine-readable Corresponding Source under the terms of this License,
+in one of these ways:
+
+ a) Convey the object code in, or embodied in, a physical product
+ (including a physical distribution medium), accompanied by the
+ Corresponding Source fixed on a durable physical medium
+ customarily used for software interchange.
+
+ b) Convey the object code in, or embodied in, a physical product
+ (including a physical distribution medium), accompanied by a
+ written offer, valid for at least three years and valid for as
+ long as you offer spare parts or customer support for that product
+ model, to give anyone who possesses the object code either (1) a
+ copy of the Corresponding Source for all the software in the
+ product that is covered by this License, on a durable physical
+ medium customarily used for software interchange, for a price no
+ more than your reasonable cost of physically performing this
+ conveying of source, or (2) access to copy the
+ Corresponding Source from a network server at no charge.
+
+ c) Convey individual copies of the object code with a copy of the
+ written offer to provide the Corresponding Source. This
+ alternative is allowed only occasionally and noncommercially, and
+ only if you received the object code with such an offer, in accord
+ with subsection 6b.
+
+ d) Convey the object code by offering access from a designated
+ place (gratis or for a charge), and offer equivalent access to the
+ Corresponding Source in the same way through the same place at no
+ further charge. You need not require recipients to copy the
+ Corresponding Source along with the object code. If the place to
+ copy the object code is a network server, the Corresponding Source
+ may be on a different server (operated by you or a third party)
+ that supports equivalent copying facilities, provided you maintain
+ clear directions next to the object code saying where to find the
+ Corresponding Source. Regardless of what server hosts the
+ Corresponding Source, you remain obligated to ensure that it is
+ available for as long as needed to satisfy these requirements.
+
+ e) Convey the object code using peer-to-peer transmission, provided
+ you inform other peers where the object code and Corresponding
+ Source of the work are being offered to the general public at no
+ charge under subsection 6d.
+
+ A separable portion of the object code, whose source code is excluded
+from the Corresponding Source as a System Library, need not be
+included in conveying the object code work.
+
+ A "User Product" is either (1) a "consumer product", which means any
+tangible personal property which is normally used for personal, family,
+or household purposes, or (2) anything designed or sold for incorporation
+into a dwelling. In determining whether a product is a consumer product,
+doubtful cases shall be resolved in favor of coverage. For a particular
+product received by a particular user, "normally used" refers to a
+typical or common use of that class of product, regardless of the status
+of the particular user or of the way in which the particular user
+actually uses, or expects or is expected to use, the product. A product
+is a consumer product regardless of whether the product has substantial
+commercial, industrial or non-consumer uses, unless such uses represent
+the only significant mode of use of the product.
+
+ "Installation Information" for a User Product means any methods,
+procedures, authorization keys, or other information required to install
+and execute modified versions of a covered work in that User Product from
+a modified version of its Corresponding Source. The information must
+suffice to ensure that the continued functioning of the modified object
+code is in no case prevented or interfered with solely because
+modification has been made.
+
+ If you convey an object code work under this section in, or with, or
+specifically for use in, a User Product, and the conveying occurs as
+part of a transaction in which the right of possession and use of the
+User Product is transferred to the recipient in perpetuity or for a
+fixed term (regardless of how the transaction is characterized), the
+Corresponding Source conveyed under this section must be accompanied
+by the Installation Information. But this requirement does not apply
+if neither you nor any third party retains the ability to install
+modified object code on the User Product (for example, the work has
+been installed in ROM).
+
+ The requirement to provide Installation Information does not include a
+requirement to continue to provide support service, warranty, or updates
+for a work that has been modified or installed by the recipient, or for
+the User Product in which it has been modified or installed. Access to a
+network may be denied when the modification itself materially and
+adversely affects the operation of the network or violates the rules and
+protocols for communication across the network.
+
+ Corresponding Source conveyed, and Installation Information provided,
+in accord with this section must be in a format that is publicly
+documented (and with an implementation available to the public in
+source code form), and must require no special password or key for
+unpacking, reading or copying.
+
+ 7. Additional Terms.
+
+ "Additional permissions" are terms that supplement the terms of this
+License by making exceptions from one or more of its conditions.
+Additional permissions that are applicable to the entire Program shall
+be treated as though they were included in this License, to the extent
+that they are valid under applicable law. If additional permissions
+apply only to part of the Program, that part may be used separately
+under those permissions, but the entire Program remains governed by
+this License without regard to the additional permissions.
+
+ When you convey a copy of a covered work, you may at your option
+remove any additional permissions from that copy, or from any part of
+it. (Additional permissions may be written to require their own
+removal in certain cases when you modify the work.) You may place
+additional permissions on material, added by you to a covered work,
+for which you have or can give appropriate copyright permission.
+
+ Notwithstanding any other provision of this License, for material you
+add to a covered work, you may (if authorized by the copyright holders of
+that material) supplement the terms of this License with terms:
+
+ a) Disclaiming warranty or limiting liability differently from the
+ terms of sections 15 and 16 of this License; or
+
+ b) Requiring preservation of specified reasonable legal notices or
+ author attributions in that material or in the Appropriate Legal
+ Notices displayed by works containing it; or
+
+ c) Prohibiting misrepresentation of the origin of that material, or
+ requiring that modified versions of such material be marked in
+ reasonable ways as different from the original version; or
+
+ d) Limiting the use for publicity purposes of names of licensors or
+ authors of the material; or
+
+ e) Declining to grant rights under trademark law for use of some
+ trade names, trademarks, or service marks; or
+
+ f) Requiring indemnification of licensors and authors of that
+ material by anyone who conveys the material (or modified versions of
+ it) with contractual assumptions of liability to the recipient, for
+ any liability that these contractual assumptions directly impose on
+ those licensors and authors.
+
+ All other non-permissive additional terms are considered "further
+restrictions" within the meaning of section 10. If the Program as you
+received it, or any part of it, contains a notice stating that it is
+governed by this License along with a term that is a further
+restriction, you may remove that term. If a license document contains
+a further restriction but permits relicensing or conveying under this
+License, you may add to a covered work material governed by the terms
+of that license document, provided that the further restriction does
+not survive such relicensing or conveying.
+
+ If you add terms to a covered work in accord with this section, you
+must place, in the relevant source files, a statement of the
+additional terms that apply to those files, or a notice indicating
+where to find the applicable terms.
+
+ Additional terms, permissive or non-permissive, may be stated in the
+form of a separately written license, or stated as exceptions;
+the above requirements apply either way.
+
+ 8. Termination.
+
+ You may not propagate or modify a covered work except as expressly
+provided under this License. Any attempt otherwise to propagate or
+modify it is void, and will automatically terminate your rights under
+this License (including any patent licenses granted under the third
+paragraph of section 11).
+
+ However, if you cease all violation of this License, then your
+license from a particular copyright holder is reinstated (a)
+provisionally, unless and until the copyright holder explicitly and
+finally terminates your license, and (b) permanently, if the copyright
+holder fails to notify you of the violation by some reasonable means
+prior to 60 days after the cessation.
+
+ Moreover, your license from a particular copyright holder is
+reinstated permanently if the copyright holder notifies you of the
+violation by some reasonable means, this is the first time you have
+received notice of violation of this License (for any work) from that
+copyright holder, and you cure the violation prior to 30 days after
+your receipt of the notice.
+
+ Termination of your rights under this section does not terminate the
+licenses of parties who have received copies or rights from you under
+this License. If your rights have been terminated and not permanently
+reinstated, you do not qualify to receive new licenses for the same
+material under section 10.
+
+ 9. Acceptance Not Required for Having Copies.
+
+ You are not required to accept this License in order to receive or
+run a copy of the Program. Ancillary propagation of a covered work
+occurring solely as a consequence of using peer-to-peer transmission
+to receive a copy likewise does not require acceptance. However,
+nothing other than this License grants you permission to propagate or
+modify any covered work. These actions infringe copyright if you do
+not accept this License. Therefore, by modifying or propagating a
+covered work, you indicate your acceptance of this License to do so.
+
+ 10. Automatic Licensing of Downstream Recipients.
+
+ Each time you convey a covered work, the recipient automatically
+receives a license from the original licensors, to run, modify and
+propagate that work, subject to this License. You are not responsible
+for enforcing compliance by third parties with this License.
+
+ An "entity transaction" is a transaction transferring control of an
+organization, or substantially all assets of one, or subdividing an
+organization, or merging organizations. If propagation of a covered
+work results from an entity transaction, each party to that
+transaction who receives a copy of the work also receives whatever
+licenses to the work the party's predecessor in interest had or could
+give under the previous paragraph, plus a right to possession of the
+Corresponding Source of the work from the predecessor in interest, if
+the predecessor has it or can get it with reasonable efforts.
+
+ You may not impose any further restrictions on the exercise of the
+rights granted or affirmed under this License. For example, you may
+not impose a license fee, royalty, or other charge for exercise of
+rights granted under this License, and you may not initiate litigation
+(including a cross-claim or counterclaim in a lawsuit) alleging that
+any patent claim is infringed by making, using, selling, offering for
+sale, or importing the Program or any portion of it.
+
+ 11. Patents.
+
+ A "contributor" is a copyright holder who authorizes use under this
+License of the Program or a work on which the Program is based. The
+work thus licensed is called the contributor's "contributor version".
+
+ A contributor's "essential patent claims" are all patent claims
+owned or controlled by the contributor, whether already acquired or
+hereafter acquired, that would be infringed by some manner, permitted
+by this License, of making, using, or selling its contributor version,
+but do not include claims that would be infringed only as a
+consequence of further modification of the contributor version. For
+purposes of this definition, "control" includes the right to grant
+patent sublicenses in a manner consistent with the requirements of
+this License.
+
+ Each contributor grants you a non-exclusive, worldwide, royalty-free
+patent license under the contributor's essential patent claims, to
+make, use, sell, offer for sale, import and otherwise run, modify and
+propagate the contents of its contributor version.
+
+ In the following three paragraphs, a "patent license" is any express
+agreement or commitment, however denominated, not to enforce a patent
+(such as an express permission to practice a patent or covenant not to
+sue for patent infringement). To "grant" such a patent license to a
+party means to make such an agreement or commitment not to enforce a
+patent against the party.
+
+ If you convey a covered work, knowingly relying on a patent license,
+and the Corresponding Source of the work is not available for anyone
+to copy, free of charge and under the terms of this License, through a
+publicly available network server or other readily accessible means,
+then you must either (1) cause the Corresponding Source to be so
+available, or (2) arrange to deprive yourself of the benefit of the
+patent license for this particular work, or (3) arrange, in a manner
+consistent with the requirements of this License, to extend the patent
+license to downstream recipients. "Knowingly relying" means you have
+actual knowledge that, but for the patent license, your conveying the
+covered work in a country, or your recipient's use of the covered work
+in a country, would infringe one or more identifiable patents in that
+country that you have reason to believe are valid.
+
+ If, pursuant to or in connection with a single transaction or
+arrangement, you convey, or propagate by procuring conveyance of, a
+covered work, and grant a patent license to some of the parties
+receiving the covered work authorizing them to use, propagate, modify
+or convey a specific copy of the covered work, then the patent license
+you grant is automatically extended to all recipients of the covered
+work and works based on it.
+
+ A patent license is "discriminatory" if it does not include within
+the scope of its coverage, prohibits the exercise of, or is
+conditioned on the non-exercise of one or more of the rights that are
+specifically granted under this License. You may not convey a covered
+work if you are a party to an arrangement with a third party that is
+in the business of distributing software, under which you make payment
+to the third party based on the extent of your activity of conveying
+the work, and under which the third party grants, to any of the
+parties who would receive the covered work from you, a discriminatory
+patent license (a) in connection with copies of the covered work
+conveyed by you (or copies made from those copies), or (b) primarily
+for and in connection with specific products or compilations that
+contain the covered work, unless you entered into that arrangement,
+or that patent license was granted, prior to 28 March 2007.
+
+ Nothing in this License shall be construed as excluding or limiting
+any implied license or other defenses to infringement that may
+otherwise be available to you under applicable patent law.
+
+ 12. No Surrender of Others' Freedom.
+
+ If conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License. If you cannot convey a
+covered work so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you may
+not convey it at all. For example, if you agree to terms that obligate you
+to collect a royalty for further conveying from those to whom you convey
+the Program, the only way you could satisfy both those terms and this
+License would be to refrain entirely from conveying the Program.
+
+ 13. Use with the GNU Affero General Public License.
+
+ Notwithstanding any other provision of this License, you have
+permission to link or combine any covered work with a work licensed
+under version 3 of the GNU Affero General Public License into a single
+combined work, and to convey the resulting work. The terms of this
+License will continue to apply to the part which is the covered work,
+but the special requirements of the GNU Affero General Public License,
+section 13, concerning interaction through a network will apply to the
+combination as such.
+
+ 14. Revised Versions of this License.
+
+ The Free Software Foundation may publish revised and/or new versions of
+the GNU General Public License from time to time. Such new versions will
+be similar in spirit to the present version, but may differ in detail to
+address new problems or concerns.
+
+ Each version is given a distinguishing version number. If the
+Program specifies that a certain numbered version of the GNU General
+Public License "or any later version" applies to it, you have the
+option of following the terms and conditions either of that numbered
+version or of any later version published by the Free Software
+Foundation. If the Program does not specify a version number of the
+GNU General Public License, you may choose any version ever published
+by the Free Software Foundation.
+
+ If the Program specifies that a proxy can decide which future
+versions of the GNU General Public License can be used, that proxy's
+public statement of acceptance of a version permanently authorizes you
+to choose that version for the Program.
+
+ Later license versions may give you additional or different
+permissions. However, no additional obligations are imposed on any
+author or copyright holder as a result of your choosing to follow a
+later version.
+
+ 15. Disclaimer of Warranty.
+
+ THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY
+APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT
+HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY
+OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO,
+THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM
+IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF
+ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
+
+ 16. Limitation of Liability.
+
+ IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS
+THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY
+GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE
+USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF
+DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD
+PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS),
+EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF
+SUCH DAMAGES.
+
+ 17. Interpretation of Sections 15 and 16.
+
+ If the disclaimer of warranty and limitation of liability provided
+above cannot be given local legal effect according to their terms,
+reviewing courts shall apply local law that most closely approximates
+an absolute waiver of all civil liability in connection with the
+Program, unless a warranty or assumption of liability accompanies a
+copy of the Program in return for a fee.
+
+ END OF TERMS AND CONDITIONS
+
+ How to Apply These Terms to Your New Programs
+
+ If you develop a new program, and you want it to be of the greatest
+possible use to the public, the best way to achieve this is to make it
+free software which everyone can redistribute and change under these terms.
+
+ To do so, attach the following notices to the program. It is safest
+to attach them to the start of each source file to most effectively
+state the exclusion of warranty; and each file should have at least
+the "copyright" line and a pointer to where the full notice is found.
+
+
+ Copyright (C)
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see .
+
+Also add information on how to contact you by electronic and paper mail.
+
+ If the program does terminal interaction, make it output a short
+notice like this when it starts in an interactive mode:
+
+ Copyright (C)
+ This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
+ This is free software, and you are welcome to redistribute it
+ under certain conditions; type `show c' for details.
+
+The hypothetical commands `show w' and `show c' should show the appropriate
+parts of the General Public License. Of course, your program's commands
+might be different; for a GUI interface, you would use an "about box".
+
+ You should also get your employer (if you work as a programmer) or school,
+if any, to sign a "copyright disclaimer" for the program, if necessary.
+For more information on this, and how to apply and follow the GNU GPL, see
+.
+
+ The GNU General Public License does not permit incorporating your program
+into proprietary programs. If your program is a subroutine library, you
+may consider it more useful to permit linking proprietary applications with
+the library. If this is what you want to do, use the GNU Lesser General
+Public License instead of this License. But first, please read
+.
diff --git a/modules/sale_secondary_unit/MANIFEST.in b/modules/sale_secondary_unit/MANIFEST.in
new file mode 100644
index 0000000000..e88b2348a3
--- /dev/null
+++ b/modules/sale_secondary_unit/MANIFEST.in
@@ -0,0 +1,5 @@
+include CHANGELOG
+include COPYRIGHT
+include LICENSE
+include README.rst
+include doc/*
diff --git a/modules/sale_secondary_unit/README.rst b/modules/sale_secondary_unit/README.rst
new file mode 120000
index 0000000000..176d9c2695
--- /dev/null
+++ b/modules/sale_secondary_unit/README.rst
@@ -0,0 +1 @@
+doc/index.rst
\ No newline at end of file
diff --git a/modules/sale_secondary_unit/__init__.py b/modules/sale_secondary_unit/__init__.py
new file mode 100644
index 0000000000..9f9902a747
--- /dev/null
+++ b/modules/sale_secondary_unit/__init__.py
@@ -0,0 +1,29 @@
+# This file is part of Tryton. The COPYRIGHT file at the top level of
+# this repository contains the full copyright notices and license terms.
+
+from trytond.pool import Pool
+from . import account
+from . import product
+from . import sale
+from . import stock
+
+__all__ = ['register']
+
+
+def register():
+ Pool.register(
+ account.InvoiceLine,
+ product.Template,
+ product.Product,
+ sale.Line,
+ stock.Move,
+ module='sale_secondary_unit', type_='model')
+ Pool.register(
+ product.ProductCustomer,
+ sale.Line_ProductCustomer,
+ module='sale_secondary_unit', type_='model',
+ depends=['sale_product_customer'])
+ Pool.register(
+ sale.OpportunityLine,
+ module='sale_secondary_unit', type_='model',
+ depends=['sale_opportunity'])
diff --git a/modules/sale_secondary_unit/account.py b/modules/sale_secondary_unit/account.py
new file mode 100644
index 0000000000..5a28cc89a9
--- /dev/null
+++ b/modules/sale_secondary_unit/account.py
@@ -0,0 +1,35 @@
+# This file is part of Tryton. The COPYRIGHT file at the top level of
+# this repository contains the full copyright notices and license terms.
+
+from trytond.pool import PoolMeta, Pool
+
+
+class InvoiceLine(metaclass=PoolMeta):
+ __name__ = 'account.invoice.line'
+
+ def get_product_secondary_uom_category(self, name):
+ pool = Pool()
+ SaleLine = pool.get('sale.line')
+ category = super().get_product_secondary_uom_category(name)
+ if isinstance(self.origin, SaleLine):
+ if self.origin.secondary_unit:
+ category = self.origin.secondary_unit.category.id
+ return category
+
+ @property
+ def secondary_uom_factor(self):
+ pool = Pool()
+ SaleLine = pool.get('sale.line')
+ factor = super().secondary_uom_factor
+ if isinstance(self.origin, SaleLine):
+ factor = self.origin.secondary_uom_factor
+ return factor
+
+ @property
+ def secondary_uom_rate(self):
+ pool = Pool()
+ SaleLine = pool.get('sale.line')
+ factor = super().secondary_uom_rate
+ if isinstance(self.origin, SaleLine):
+ factor = self.origin.secondary_uom_rate
+ return factor
diff --git a/modules/sale_secondary_unit/doc/index.rst b/modules/sale_secondary_unit/doc/index.rst
new file mode 100644
index 0000000000..725b97637f
--- /dev/null
+++ b/modules/sale_secondary_unit/doc/index.rst
@@ -0,0 +1,12 @@
+Sale Secondary Unit Module
+##########################
+
+The sale secondary unit module adds a secondary unit of measure on sale lines.
+The secondary quantity and unit price are kept synchronized with the quantity
+and unit price.
+The secondary unit is defined on the product with its factor against the sale
+unit.
+
+If the sale product customer module is activated, a specific secondary unit may
+be defined on the product customer. And it overrides the definition on the
+product.
diff --git a/modules/sale_secondary_unit/locale/bg.po b/modules/sale_secondary_unit/locale/bg.po
new file mode 100644
index 0000000000..b91ff365cf
--- /dev/null
+++ b/modules/sale_secondary_unit/locale/bg.po
@@ -0,0 +1,140 @@
+#
+msgid ""
+msgstr "Content-Type: text/plain; charset=utf-8\n"
+
+msgctxt "field:product.product,sale_secondary_uom:"
+msgid "Sale Secondary UOM"
+msgstr ""
+
+msgctxt "field:product.product,sale_secondary_uom_factor:"
+msgid "Sale Secondary UOM Factor"
+msgstr ""
+
+msgctxt "field:product.product,sale_secondary_uom_rate:"
+msgid "Sale Secondary UOM Rate"
+msgstr ""
+
+msgctxt "field:product.template,sale_secondary_uom:"
+msgid "Sale Secondary UOM"
+msgstr ""
+
+msgctxt "field:product.template,sale_secondary_uom_factor:"
+msgid "Sale Secondary UOM Factor"
+msgstr ""
+
+msgctxt "field:product.template,sale_secondary_uom_rate:"
+msgid "Sale Secondary UOM Rate"
+msgstr ""
+
+msgctxt "field:sale.line,product_secondary_uom_category:"
+msgid "Product Secondary UOM Category"
+msgstr ""
+
+msgctxt "field:sale.line,secondary_quantity:"
+msgid "Secondary Quantity"
+msgstr ""
+
+msgctxt "field:sale.line,secondary_unit:"
+msgid "Secondary Unit"
+msgstr ""
+
+msgctxt "field:sale.line,secondary_unit_digits:"
+msgid "Secondary Unit Digits"
+msgstr ""
+
+msgctxt "field:sale.line,secondary_unit_price:"
+msgid "Secondary Unit Price"
+msgstr ""
+
+msgctxt "field:sale.line,secondary_uom_factor:"
+msgid "Secondary UOM Factor"
+msgstr ""
+
+msgctxt "field:sale.line,secondary_uom_rate:"
+msgid "Secondary UOM Rate"
+msgstr ""
+
+msgctxt "field:sale.product_customer,default_uom_category:"
+msgid "Default UOM Category"
+msgstr ""
+
+msgctxt "field:sale.product_customer,sale_secondary_uom:"
+msgid "Sale Secondary UOM"
+msgstr ""
+
+msgctxt "field:sale.product_customer,sale_secondary_uom_factor:"
+msgid "Sale Secondary UOM Factor"
+msgstr ""
+
+msgctxt "field:sale.product_customer,sale_secondary_uom_rate:"
+msgid "Sale Secondary UOM Rate"
+msgstr ""
+
+msgctxt "help:product.product,sale_secondary_uom_factor:"
+msgid ""
+"The coefficient for the formula:\n"
+"1 (sale unit) = coefficient (secondary unit)"
+msgstr ""
+
+msgctxt "help:product.product,sale_secondary_uom_rate:"
+msgid ""
+"The coefficient for the formula:\n"
+"coefficient (sale unit) = 1 (secondary unit)"
+msgstr ""
+
+msgctxt "help:product.template,sale_secondary_uom_factor:"
+msgid ""
+"The coefficient for the formula:\n"
+"1 (sale unit) = coefficient (secondary unit)"
+msgstr ""
+
+msgctxt "help:product.template,sale_secondary_uom_rate:"
+msgid ""
+"The coefficient for the formula:\n"
+"coefficient (sale unit) = 1 (secondary unit)"
+msgstr ""
+
+msgctxt "help:sale.product_customer,sale_secondary_uom_factor:"
+msgid ""
+"The coefficient for the formula:\n"
+"1 (sale unit) = coefficient (secondary unit)"
+msgstr ""
+
+msgctxt "help:sale.product_customer,sale_secondary_uom_rate:"
+msgid ""
+"The coefficient for the formula:\n"
+"coefficient (sale unit) = 1 (secondary unit)"
+msgstr ""
+
+msgctxt ""
+"model:ir.message,text:msg_sale_secondary_uom_incompatible_factor_rate"
+msgid "Incompatible sale secondary factor and rate values for \"%(record)s\"."
+msgstr ""
+
+msgctxt "view:product.template:"
+msgid "Factor:"
+msgstr ""
+
+msgctxt "view:product.template:"
+msgid "Rate:"
+msgstr ""
+
+msgctxt "view:sale.line:"
+msgid "Quantity:"
+msgstr ""
+
+msgctxt "view:sale.line:"
+msgid "Unit Price:"
+msgstr ""
+
+msgctxt "view:sale.line:"
+msgid "Unit:"
+msgstr ""
+
+msgctxt "view:sale.product_customer:"
+msgid "Factor:"
+msgstr ""
+
+msgctxt "view:sale.product_customer:"
+msgid "Rate:"
+msgstr ""
diff --git a/modules/sale_secondary_unit/locale/ca.po b/modules/sale_secondary_unit/locale/ca.po
new file mode 100644
index 0000000000..36a9d64772
--- /dev/null
+++ b/modules/sale_secondary_unit/locale/ca.po
@@ -0,0 +1,153 @@
+#
+msgid ""
+msgstr "Content-Type: text/plain; charset=utf-8\n"
+
+msgctxt "field:product.product,sale_secondary_uom:"
+msgid "Sale Secondary UOM"
+msgstr "UdM de venta secundaria"
+
+msgctxt "field:product.product,sale_secondary_uom_factor:"
+msgid "Sale Secondary UOM Factor"
+msgstr "Factor UdM de venta secundaria"
+
+msgctxt "field:product.product,sale_secondary_uom_rate:"
+msgid "Sale Secondary UOM Rate"
+msgstr "Rati UdM de venta secundaria"
+
+msgctxt "field:product.template,sale_secondary_uom:"
+msgid "Sale Secondary UOM"
+msgstr "UdM de venta secundaria"
+
+msgctxt "field:product.template,sale_secondary_uom_factor:"
+msgid "Sale Secondary UOM Factor"
+msgstr "Factor UdM de venta secundaria"
+
+msgctxt "field:product.template,sale_secondary_uom_rate:"
+msgid "Sale Secondary UOM Rate"
+msgstr "Rati UdM de venta secundaria"
+
+msgctxt "field:sale.line,product_secondary_uom_category:"
+msgid "Product Secondary UOM Category"
+msgstr "Categoria de UdM secundaria del producte"
+
+msgctxt "field:sale.line,secondary_quantity:"
+msgid "Secondary Quantity"
+msgstr "Quantitat secundaria"
+
+msgctxt "field:sale.line,secondary_unit:"
+msgid "Secondary Unit"
+msgstr "Unitat secundaria"
+
+msgctxt "field:sale.line,secondary_unit_digits:"
+msgid "Secondary Unit Digits"
+msgstr "Dígits de la unitat secundaria"
+
+msgctxt "field:sale.line,secondary_unit_price:"
+msgid "Secondary Unit Price"
+msgstr "Preu unitari secundari"
+
+msgctxt "field:sale.line,secondary_uom_factor:"
+msgid "Secondary UOM Factor"
+msgstr "Factor UdM secundaria"
+
+msgctxt "field:sale.line,secondary_uom_rate:"
+msgid "Secondary UOM Rate"
+msgstr "Rati UdM secundaria"
+
+msgctxt "field:sale.product_customer,default_uom_category:"
+msgid "Default UOM Category"
+msgstr "Categoria UdM per defecte"
+
+msgctxt "field:sale.product_customer,sale_secondary_uom:"
+msgid "Sale Secondary UOM"
+msgstr "UdM de venta secundaria"
+
+msgctxt "field:sale.product_customer,sale_secondary_uom_factor:"
+msgid "Sale Secondary UOM Factor"
+msgstr "Factor UdM de venta secundaria"
+
+msgctxt "field:sale.product_customer,sale_secondary_uom_rate:"
+msgid "Sale Secondary UOM Rate"
+msgstr "Rati UdM de venta secundaria"
+
+msgctxt "help:product.product,sale_secondary_uom_factor:"
+msgid ""
+"The coefficient for the formula:\n"
+"1 (sale unit) = coefficient (secondary unit)"
+msgstr ""
+"El coeficient per la fórmula:\n"
+"1 (unitat de venta) = coeficient (unitat secundaria)"
+
+msgctxt "help:product.product,sale_secondary_uom_rate:"
+msgid ""
+"The coefficient for the formula:\n"
+"coefficient (sale unit) = 1 (secondary unit)"
+msgstr ""
+"El coeficient per la fórmula:\n"
+"coeficient (unitat de venta) = 1 (unitat secundaria)"
+
+msgctxt "help:product.template,sale_secondary_uom_factor:"
+msgid ""
+"The coefficient for the formula:\n"
+"1 (sale unit) = coefficient (secondary unit)"
+msgstr ""
+"El coeficient per la fórmula:\n"
+"1 (unitat de venta) = coeficient (unitat secundaria)"
+
+msgctxt "help:product.template,sale_secondary_uom_rate:"
+msgid ""
+"The coefficient for the formula:\n"
+"coefficient (sale unit) = 1 (secondary unit)"
+msgstr ""
+"El coeficient per la fórmula:\n"
+"coeficient (unitat de venta) = 1 (unitat secundaria)"
+
+msgctxt "help:sale.product_customer,sale_secondary_uom_factor:"
+msgid ""
+"The coefficient for the formula:\n"
+"1 (sale unit) = coefficient (secondary unit)"
+msgstr ""
+"El coeficient per la fórmula:\n"
+"1 (unitat de venta) = coeficient (unitat secundaria)"
+
+msgctxt "help:sale.product_customer,sale_secondary_uom_rate:"
+msgid ""
+"The coefficient for the formula:\n"
+"coefficient (sale unit) = 1 (secondary unit)"
+msgstr ""
+"El coeficient per la fórmula:\n"
+"coeficient (unitat de venta) = 1 (unitat secundaria)"
+
+msgctxt ""
+"model:ir.message,text:msg_sale_secondary_uom_incompatible_factor_rate"
+msgid "Incompatible sale secondary factor and rate values for \"%(record)s\"."
+msgstr ""
+"El factor i el rati de venda secundari de \"%(record)s\" són incompatibles."
+
+msgctxt "view:product.template:"
+msgid "Factor:"
+msgstr "Factor:"
+
+msgctxt "view:product.template:"
+msgid "Rate:"
+msgstr "Rati:"
+
+msgctxt "view:sale.line:"
+msgid "Quantity:"
+msgstr "Quantitat:"
+
+msgctxt "view:sale.line:"
+msgid "Unit Price:"
+msgstr "Preu unitari:"
+
+msgctxt "view:sale.line:"
+msgid "Unit:"
+msgstr "Unitat:"
+
+msgctxt "view:sale.product_customer:"
+msgid "Factor:"
+msgstr "Factor:"
+
+msgctxt "view:sale.product_customer:"
+msgid "Rate:"
+msgstr "Rati:"
diff --git a/modules/sale_secondary_unit/locale/cs.po b/modules/sale_secondary_unit/locale/cs.po
new file mode 100644
index 0000000000..b91ff365cf
--- /dev/null
+++ b/modules/sale_secondary_unit/locale/cs.po
@@ -0,0 +1,140 @@
+#
+msgid ""
+msgstr "Content-Type: text/plain; charset=utf-8\n"
+
+msgctxt "field:product.product,sale_secondary_uom:"
+msgid "Sale Secondary UOM"
+msgstr ""
+
+msgctxt "field:product.product,sale_secondary_uom_factor:"
+msgid "Sale Secondary UOM Factor"
+msgstr ""
+
+msgctxt "field:product.product,sale_secondary_uom_rate:"
+msgid "Sale Secondary UOM Rate"
+msgstr ""
+
+msgctxt "field:product.template,sale_secondary_uom:"
+msgid "Sale Secondary UOM"
+msgstr ""
+
+msgctxt "field:product.template,sale_secondary_uom_factor:"
+msgid "Sale Secondary UOM Factor"
+msgstr ""
+
+msgctxt "field:product.template,sale_secondary_uom_rate:"
+msgid "Sale Secondary UOM Rate"
+msgstr ""
+
+msgctxt "field:sale.line,product_secondary_uom_category:"
+msgid "Product Secondary UOM Category"
+msgstr ""
+
+msgctxt "field:sale.line,secondary_quantity:"
+msgid "Secondary Quantity"
+msgstr ""
+
+msgctxt "field:sale.line,secondary_unit:"
+msgid "Secondary Unit"
+msgstr ""
+
+msgctxt "field:sale.line,secondary_unit_digits:"
+msgid "Secondary Unit Digits"
+msgstr ""
+
+msgctxt "field:sale.line,secondary_unit_price:"
+msgid "Secondary Unit Price"
+msgstr ""
+
+msgctxt "field:sale.line,secondary_uom_factor:"
+msgid "Secondary UOM Factor"
+msgstr ""
+
+msgctxt "field:sale.line,secondary_uom_rate:"
+msgid "Secondary UOM Rate"
+msgstr ""
+
+msgctxt "field:sale.product_customer,default_uom_category:"
+msgid "Default UOM Category"
+msgstr ""
+
+msgctxt "field:sale.product_customer,sale_secondary_uom:"
+msgid "Sale Secondary UOM"
+msgstr ""
+
+msgctxt "field:sale.product_customer,sale_secondary_uom_factor:"
+msgid "Sale Secondary UOM Factor"
+msgstr ""
+
+msgctxt "field:sale.product_customer,sale_secondary_uom_rate:"
+msgid "Sale Secondary UOM Rate"
+msgstr ""
+
+msgctxt "help:product.product,sale_secondary_uom_factor:"
+msgid ""
+"The coefficient for the formula:\n"
+"1 (sale unit) = coefficient (secondary unit)"
+msgstr ""
+
+msgctxt "help:product.product,sale_secondary_uom_rate:"
+msgid ""
+"The coefficient for the formula:\n"
+"coefficient (sale unit) = 1 (secondary unit)"
+msgstr ""
+
+msgctxt "help:product.template,sale_secondary_uom_factor:"
+msgid ""
+"The coefficient for the formula:\n"
+"1 (sale unit) = coefficient (secondary unit)"
+msgstr ""
+
+msgctxt "help:product.template,sale_secondary_uom_rate:"
+msgid ""
+"The coefficient for the formula:\n"
+"coefficient (sale unit) = 1 (secondary unit)"
+msgstr ""
+
+msgctxt "help:sale.product_customer,sale_secondary_uom_factor:"
+msgid ""
+"The coefficient for the formula:\n"
+"1 (sale unit) = coefficient (secondary unit)"
+msgstr ""
+
+msgctxt "help:sale.product_customer,sale_secondary_uom_rate:"
+msgid ""
+"The coefficient for the formula:\n"
+"coefficient (sale unit) = 1 (secondary unit)"
+msgstr ""
+
+msgctxt ""
+"model:ir.message,text:msg_sale_secondary_uom_incompatible_factor_rate"
+msgid "Incompatible sale secondary factor and rate values for \"%(record)s\"."
+msgstr ""
+
+msgctxt "view:product.template:"
+msgid "Factor:"
+msgstr ""
+
+msgctxt "view:product.template:"
+msgid "Rate:"
+msgstr ""
+
+msgctxt "view:sale.line:"
+msgid "Quantity:"
+msgstr ""
+
+msgctxt "view:sale.line:"
+msgid "Unit Price:"
+msgstr ""
+
+msgctxt "view:sale.line:"
+msgid "Unit:"
+msgstr ""
+
+msgctxt "view:sale.product_customer:"
+msgid "Factor:"
+msgstr ""
+
+msgctxt "view:sale.product_customer:"
+msgid "Rate:"
+msgstr ""
diff --git a/modules/sale_secondary_unit/locale/de.po b/modules/sale_secondary_unit/locale/de.po
new file mode 100644
index 0000000000..9925514990
--- /dev/null
+++ b/modules/sale_secondary_unit/locale/de.po
@@ -0,0 +1,154 @@
+#
+msgid ""
+msgstr "Content-Type: text/plain; charset=utf-8\n"
+
+msgctxt "field:product.product,sale_secondary_uom:"
+msgid "Sale Secondary UOM"
+msgstr "Verkauf Zweitmaßeinheit"
+
+msgctxt "field:product.product,sale_secondary_uom_factor:"
+msgid "Sale Secondary UOM Factor"
+msgstr "Verkauf Zweitmaßeinheit Faktor"
+
+msgctxt "field:product.product,sale_secondary_uom_rate:"
+msgid "Sale Secondary UOM Rate"
+msgstr "Verkauf Zweitmaßeinheit Kehrwert Faktor"
+
+msgctxt "field:product.template,sale_secondary_uom:"
+msgid "Sale Secondary UOM"
+msgstr "Verkauf Zweitmaßeinheit"
+
+msgctxt "field:product.template,sale_secondary_uom_factor:"
+msgid "Sale Secondary UOM Factor"
+msgstr "Verkauf Zweitmaßeinheit Faktor"
+
+msgctxt "field:product.template,sale_secondary_uom_rate:"
+msgid "Sale Secondary UOM Rate"
+msgstr "Verkauf Zweitmaßeinheit Kehrwert Faktor"
+
+msgctxt "field:sale.line,product_secondary_uom_category:"
+msgid "Product Secondary UOM Category"
+msgstr "Artikel Zweitmaßeinheitenkategorie"
+
+msgctxt "field:sale.line,secondary_quantity:"
+msgid "Secondary Quantity"
+msgstr "Zweitmenge"
+
+msgctxt "field:sale.line,secondary_unit:"
+msgid "Secondary Unit"
+msgstr "Zweitmaßeinheit"
+
+msgctxt "field:sale.line,secondary_unit_digits:"
+msgid "Secondary Unit Digits"
+msgstr "Nachkommastellen Zweitmaßeinheit"
+
+msgctxt "field:sale.line,secondary_unit_price:"
+msgid "Secondary Unit Price"
+msgstr "Zweiteinzelpreis"
+
+msgctxt "field:sale.line,secondary_uom_factor:"
+msgid "Secondary UOM Factor"
+msgstr "Zweitmaßeinheit Faktor"
+
+msgctxt "field:sale.line,secondary_uom_rate:"
+msgid "Secondary UOM Rate"
+msgstr "Zweitmaßeinheit Kehrwert Faktor"
+
+msgctxt "field:sale.product_customer,default_uom_category:"
+msgid "Default UOM Category"
+msgstr "Standardkategorie Maßeinheit"
+
+msgctxt "field:sale.product_customer,sale_secondary_uom:"
+msgid "Sale Secondary UOM"
+msgstr "Verkauf Zweitmaßeinheit"
+
+msgctxt "field:sale.product_customer,sale_secondary_uom_factor:"
+msgid "Sale Secondary UOM Factor"
+msgstr "Verkauf Zweitmaßeinheit Faktor"
+
+msgctxt "field:sale.product_customer,sale_secondary_uom_rate:"
+msgid "Sale Secondary UOM Rate"
+msgstr "Verkauf Zweitmaßeinheit Kehrwert Faktor"
+
+msgctxt "help:product.product,sale_secondary_uom_factor:"
+msgid ""
+"The coefficient for the formula:\n"
+"1 (sale unit) = coefficient (secondary unit)"
+msgstr ""
+"Der Koeffizient für die Formel:\n"
+"1 (Verkaufseinheit) = Koeffizient (Zweitmaßeinheit)"
+
+msgctxt "help:product.product,sale_secondary_uom_rate:"
+msgid ""
+"The coefficient for the formula:\n"
+"coefficient (sale unit) = 1 (secondary unit)"
+msgstr ""
+"Der Koeffizient für die Formel:\n"
+"Koeffizient (Verkaufseinheit) = 1 (Zweitmaßeinheit)"
+
+msgctxt "help:product.template,sale_secondary_uom_factor:"
+msgid ""
+"The coefficient for the formula:\n"
+"1 (sale unit) = coefficient (secondary unit)"
+msgstr ""
+"Der Koeffizient für die Formel:\n"
+"1 (Verkaufseinheit) = Koeffizient (Zweitmaßeinheit)"
+
+msgctxt "help:product.template,sale_secondary_uom_rate:"
+msgid ""
+"The coefficient for the formula:\n"
+"coefficient (sale unit) = 1 (secondary unit)"
+msgstr ""
+"Der Koeffizient für die Formel:\n"
+"Koeffizient (Verkaufseinheit) = 1 (Zweitmaßeinheit)"
+
+msgctxt "help:sale.product_customer,sale_secondary_uom_factor:"
+msgid ""
+"The coefficient for the formula:\n"
+"1 (sale unit) = coefficient (secondary unit)"
+msgstr ""
+"Der Koeffizient für die Formel:\n"
+"1 (Verkaufseinheit) = Koeffizient (Zweitmaßeinheit)"
+
+msgctxt "help:sale.product_customer,sale_secondary_uom_rate:"
+msgid ""
+"The coefficient for the formula:\n"
+"coefficient (sale unit) = 1 (secondary unit)"
+msgstr ""
+"Der Koeffizient für die Formel:\n"
+"Koeffizient (Verkaufseinheit) = 1 (Zweitmaßeinheit)"
+
+msgctxt ""
+"model:ir.message,text:msg_sale_secondary_uom_incompatible_factor_rate"
+msgid "Incompatible sale secondary factor and rate values for \"%(record)s\"."
+msgstr ""
+"Inkompatible Werte für Faktor und Kehrwert der Zweiteinheit für "
+"\"%(record)s\"."
+
+msgctxt "view:product.template:"
+msgid "Factor:"
+msgstr "Faktor:"
+
+msgctxt "view:product.template:"
+msgid "Rate:"
+msgstr "Kehrwert Faktor:"
+
+msgctxt "view:sale.line:"
+msgid "Quantity:"
+msgstr "Menge:"
+
+msgctxt "view:sale.line:"
+msgid "Unit Price:"
+msgstr "Einzelpreis:"
+
+msgctxt "view:sale.line:"
+msgid "Unit:"
+msgstr "Einheit:"
+
+msgctxt "view:sale.product_customer:"
+msgid "Factor:"
+msgstr "Faktor:"
+
+msgctxt "view:sale.product_customer:"
+msgid "Rate:"
+msgstr "Kehrwert Faktor:"
diff --git a/modules/sale_secondary_unit/locale/es.po b/modules/sale_secondary_unit/locale/es.po
new file mode 100644
index 0000000000..21d540c165
--- /dev/null
+++ b/modules/sale_secondary_unit/locale/es.po
@@ -0,0 +1,154 @@
+#
+msgid ""
+msgstr "Content-Type: text/plain; charset=utf-8\n"
+
+msgctxt "field:product.product,sale_secondary_uom:"
+msgid "Sale Secondary UOM"
+msgstr "UdM de venta secundaria"
+
+msgctxt "field:product.product,sale_secondary_uom_factor:"
+msgid "Sale Secondary UOM Factor"
+msgstr "Factor UdM de venta secundaria"
+
+msgctxt "field:product.product,sale_secondary_uom_rate:"
+msgid "Sale Secondary UOM Rate"
+msgstr "Ratio UdM de venta secundaria"
+
+msgctxt "field:product.template,sale_secondary_uom:"
+msgid "Sale Secondary UOM"
+msgstr "UdM de venta secundaria"
+
+msgctxt "field:product.template,sale_secondary_uom_factor:"
+msgid "Sale Secondary UOM Factor"
+msgstr "Factor UdM de venta secundaria"
+
+msgctxt "field:product.template,sale_secondary_uom_rate:"
+msgid "Sale Secondary UOM Rate"
+msgstr "Ratio UdM de venta secundaria"
+
+msgctxt "field:sale.line,product_secondary_uom_category:"
+msgid "Product Secondary UOM Category"
+msgstr "Categoría de UdM secundaria del producto"
+
+msgctxt "field:sale.line,secondary_quantity:"
+msgid "Secondary Quantity"
+msgstr "Cantidad secundaria"
+
+msgctxt "field:sale.line,secondary_unit:"
+msgid "Secondary Unit"
+msgstr "Unidad secundaria"
+
+msgctxt "field:sale.line,secondary_unit_digits:"
+msgid "Secondary Unit Digits"
+msgstr "Dígitos unidad secundaria"
+
+msgctxt "field:sale.line,secondary_unit_price:"
+msgid "Secondary Unit Price"
+msgstr "Precio unitario secundario"
+
+msgctxt "field:sale.line,secondary_uom_factor:"
+msgid "Secondary UOM Factor"
+msgstr "Factor UdM secundaria"
+
+msgctxt "field:sale.line,secondary_uom_rate:"
+msgid "Secondary UOM Rate"
+msgstr "Ratio UdM secundaria"
+
+msgctxt "field:sale.product_customer,default_uom_category:"
+msgid "Default UOM Category"
+msgstr "Categoria UdM por defecto"
+
+msgctxt "field:sale.product_customer,sale_secondary_uom:"
+msgid "Sale Secondary UOM"
+msgstr "UdM de venta secundaria"
+
+msgctxt "field:sale.product_customer,sale_secondary_uom_factor:"
+msgid "Sale Secondary UOM Factor"
+msgstr "Factor UdM de venta secundaria"
+
+msgctxt "field:sale.product_customer,sale_secondary_uom_rate:"
+msgid "Sale Secondary UOM Rate"
+msgstr "Ratio UdM de venta secundaria"
+
+msgctxt "help:product.product,sale_secondary_uom_factor:"
+msgid ""
+"The coefficient for the formula:\n"
+"1 (sale unit) = coefficient (secondary unit)"
+msgstr ""
+"El coeficiente para la formula:\n"
+"1 (unidad de venta) = coeficiente (unidad secundaria)"
+
+msgctxt "help:product.product,sale_secondary_uom_rate:"
+msgid ""
+"The coefficient for the formula:\n"
+"coefficient (sale unit) = 1 (secondary unit)"
+msgstr ""
+"El coeficiente para la formula:\n"
+"coeficiente (unidad de venta) = 1 (unidad secundaria)"
+
+msgctxt "help:product.template,sale_secondary_uom_factor:"
+msgid ""
+"The coefficient for the formula:\n"
+"1 (sale unit) = coefficient (secondary unit)"
+msgstr ""
+"El coeficiente para la fórmula:\n"
+"1 (unidad de venta) = coeficiente (unidad secundaria)"
+
+msgctxt "help:product.template,sale_secondary_uom_rate:"
+msgid ""
+"The coefficient for the formula:\n"
+"coefficient (sale unit) = 1 (secondary unit)"
+msgstr ""
+"El coeficiente para la fórmula:\n"
+"coeficiente (unidad de venta) = 1 (unidad secundaria)"
+
+msgctxt "help:sale.product_customer,sale_secondary_uom_factor:"
+msgid ""
+"The coefficient for the formula:\n"
+"1 (sale unit) = coefficient (secondary unit)"
+msgstr ""
+"El coeficiente para la fórmula:\n"
+"1 (unidad de venta) = coeficiente (unidad secundaria)"
+
+msgctxt "help:sale.product_customer,sale_secondary_uom_rate:"
+msgid ""
+"The coefficient for the formula:\n"
+"coefficient (sale unit) = 1 (secondary unit)"
+msgstr ""
+"El coeficiente para la fórmula:\n"
+"coeficiente (unidad de venta) = 1 (unidad secundaria)"
+
+msgctxt ""
+"model:ir.message,text:msg_sale_secondary_uom_incompatible_factor_rate"
+msgid "Incompatible sale secondary factor and rate values for \"%(record)s\"."
+msgstr ""
+"El factor i el ratio de venta secundarios de \"%(record)s\" són "
+"incompatibles."
+
+msgctxt "view:product.template:"
+msgid "Factor:"
+msgstr "Factor:"
+
+msgctxt "view:product.template:"
+msgid "Rate:"
+msgstr "Ratio:"
+
+msgctxt "view:sale.line:"
+msgid "Quantity:"
+msgstr "Cantidad:"
+
+msgctxt "view:sale.line:"
+msgid "Unit Price:"
+msgstr "Precio unitario:"
+
+msgctxt "view:sale.line:"
+msgid "Unit:"
+msgstr "Unidad:"
+
+msgctxt "view:sale.product_customer:"
+msgid "Factor:"
+msgstr "Factor:"
+
+msgctxt "view:sale.product_customer:"
+msgid "Rate:"
+msgstr "Ratio:"
diff --git a/modules/sale_secondary_unit/locale/es_419.po b/modules/sale_secondary_unit/locale/es_419.po
new file mode 100644
index 0000000000..b91ff365cf
--- /dev/null
+++ b/modules/sale_secondary_unit/locale/es_419.po
@@ -0,0 +1,140 @@
+#
+msgid ""
+msgstr "Content-Type: text/plain; charset=utf-8\n"
+
+msgctxt "field:product.product,sale_secondary_uom:"
+msgid "Sale Secondary UOM"
+msgstr ""
+
+msgctxt "field:product.product,sale_secondary_uom_factor:"
+msgid "Sale Secondary UOM Factor"
+msgstr ""
+
+msgctxt "field:product.product,sale_secondary_uom_rate:"
+msgid "Sale Secondary UOM Rate"
+msgstr ""
+
+msgctxt "field:product.template,sale_secondary_uom:"
+msgid "Sale Secondary UOM"
+msgstr ""
+
+msgctxt "field:product.template,sale_secondary_uom_factor:"
+msgid "Sale Secondary UOM Factor"
+msgstr ""
+
+msgctxt "field:product.template,sale_secondary_uom_rate:"
+msgid "Sale Secondary UOM Rate"
+msgstr ""
+
+msgctxt "field:sale.line,product_secondary_uom_category:"
+msgid "Product Secondary UOM Category"
+msgstr ""
+
+msgctxt "field:sale.line,secondary_quantity:"
+msgid "Secondary Quantity"
+msgstr ""
+
+msgctxt "field:sale.line,secondary_unit:"
+msgid "Secondary Unit"
+msgstr ""
+
+msgctxt "field:sale.line,secondary_unit_digits:"
+msgid "Secondary Unit Digits"
+msgstr ""
+
+msgctxt "field:sale.line,secondary_unit_price:"
+msgid "Secondary Unit Price"
+msgstr ""
+
+msgctxt "field:sale.line,secondary_uom_factor:"
+msgid "Secondary UOM Factor"
+msgstr ""
+
+msgctxt "field:sale.line,secondary_uom_rate:"
+msgid "Secondary UOM Rate"
+msgstr ""
+
+msgctxt "field:sale.product_customer,default_uom_category:"
+msgid "Default UOM Category"
+msgstr ""
+
+msgctxt "field:sale.product_customer,sale_secondary_uom:"
+msgid "Sale Secondary UOM"
+msgstr ""
+
+msgctxt "field:sale.product_customer,sale_secondary_uom_factor:"
+msgid "Sale Secondary UOM Factor"
+msgstr ""
+
+msgctxt "field:sale.product_customer,sale_secondary_uom_rate:"
+msgid "Sale Secondary UOM Rate"
+msgstr ""
+
+msgctxt "help:product.product,sale_secondary_uom_factor:"
+msgid ""
+"The coefficient for the formula:\n"
+"1 (sale unit) = coefficient (secondary unit)"
+msgstr ""
+
+msgctxt "help:product.product,sale_secondary_uom_rate:"
+msgid ""
+"The coefficient for the formula:\n"
+"coefficient (sale unit) = 1 (secondary unit)"
+msgstr ""
+
+msgctxt "help:product.template,sale_secondary_uom_factor:"
+msgid ""
+"The coefficient for the formula:\n"
+"1 (sale unit) = coefficient (secondary unit)"
+msgstr ""
+
+msgctxt "help:product.template,sale_secondary_uom_rate:"
+msgid ""
+"The coefficient for the formula:\n"
+"coefficient (sale unit) = 1 (secondary unit)"
+msgstr ""
+
+msgctxt "help:sale.product_customer,sale_secondary_uom_factor:"
+msgid ""
+"The coefficient for the formula:\n"
+"1 (sale unit) = coefficient (secondary unit)"
+msgstr ""
+
+msgctxt "help:sale.product_customer,sale_secondary_uom_rate:"
+msgid ""
+"The coefficient for the formula:\n"
+"coefficient (sale unit) = 1 (secondary unit)"
+msgstr ""
+
+msgctxt ""
+"model:ir.message,text:msg_sale_secondary_uom_incompatible_factor_rate"
+msgid "Incompatible sale secondary factor and rate values for \"%(record)s\"."
+msgstr ""
+
+msgctxt "view:product.template:"
+msgid "Factor:"
+msgstr ""
+
+msgctxt "view:product.template:"
+msgid "Rate:"
+msgstr ""
+
+msgctxt "view:sale.line:"
+msgid "Quantity:"
+msgstr ""
+
+msgctxt "view:sale.line:"
+msgid "Unit Price:"
+msgstr ""
+
+msgctxt "view:sale.line:"
+msgid "Unit:"
+msgstr ""
+
+msgctxt "view:sale.product_customer:"
+msgid "Factor:"
+msgstr ""
+
+msgctxt "view:sale.product_customer:"
+msgid "Rate:"
+msgstr ""
diff --git a/modules/sale_secondary_unit/locale/et.po b/modules/sale_secondary_unit/locale/et.po
new file mode 100644
index 0000000000..b91ff365cf
--- /dev/null
+++ b/modules/sale_secondary_unit/locale/et.po
@@ -0,0 +1,140 @@
+#
+msgid ""
+msgstr "Content-Type: text/plain; charset=utf-8\n"
+
+msgctxt "field:product.product,sale_secondary_uom:"
+msgid "Sale Secondary UOM"
+msgstr ""
+
+msgctxt "field:product.product,sale_secondary_uom_factor:"
+msgid "Sale Secondary UOM Factor"
+msgstr ""
+
+msgctxt "field:product.product,sale_secondary_uom_rate:"
+msgid "Sale Secondary UOM Rate"
+msgstr ""
+
+msgctxt "field:product.template,sale_secondary_uom:"
+msgid "Sale Secondary UOM"
+msgstr ""
+
+msgctxt "field:product.template,sale_secondary_uom_factor:"
+msgid "Sale Secondary UOM Factor"
+msgstr ""
+
+msgctxt "field:product.template,sale_secondary_uom_rate:"
+msgid "Sale Secondary UOM Rate"
+msgstr ""
+
+msgctxt "field:sale.line,product_secondary_uom_category:"
+msgid "Product Secondary UOM Category"
+msgstr ""
+
+msgctxt "field:sale.line,secondary_quantity:"
+msgid "Secondary Quantity"
+msgstr ""
+
+msgctxt "field:sale.line,secondary_unit:"
+msgid "Secondary Unit"
+msgstr ""
+
+msgctxt "field:sale.line,secondary_unit_digits:"
+msgid "Secondary Unit Digits"
+msgstr ""
+
+msgctxt "field:sale.line,secondary_unit_price:"
+msgid "Secondary Unit Price"
+msgstr ""
+
+msgctxt "field:sale.line,secondary_uom_factor:"
+msgid "Secondary UOM Factor"
+msgstr ""
+
+msgctxt "field:sale.line,secondary_uom_rate:"
+msgid "Secondary UOM Rate"
+msgstr ""
+
+msgctxt "field:sale.product_customer,default_uom_category:"
+msgid "Default UOM Category"
+msgstr ""
+
+msgctxt "field:sale.product_customer,sale_secondary_uom:"
+msgid "Sale Secondary UOM"
+msgstr ""
+
+msgctxt "field:sale.product_customer,sale_secondary_uom_factor:"
+msgid "Sale Secondary UOM Factor"
+msgstr ""
+
+msgctxt "field:sale.product_customer,sale_secondary_uom_rate:"
+msgid "Sale Secondary UOM Rate"
+msgstr ""
+
+msgctxt "help:product.product,sale_secondary_uom_factor:"
+msgid ""
+"The coefficient for the formula:\n"
+"1 (sale unit) = coefficient (secondary unit)"
+msgstr ""
+
+msgctxt "help:product.product,sale_secondary_uom_rate:"
+msgid ""
+"The coefficient for the formula:\n"
+"coefficient (sale unit) = 1 (secondary unit)"
+msgstr ""
+
+msgctxt "help:product.template,sale_secondary_uom_factor:"
+msgid ""
+"The coefficient for the formula:\n"
+"1 (sale unit) = coefficient (secondary unit)"
+msgstr ""
+
+msgctxt "help:product.template,sale_secondary_uom_rate:"
+msgid ""
+"The coefficient for the formula:\n"
+"coefficient (sale unit) = 1 (secondary unit)"
+msgstr ""
+
+msgctxt "help:sale.product_customer,sale_secondary_uom_factor:"
+msgid ""
+"The coefficient for the formula:\n"
+"1 (sale unit) = coefficient (secondary unit)"
+msgstr ""
+
+msgctxt "help:sale.product_customer,sale_secondary_uom_rate:"
+msgid ""
+"The coefficient for the formula:\n"
+"coefficient (sale unit) = 1 (secondary unit)"
+msgstr ""
+
+msgctxt ""
+"model:ir.message,text:msg_sale_secondary_uom_incompatible_factor_rate"
+msgid "Incompatible sale secondary factor and rate values for \"%(record)s\"."
+msgstr ""
+
+msgctxt "view:product.template:"
+msgid "Factor:"
+msgstr ""
+
+msgctxt "view:product.template:"
+msgid "Rate:"
+msgstr ""
+
+msgctxt "view:sale.line:"
+msgid "Quantity:"
+msgstr ""
+
+msgctxt "view:sale.line:"
+msgid "Unit Price:"
+msgstr ""
+
+msgctxt "view:sale.line:"
+msgid "Unit:"
+msgstr ""
+
+msgctxt "view:sale.product_customer:"
+msgid "Factor:"
+msgstr ""
+
+msgctxt "view:sale.product_customer:"
+msgid "Rate:"
+msgstr ""
diff --git a/modules/sale_secondary_unit/locale/fa.po b/modules/sale_secondary_unit/locale/fa.po
new file mode 100644
index 0000000000..b91ff365cf
--- /dev/null
+++ b/modules/sale_secondary_unit/locale/fa.po
@@ -0,0 +1,140 @@
+#
+msgid ""
+msgstr "Content-Type: text/plain; charset=utf-8\n"
+
+msgctxt "field:product.product,sale_secondary_uom:"
+msgid "Sale Secondary UOM"
+msgstr ""
+
+msgctxt "field:product.product,sale_secondary_uom_factor:"
+msgid "Sale Secondary UOM Factor"
+msgstr ""
+
+msgctxt "field:product.product,sale_secondary_uom_rate:"
+msgid "Sale Secondary UOM Rate"
+msgstr ""
+
+msgctxt "field:product.template,sale_secondary_uom:"
+msgid "Sale Secondary UOM"
+msgstr ""
+
+msgctxt "field:product.template,sale_secondary_uom_factor:"
+msgid "Sale Secondary UOM Factor"
+msgstr ""
+
+msgctxt "field:product.template,sale_secondary_uom_rate:"
+msgid "Sale Secondary UOM Rate"
+msgstr ""
+
+msgctxt "field:sale.line,product_secondary_uom_category:"
+msgid "Product Secondary UOM Category"
+msgstr ""
+
+msgctxt "field:sale.line,secondary_quantity:"
+msgid "Secondary Quantity"
+msgstr ""
+
+msgctxt "field:sale.line,secondary_unit:"
+msgid "Secondary Unit"
+msgstr ""
+
+msgctxt "field:sale.line,secondary_unit_digits:"
+msgid "Secondary Unit Digits"
+msgstr ""
+
+msgctxt "field:sale.line,secondary_unit_price:"
+msgid "Secondary Unit Price"
+msgstr ""
+
+msgctxt "field:sale.line,secondary_uom_factor:"
+msgid "Secondary UOM Factor"
+msgstr ""
+
+msgctxt "field:sale.line,secondary_uom_rate:"
+msgid "Secondary UOM Rate"
+msgstr ""
+
+msgctxt "field:sale.product_customer,default_uom_category:"
+msgid "Default UOM Category"
+msgstr ""
+
+msgctxt "field:sale.product_customer,sale_secondary_uom:"
+msgid "Sale Secondary UOM"
+msgstr ""
+
+msgctxt "field:sale.product_customer,sale_secondary_uom_factor:"
+msgid "Sale Secondary UOM Factor"
+msgstr ""
+
+msgctxt "field:sale.product_customer,sale_secondary_uom_rate:"
+msgid "Sale Secondary UOM Rate"
+msgstr ""
+
+msgctxt "help:product.product,sale_secondary_uom_factor:"
+msgid ""
+"The coefficient for the formula:\n"
+"1 (sale unit) = coefficient (secondary unit)"
+msgstr ""
+
+msgctxt "help:product.product,sale_secondary_uom_rate:"
+msgid ""
+"The coefficient for the formula:\n"
+"coefficient (sale unit) = 1 (secondary unit)"
+msgstr ""
+
+msgctxt "help:product.template,sale_secondary_uom_factor:"
+msgid ""
+"The coefficient for the formula:\n"
+"1 (sale unit) = coefficient (secondary unit)"
+msgstr ""
+
+msgctxt "help:product.template,sale_secondary_uom_rate:"
+msgid ""
+"The coefficient for the formula:\n"
+"coefficient (sale unit) = 1 (secondary unit)"
+msgstr ""
+
+msgctxt "help:sale.product_customer,sale_secondary_uom_factor:"
+msgid ""
+"The coefficient for the formula:\n"
+"1 (sale unit) = coefficient (secondary unit)"
+msgstr ""
+
+msgctxt "help:sale.product_customer,sale_secondary_uom_rate:"
+msgid ""
+"The coefficient for the formula:\n"
+"coefficient (sale unit) = 1 (secondary unit)"
+msgstr ""
+
+msgctxt ""
+"model:ir.message,text:msg_sale_secondary_uom_incompatible_factor_rate"
+msgid "Incompatible sale secondary factor and rate values for \"%(record)s\"."
+msgstr ""
+
+msgctxt "view:product.template:"
+msgid "Factor:"
+msgstr ""
+
+msgctxt "view:product.template:"
+msgid "Rate:"
+msgstr ""
+
+msgctxt "view:sale.line:"
+msgid "Quantity:"
+msgstr ""
+
+msgctxt "view:sale.line:"
+msgid "Unit Price:"
+msgstr ""
+
+msgctxt "view:sale.line:"
+msgid "Unit:"
+msgstr ""
+
+msgctxt "view:sale.product_customer:"
+msgid "Factor:"
+msgstr ""
+
+msgctxt "view:sale.product_customer:"
+msgid "Rate:"
+msgstr ""
diff --git a/modules/sale_secondary_unit/locale/fi.po b/modules/sale_secondary_unit/locale/fi.po
new file mode 100644
index 0000000000..b91ff365cf
--- /dev/null
+++ b/modules/sale_secondary_unit/locale/fi.po
@@ -0,0 +1,140 @@
+#
+msgid ""
+msgstr "Content-Type: text/plain; charset=utf-8\n"
+
+msgctxt "field:product.product,sale_secondary_uom:"
+msgid "Sale Secondary UOM"
+msgstr ""
+
+msgctxt "field:product.product,sale_secondary_uom_factor:"
+msgid "Sale Secondary UOM Factor"
+msgstr ""
+
+msgctxt "field:product.product,sale_secondary_uom_rate:"
+msgid "Sale Secondary UOM Rate"
+msgstr ""
+
+msgctxt "field:product.template,sale_secondary_uom:"
+msgid "Sale Secondary UOM"
+msgstr ""
+
+msgctxt "field:product.template,sale_secondary_uom_factor:"
+msgid "Sale Secondary UOM Factor"
+msgstr ""
+
+msgctxt "field:product.template,sale_secondary_uom_rate:"
+msgid "Sale Secondary UOM Rate"
+msgstr ""
+
+msgctxt "field:sale.line,product_secondary_uom_category:"
+msgid "Product Secondary UOM Category"
+msgstr ""
+
+msgctxt "field:sale.line,secondary_quantity:"
+msgid "Secondary Quantity"
+msgstr ""
+
+msgctxt "field:sale.line,secondary_unit:"
+msgid "Secondary Unit"
+msgstr ""
+
+msgctxt "field:sale.line,secondary_unit_digits:"
+msgid "Secondary Unit Digits"
+msgstr ""
+
+msgctxt "field:sale.line,secondary_unit_price:"
+msgid "Secondary Unit Price"
+msgstr ""
+
+msgctxt "field:sale.line,secondary_uom_factor:"
+msgid "Secondary UOM Factor"
+msgstr ""
+
+msgctxt "field:sale.line,secondary_uom_rate:"
+msgid "Secondary UOM Rate"
+msgstr ""
+
+msgctxt "field:sale.product_customer,default_uom_category:"
+msgid "Default UOM Category"
+msgstr ""
+
+msgctxt "field:sale.product_customer,sale_secondary_uom:"
+msgid "Sale Secondary UOM"
+msgstr ""
+
+msgctxt "field:sale.product_customer,sale_secondary_uom_factor:"
+msgid "Sale Secondary UOM Factor"
+msgstr ""
+
+msgctxt "field:sale.product_customer,sale_secondary_uom_rate:"
+msgid "Sale Secondary UOM Rate"
+msgstr ""
+
+msgctxt "help:product.product,sale_secondary_uom_factor:"
+msgid ""
+"The coefficient for the formula:\n"
+"1 (sale unit) = coefficient (secondary unit)"
+msgstr ""
+
+msgctxt "help:product.product,sale_secondary_uom_rate:"
+msgid ""
+"The coefficient for the formula:\n"
+"coefficient (sale unit) = 1 (secondary unit)"
+msgstr ""
+
+msgctxt "help:product.template,sale_secondary_uom_factor:"
+msgid ""
+"The coefficient for the formula:\n"
+"1 (sale unit) = coefficient (secondary unit)"
+msgstr ""
+
+msgctxt "help:product.template,sale_secondary_uom_rate:"
+msgid ""
+"The coefficient for the formula:\n"
+"coefficient (sale unit) = 1 (secondary unit)"
+msgstr ""
+
+msgctxt "help:sale.product_customer,sale_secondary_uom_factor:"
+msgid ""
+"The coefficient for the formula:\n"
+"1 (sale unit) = coefficient (secondary unit)"
+msgstr ""
+
+msgctxt "help:sale.product_customer,sale_secondary_uom_rate:"
+msgid ""
+"The coefficient for the formula:\n"
+"coefficient (sale unit) = 1 (secondary unit)"
+msgstr ""
+
+msgctxt ""
+"model:ir.message,text:msg_sale_secondary_uom_incompatible_factor_rate"
+msgid "Incompatible sale secondary factor and rate values for \"%(record)s\"."
+msgstr ""
+
+msgctxt "view:product.template:"
+msgid "Factor:"
+msgstr ""
+
+msgctxt "view:product.template:"
+msgid "Rate:"
+msgstr ""
+
+msgctxt "view:sale.line:"
+msgid "Quantity:"
+msgstr ""
+
+msgctxt "view:sale.line:"
+msgid "Unit Price:"
+msgstr ""
+
+msgctxt "view:sale.line:"
+msgid "Unit:"
+msgstr ""
+
+msgctxt "view:sale.product_customer:"
+msgid "Factor:"
+msgstr ""
+
+msgctxt "view:sale.product_customer:"
+msgid "Rate:"
+msgstr ""
diff --git a/modules/sale_secondary_unit/locale/fr.po b/modules/sale_secondary_unit/locale/fr.po
new file mode 100644
index 0000000000..e7cd7b5d8e
--- /dev/null
+++ b/modules/sale_secondary_unit/locale/fr.po
@@ -0,0 +1,153 @@
+#
+msgid ""
+msgstr "Content-Type: text/plain; charset=utf-8\n"
+
+msgctxt "field:product.product,sale_secondary_uom:"
+msgid "Sale Secondary UOM"
+msgstr "UDM secondaire de vente"
+
+msgctxt "field:product.product,sale_secondary_uom_factor:"
+msgid "Sale Secondary UOM Factor"
+msgstr "Facture d'unité de mesure secondaire de vente"
+
+msgctxt "field:product.product,sale_secondary_uom_rate:"
+msgid "Sale Secondary UOM Rate"
+msgstr "Taux d'UDM secondaire de vente"
+
+msgctxt "field:product.template,sale_secondary_uom:"
+msgid "Sale Secondary UOM"
+msgstr "UDM secondaire de vente"
+
+msgctxt "field:product.template,sale_secondary_uom_factor:"
+msgid "Sale Secondary UOM Factor"
+msgstr "Facteur d'UDM secondaire de vente"
+
+msgctxt "field:product.template,sale_secondary_uom_rate:"
+msgid "Sale Secondary UOM Rate"
+msgstr "Taux d'UDM secondaire de vente"
+
+msgctxt "field:sale.line,product_secondary_uom_category:"
+msgid "Product Secondary UOM Category"
+msgstr "Catégorie d'UDM secondaire du produit"
+
+msgctxt "field:sale.line,secondary_quantity:"
+msgid "Secondary Quantity"
+msgstr "Quantité secondaire"
+
+msgctxt "field:sale.line,secondary_unit:"
+msgid "Secondary Unit"
+msgstr "Unité secondaire"
+
+msgctxt "field:sale.line,secondary_unit_digits:"
+msgid "Secondary Unit Digits"
+msgstr "Décimales d'unité secondaire"
+
+msgctxt "field:sale.line,secondary_unit_price:"
+msgid "Secondary Unit Price"
+msgstr "Prix unitaire secondaire"
+
+msgctxt "field:sale.line,secondary_uom_factor:"
+msgid "Secondary UOM Factor"
+msgstr "Facteur d'UDM secondaire"
+
+msgctxt "field:sale.line,secondary_uom_rate:"
+msgid "Secondary UOM Rate"
+msgstr "Taux d'UDM secondaire"
+
+msgctxt "field:sale.product_customer,default_uom_category:"
+msgid "Default UOM Category"
+msgstr "Catégorie d'UDM par défaut"
+
+msgctxt "field:sale.product_customer,sale_secondary_uom:"
+msgid "Sale Secondary UOM"
+msgstr "UDM secondaire de vente"
+
+msgctxt "field:sale.product_customer,sale_secondary_uom_factor:"
+msgid "Sale Secondary UOM Factor"
+msgstr "Facture d'unité de mesure secondaire de vente"
+
+msgctxt "field:sale.product_customer,sale_secondary_uom_rate:"
+msgid "Sale Secondary UOM Rate"
+msgstr "Taux d'UDM secondaire de vente"
+
+msgctxt "help:product.product,sale_secondary_uom_factor:"
+msgid ""
+"The coefficient for the formula:\n"
+"1 (sale unit) = coefficient (secondary unit)"
+msgstr ""
+"Le coefficient pour la formule :\n"
+"1 (unité de vente) = coefficient (unité secondaire)"
+
+msgctxt "help:product.product,sale_secondary_uom_rate:"
+msgid ""
+"The coefficient for the formula:\n"
+"coefficient (sale unit) = 1 (secondary unit)"
+msgstr ""
+"Le coefficient pour la formule :\n"
+"coefficient (unité de vente) = 1 (unité secondaire)"
+
+msgctxt "help:product.template,sale_secondary_uom_factor:"
+msgid ""
+"The coefficient for the formula:\n"
+"1 (sale unit) = coefficient (secondary unit)"
+msgstr ""
+"Le coefficient pour la formule :\n"
+"1 (unité de vente) = coefficient (unité secondaire)"
+
+msgctxt "help:product.template,sale_secondary_uom_rate:"
+msgid ""
+"The coefficient for the formula:\n"
+"coefficient (sale unit) = 1 (secondary unit)"
+msgstr ""
+"Le coefficient pour la formule :\n"
+"coefficient (unité de vente) = 1 (unité secondaire)"
+
+msgctxt "help:sale.product_customer,sale_secondary_uom_factor:"
+msgid ""
+"The coefficient for the formula:\n"
+"1 (sale unit) = coefficient (secondary unit)"
+msgstr ""
+"Le coefficient pour la formule :\n"
+"1 (unité de vente) = coefficient (unité secondaire)"
+
+msgctxt "help:sale.product_customer,sale_secondary_uom_rate:"
+msgid ""
+"The coefficient for the formula:\n"
+"coefficient (sale unit) = 1 (secondary unit)"
+msgstr ""
+"Le coefficient pour la formule :\n"
+"coefficient (unité de vente) = 1 (unité secondaire)"
+
+msgctxt ""
+"model:ir.message,text:msg_sale_secondary_uom_incompatible_factor_rate"
+msgid "Incompatible sale secondary factor and rate values for \"%(record)s\"."
+msgstr ""
+"Facteur et taux secondaires de vente incompatibles pour « %(record)s »."
+
+msgctxt "view:product.template:"
+msgid "Factor:"
+msgstr "Facteur :"
+
+msgctxt "view:product.template:"
+msgid "Rate:"
+msgstr "Taux :"
+
+msgctxt "view:sale.line:"
+msgid "Quantity:"
+msgstr "Quantité :"
+
+msgctxt "view:sale.line:"
+msgid "Unit Price:"
+msgstr "Prix unitaire :"
+
+msgctxt "view:sale.line:"
+msgid "Unit:"
+msgstr "Unité :"
+
+msgctxt "view:sale.product_customer:"
+msgid "Factor:"
+msgstr "Facteur :"
+
+msgctxt "view:sale.product_customer:"
+msgid "Rate:"
+msgstr "Taux :"
diff --git a/modules/sale_secondary_unit/locale/hu.po b/modules/sale_secondary_unit/locale/hu.po
new file mode 100644
index 0000000000..b91ff365cf
--- /dev/null
+++ b/modules/sale_secondary_unit/locale/hu.po
@@ -0,0 +1,140 @@
+#
+msgid ""
+msgstr "Content-Type: text/plain; charset=utf-8\n"
+
+msgctxt "field:product.product,sale_secondary_uom:"
+msgid "Sale Secondary UOM"
+msgstr ""
+
+msgctxt "field:product.product,sale_secondary_uom_factor:"
+msgid "Sale Secondary UOM Factor"
+msgstr ""
+
+msgctxt "field:product.product,sale_secondary_uom_rate:"
+msgid "Sale Secondary UOM Rate"
+msgstr ""
+
+msgctxt "field:product.template,sale_secondary_uom:"
+msgid "Sale Secondary UOM"
+msgstr ""
+
+msgctxt "field:product.template,sale_secondary_uom_factor:"
+msgid "Sale Secondary UOM Factor"
+msgstr ""
+
+msgctxt "field:product.template,sale_secondary_uom_rate:"
+msgid "Sale Secondary UOM Rate"
+msgstr ""
+
+msgctxt "field:sale.line,product_secondary_uom_category:"
+msgid "Product Secondary UOM Category"
+msgstr ""
+
+msgctxt "field:sale.line,secondary_quantity:"
+msgid "Secondary Quantity"
+msgstr ""
+
+msgctxt "field:sale.line,secondary_unit:"
+msgid "Secondary Unit"
+msgstr ""
+
+msgctxt "field:sale.line,secondary_unit_digits:"
+msgid "Secondary Unit Digits"
+msgstr ""
+
+msgctxt "field:sale.line,secondary_unit_price:"
+msgid "Secondary Unit Price"
+msgstr ""
+
+msgctxt "field:sale.line,secondary_uom_factor:"
+msgid "Secondary UOM Factor"
+msgstr ""
+
+msgctxt "field:sale.line,secondary_uom_rate:"
+msgid "Secondary UOM Rate"
+msgstr ""
+
+msgctxt "field:sale.product_customer,default_uom_category:"
+msgid "Default UOM Category"
+msgstr ""
+
+msgctxt "field:sale.product_customer,sale_secondary_uom:"
+msgid "Sale Secondary UOM"
+msgstr ""
+
+msgctxt "field:sale.product_customer,sale_secondary_uom_factor:"
+msgid "Sale Secondary UOM Factor"
+msgstr ""
+
+msgctxt "field:sale.product_customer,sale_secondary_uom_rate:"
+msgid "Sale Secondary UOM Rate"
+msgstr ""
+
+msgctxt "help:product.product,sale_secondary_uom_factor:"
+msgid ""
+"The coefficient for the formula:\n"
+"1 (sale unit) = coefficient (secondary unit)"
+msgstr ""
+
+msgctxt "help:product.product,sale_secondary_uom_rate:"
+msgid ""
+"The coefficient for the formula:\n"
+"coefficient (sale unit) = 1 (secondary unit)"
+msgstr ""
+
+msgctxt "help:product.template,sale_secondary_uom_factor:"
+msgid ""
+"The coefficient for the formula:\n"
+"1 (sale unit) = coefficient (secondary unit)"
+msgstr ""
+
+msgctxt "help:product.template,sale_secondary_uom_rate:"
+msgid ""
+"The coefficient for the formula:\n"
+"coefficient (sale unit) = 1 (secondary unit)"
+msgstr ""
+
+msgctxt "help:sale.product_customer,sale_secondary_uom_factor:"
+msgid ""
+"The coefficient for the formula:\n"
+"1 (sale unit) = coefficient (secondary unit)"
+msgstr ""
+
+msgctxt "help:sale.product_customer,sale_secondary_uom_rate:"
+msgid ""
+"The coefficient for the formula:\n"
+"coefficient (sale unit) = 1 (secondary unit)"
+msgstr ""
+
+msgctxt ""
+"model:ir.message,text:msg_sale_secondary_uom_incompatible_factor_rate"
+msgid "Incompatible sale secondary factor and rate values for \"%(record)s\"."
+msgstr ""
+
+msgctxt "view:product.template:"
+msgid "Factor:"
+msgstr ""
+
+msgctxt "view:product.template:"
+msgid "Rate:"
+msgstr ""
+
+msgctxt "view:sale.line:"
+msgid "Quantity:"
+msgstr ""
+
+msgctxt "view:sale.line:"
+msgid "Unit Price:"
+msgstr ""
+
+msgctxt "view:sale.line:"
+msgid "Unit:"
+msgstr ""
+
+msgctxt "view:sale.product_customer:"
+msgid "Factor:"
+msgstr ""
+
+msgctxt "view:sale.product_customer:"
+msgid "Rate:"
+msgstr ""
diff --git a/modules/sale_secondary_unit/locale/id.po b/modules/sale_secondary_unit/locale/id.po
new file mode 100644
index 0000000000..b91ff365cf
--- /dev/null
+++ b/modules/sale_secondary_unit/locale/id.po
@@ -0,0 +1,140 @@
+#
+msgid ""
+msgstr "Content-Type: text/plain; charset=utf-8\n"
+
+msgctxt "field:product.product,sale_secondary_uom:"
+msgid "Sale Secondary UOM"
+msgstr ""
+
+msgctxt "field:product.product,sale_secondary_uom_factor:"
+msgid "Sale Secondary UOM Factor"
+msgstr ""
+
+msgctxt "field:product.product,sale_secondary_uom_rate:"
+msgid "Sale Secondary UOM Rate"
+msgstr ""
+
+msgctxt "field:product.template,sale_secondary_uom:"
+msgid "Sale Secondary UOM"
+msgstr ""
+
+msgctxt "field:product.template,sale_secondary_uom_factor:"
+msgid "Sale Secondary UOM Factor"
+msgstr ""
+
+msgctxt "field:product.template,sale_secondary_uom_rate:"
+msgid "Sale Secondary UOM Rate"
+msgstr ""
+
+msgctxt "field:sale.line,product_secondary_uom_category:"
+msgid "Product Secondary UOM Category"
+msgstr ""
+
+msgctxt "field:sale.line,secondary_quantity:"
+msgid "Secondary Quantity"
+msgstr ""
+
+msgctxt "field:sale.line,secondary_unit:"
+msgid "Secondary Unit"
+msgstr ""
+
+msgctxt "field:sale.line,secondary_unit_digits:"
+msgid "Secondary Unit Digits"
+msgstr ""
+
+msgctxt "field:sale.line,secondary_unit_price:"
+msgid "Secondary Unit Price"
+msgstr ""
+
+msgctxt "field:sale.line,secondary_uom_factor:"
+msgid "Secondary UOM Factor"
+msgstr ""
+
+msgctxt "field:sale.line,secondary_uom_rate:"
+msgid "Secondary UOM Rate"
+msgstr ""
+
+msgctxt "field:sale.product_customer,default_uom_category:"
+msgid "Default UOM Category"
+msgstr ""
+
+msgctxt "field:sale.product_customer,sale_secondary_uom:"
+msgid "Sale Secondary UOM"
+msgstr ""
+
+msgctxt "field:sale.product_customer,sale_secondary_uom_factor:"
+msgid "Sale Secondary UOM Factor"
+msgstr ""
+
+msgctxt "field:sale.product_customer,sale_secondary_uom_rate:"
+msgid "Sale Secondary UOM Rate"
+msgstr ""
+
+msgctxt "help:product.product,sale_secondary_uom_factor:"
+msgid ""
+"The coefficient for the formula:\n"
+"1 (sale unit) = coefficient (secondary unit)"
+msgstr ""
+
+msgctxt "help:product.product,sale_secondary_uom_rate:"
+msgid ""
+"The coefficient for the formula:\n"
+"coefficient (sale unit) = 1 (secondary unit)"
+msgstr ""
+
+msgctxt "help:product.template,sale_secondary_uom_factor:"
+msgid ""
+"The coefficient for the formula:\n"
+"1 (sale unit) = coefficient (secondary unit)"
+msgstr ""
+
+msgctxt "help:product.template,sale_secondary_uom_rate:"
+msgid ""
+"The coefficient for the formula:\n"
+"coefficient (sale unit) = 1 (secondary unit)"
+msgstr ""
+
+msgctxt "help:sale.product_customer,sale_secondary_uom_factor:"
+msgid ""
+"The coefficient for the formula:\n"
+"1 (sale unit) = coefficient (secondary unit)"
+msgstr ""
+
+msgctxt "help:sale.product_customer,sale_secondary_uom_rate:"
+msgid ""
+"The coefficient for the formula:\n"
+"coefficient (sale unit) = 1 (secondary unit)"
+msgstr ""
+
+msgctxt ""
+"model:ir.message,text:msg_sale_secondary_uom_incompatible_factor_rate"
+msgid "Incompatible sale secondary factor and rate values for \"%(record)s\"."
+msgstr ""
+
+msgctxt "view:product.template:"
+msgid "Factor:"
+msgstr ""
+
+msgctxt "view:product.template:"
+msgid "Rate:"
+msgstr ""
+
+msgctxt "view:sale.line:"
+msgid "Quantity:"
+msgstr ""
+
+msgctxt "view:sale.line:"
+msgid "Unit Price:"
+msgstr ""
+
+msgctxt "view:sale.line:"
+msgid "Unit:"
+msgstr ""
+
+msgctxt "view:sale.product_customer:"
+msgid "Factor:"
+msgstr ""
+
+msgctxt "view:sale.product_customer:"
+msgid "Rate:"
+msgstr ""
diff --git a/modules/sale_secondary_unit/locale/it.po b/modules/sale_secondary_unit/locale/it.po
new file mode 100644
index 0000000000..b91ff365cf
--- /dev/null
+++ b/modules/sale_secondary_unit/locale/it.po
@@ -0,0 +1,140 @@
+#
+msgid ""
+msgstr "Content-Type: text/plain; charset=utf-8\n"
+
+msgctxt "field:product.product,sale_secondary_uom:"
+msgid "Sale Secondary UOM"
+msgstr ""
+
+msgctxt "field:product.product,sale_secondary_uom_factor:"
+msgid "Sale Secondary UOM Factor"
+msgstr ""
+
+msgctxt "field:product.product,sale_secondary_uom_rate:"
+msgid "Sale Secondary UOM Rate"
+msgstr ""
+
+msgctxt "field:product.template,sale_secondary_uom:"
+msgid "Sale Secondary UOM"
+msgstr ""
+
+msgctxt "field:product.template,sale_secondary_uom_factor:"
+msgid "Sale Secondary UOM Factor"
+msgstr ""
+
+msgctxt "field:product.template,sale_secondary_uom_rate:"
+msgid "Sale Secondary UOM Rate"
+msgstr ""
+
+msgctxt "field:sale.line,product_secondary_uom_category:"
+msgid "Product Secondary UOM Category"
+msgstr ""
+
+msgctxt "field:sale.line,secondary_quantity:"
+msgid "Secondary Quantity"
+msgstr ""
+
+msgctxt "field:sale.line,secondary_unit:"
+msgid "Secondary Unit"
+msgstr ""
+
+msgctxt "field:sale.line,secondary_unit_digits:"
+msgid "Secondary Unit Digits"
+msgstr ""
+
+msgctxt "field:sale.line,secondary_unit_price:"
+msgid "Secondary Unit Price"
+msgstr ""
+
+msgctxt "field:sale.line,secondary_uom_factor:"
+msgid "Secondary UOM Factor"
+msgstr ""
+
+msgctxt "field:sale.line,secondary_uom_rate:"
+msgid "Secondary UOM Rate"
+msgstr ""
+
+msgctxt "field:sale.product_customer,default_uom_category:"
+msgid "Default UOM Category"
+msgstr ""
+
+msgctxt "field:sale.product_customer,sale_secondary_uom:"
+msgid "Sale Secondary UOM"
+msgstr ""
+
+msgctxt "field:sale.product_customer,sale_secondary_uom_factor:"
+msgid "Sale Secondary UOM Factor"
+msgstr ""
+
+msgctxt "field:sale.product_customer,sale_secondary_uom_rate:"
+msgid "Sale Secondary UOM Rate"
+msgstr ""
+
+msgctxt "help:product.product,sale_secondary_uom_factor:"
+msgid ""
+"The coefficient for the formula:\n"
+"1 (sale unit) = coefficient (secondary unit)"
+msgstr ""
+
+msgctxt "help:product.product,sale_secondary_uom_rate:"
+msgid ""
+"The coefficient for the formula:\n"
+"coefficient (sale unit) = 1 (secondary unit)"
+msgstr ""
+
+msgctxt "help:product.template,sale_secondary_uom_factor:"
+msgid ""
+"The coefficient for the formula:\n"
+"1 (sale unit) = coefficient (secondary unit)"
+msgstr ""
+
+msgctxt "help:product.template,sale_secondary_uom_rate:"
+msgid ""
+"The coefficient for the formula:\n"
+"coefficient (sale unit) = 1 (secondary unit)"
+msgstr ""
+
+msgctxt "help:sale.product_customer,sale_secondary_uom_factor:"
+msgid ""
+"The coefficient for the formula:\n"
+"1 (sale unit) = coefficient (secondary unit)"
+msgstr ""
+
+msgctxt "help:sale.product_customer,sale_secondary_uom_rate:"
+msgid ""
+"The coefficient for the formula:\n"
+"coefficient (sale unit) = 1 (secondary unit)"
+msgstr ""
+
+msgctxt ""
+"model:ir.message,text:msg_sale_secondary_uom_incompatible_factor_rate"
+msgid "Incompatible sale secondary factor and rate values for \"%(record)s\"."
+msgstr ""
+
+msgctxt "view:product.template:"
+msgid "Factor:"
+msgstr ""
+
+msgctxt "view:product.template:"
+msgid "Rate:"
+msgstr ""
+
+msgctxt "view:sale.line:"
+msgid "Quantity:"
+msgstr ""
+
+msgctxt "view:sale.line:"
+msgid "Unit Price:"
+msgstr ""
+
+msgctxt "view:sale.line:"
+msgid "Unit:"
+msgstr ""
+
+msgctxt "view:sale.product_customer:"
+msgid "Factor:"
+msgstr ""
+
+msgctxt "view:sale.product_customer:"
+msgid "Rate:"
+msgstr ""
diff --git a/modules/sale_secondary_unit/locale/lo.po b/modules/sale_secondary_unit/locale/lo.po
new file mode 100644
index 0000000000..b91ff365cf
--- /dev/null
+++ b/modules/sale_secondary_unit/locale/lo.po
@@ -0,0 +1,140 @@
+#
+msgid ""
+msgstr "Content-Type: text/plain; charset=utf-8\n"
+
+msgctxt "field:product.product,sale_secondary_uom:"
+msgid "Sale Secondary UOM"
+msgstr ""
+
+msgctxt "field:product.product,sale_secondary_uom_factor:"
+msgid "Sale Secondary UOM Factor"
+msgstr ""
+
+msgctxt "field:product.product,sale_secondary_uom_rate:"
+msgid "Sale Secondary UOM Rate"
+msgstr ""
+
+msgctxt "field:product.template,sale_secondary_uom:"
+msgid "Sale Secondary UOM"
+msgstr ""
+
+msgctxt "field:product.template,sale_secondary_uom_factor:"
+msgid "Sale Secondary UOM Factor"
+msgstr ""
+
+msgctxt "field:product.template,sale_secondary_uom_rate:"
+msgid "Sale Secondary UOM Rate"
+msgstr ""
+
+msgctxt "field:sale.line,product_secondary_uom_category:"
+msgid "Product Secondary UOM Category"
+msgstr ""
+
+msgctxt "field:sale.line,secondary_quantity:"
+msgid "Secondary Quantity"
+msgstr ""
+
+msgctxt "field:sale.line,secondary_unit:"
+msgid "Secondary Unit"
+msgstr ""
+
+msgctxt "field:sale.line,secondary_unit_digits:"
+msgid "Secondary Unit Digits"
+msgstr ""
+
+msgctxt "field:sale.line,secondary_unit_price:"
+msgid "Secondary Unit Price"
+msgstr ""
+
+msgctxt "field:sale.line,secondary_uom_factor:"
+msgid "Secondary UOM Factor"
+msgstr ""
+
+msgctxt "field:sale.line,secondary_uom_rate:"
+msgid "Secondary UOM Rate"
+msgstr ""
+
+msgctxt "field:sale.product_customer,default_uom_category:"
+msgid "Default UOM Category"
+msgstr ""
+
+msgctxt "field:sale.product_customer,sale_secondary_uom:"
+msgid "Sale Secondary UOM"
+msgstr ""
+
+msgctxt "field:sale.product_customer,sale_secondary_uom_factor:"
+msgid "Sale Secondary UOM Factor"
+msgstr ""
+
+msgctxt "field:sale.product_customer,sale_secondary_uom_rate:"
+msgid "Sale Secondary UOM Rate"
+msgstr ""
+
+msgctxt "help:product.product,sale_secondary_uom_factor:"
+msgid ""
+"The coefficient for the formula:\n"
+"1 (sale unit) = coefficient (secondary unit)"
+msgstr ""
+
+msgctxt "help:product.product,sale_secondary_uom_rate:"
+msgid ""
+"The coefficient for the formula:\n"
+"coefficient (sale unit) = 1 (secondary unit)"
+msgstr ""
+
+msgctxt "help:product.template,sale_secondary_uom_factor:"
+msgid ""
+"The coefficient for the formula:\n"
+"1 (sale unit) = coefficient (secondary unit)"
+msgstr ""
+
+msgctxt "help:product.template,sale_secondary_uom_rate:"
+msgid ""
+"The coefficient for the formula:\n"
+"coefficient (sale unit) = 1 (secondary unit)"
+msgstr ""
+
+msgctxt "help:sale.product_customer,sale_secondary_uom_factor:"
+msgid ""
+"The coefficient for the formula:\n"
+"1 (sale unit) = coefficient (secondary unit)"
+msgstr ""
+
+msgctxt "help:sale.product_customer,sale_secondary_uom_rate:"
+msgid ""
+"The coefficient for the formula:\n"
+"coefficient (sale unit) = 1 (secondary unit)"
+msgstr ""
+
+msgctxt ""
+"model:ir.message,text:msg_sale_secondary_uom_incompatible_factor_rate"
+msgid "Incompatible sale secondary factor and rate values for \"%(record)s\"."
+msgstr ""
+
+msgctxt "view:product.template:"
+msgid "Factor:"
+msgstr ""
+
+msgctxt "view:product.template:"
+msgid "Rate:"
+msgstr ""
+
+msgctxt "view:sale.line:"
+msgid "Quantity:"
+msgstr ""
+
+msgctxt "view:sale.line:"
+msgid "Unit Price:"
+msgstr ""
+
+msgctxt "view:sale.line:"
+msgid "Unit:"
+msgstr ""
+
+msgctxt "view:sale.product_customer:"
+msgid "Factor:"
+msgstr ""
+
+msgctxt "view:sale.product_customer:"
+msgid "Rate:"
+msgstr ""
diff --git a/modules/sale_secondary_unit/locale/lt.po b/modules/sale_secondary_unit/locale/lt.po
new file mode 100644
index 0000000000..b91ff365cf
--- /dev/null
+++ b/modules/sale_secondary_unit/locale/lt.po
@@ -0,0 +1,140 @@
+#
+msgid ""
+msgstr "Content-Type: text/plain; charset=utf-8\n"
+
+msgctxt "field:product.product,sale_secondary_uom:"
+msgid "Sale Secondary UOM"
+msgstr ""
+
+msgctxt "field:product.product,sale_secondary_uom_factor:"
+msgid "Sale Secondary UOM Factor"
+msgstr ""
+
+msgctxt "field:product.product,sale_secondary_uom_rate:"
+msgid "Sale Secondary UOM Rate"
+msgstr ""
+
+msgctxt "field:product.template,sale_secondary_uom:"
+msgid "Sale Secondary UOM"
+msgstr ""
+
+msgctxt "field:product.template,sale_secondary_uom_factor:"
+msgid "Sale Secondary UOM Factor"
+msgstr ""
+
+msgctxt "field:product.template,sale_secondary_uom_rate:"
+msgid "Sale Secondary UOM Rate"
+msgstr ""
+
+msgctxt "field:sale.line,product_secondary_uom_category:"
+msgid "Product Secondary UOM Category"
+msgstr ""
+
+msgctxt "field:sale.line,secondary_quantity:"
+msgid "Secondary Quantity"
+msgstr ""
+
+msgctxt "field:sale.line,secondary_unit:"
+msgid "Secondary Unit"
+msgstr ""
+
+msgctxt "field:sale.line,secondary_unit_digits:"
+msgid "Secondary Unit Digits"
+msgstr ""
+
+msgctxt "field:sale.line,secondary_unit_price:"
+msgid "Secondary Unit Price"
+msgstr ""
+
+msgctxt "field:sale.line,secondary_uom_factor:"
+msgid "Secondary UOM Factor"
+msgstr ""
+
+msgctxt "field:sale.line,secondary_uom_rate:"
+msgid "Secondary UOM Rate"
+msgstr ""
+
+msgctxt "field:sale.product_customer,default_uom_category:"
+msgid "Default UOM Category"
+msgstr ""
+
+msgctxt "field:sale.product_customer,sale_secondary_uom:"
+msgid "Sale Secondary UOM"
+msgstr ""
+
+msgctxt "field:sale.product_customer,sale_secondary_uom_factor:"
+msgid "Sale Secondary UOM Factor"
+msgstr ""
+
+msgctxt "field:sale.product_customer,sale_secondary_uom_rate:"
+msgid "Sale Secondary UOM Rate"
+msgstr ""
+
+msgctxt "help:product.product,sale_secondary_uom_factor:"
+msgid ""
+"The coefficient for the formula:\n"
+"1 (sale unit) = coefficient (secondary unit)"
+msgstr ""
+
+msgctxt "help:product.product,sale_secondary_uom_rate:"
+msgid ""
+"The coefficient for the formula:\n"
+"coefficient (sale unit) = 1 (secondary unit)"
+msgstr ""
+
+msgctxt "help:product.template,sale_secondary_uom_factor:"
+msgid ""
+"The coefficient for the formula:\n"
+"1 (sale unit) = coefficient (secondary unit)"
+msgstr ""
+
+msgctxt "help:product.template,sale_secondary_uom_rate:"
+msgid ""
+"The coefficient for the formula:\n"
+"coefficient (sale unit) = 1 (secondary unit)"
+msgstr ""
+
+msgctxt "help:sale.product_customer,sale_secondary_uom_factor:"
+msgid ""
+"The coefficient for the formula:\n"
+"1 (sale unit) = coefficient (secondary unit)"
+msgstr ""
+
+msgctxt "help:sale.product_customer,sale_secondary_uom_rate:"
+msgid ""
+"The coefficient for the formula:\n"
+"coefficient (sale unit) = 1 (secondary unit)"
+msgstr ""
+
+msgctxt ""
+"model:ir.message,text:msg_sale_secondary_uom_incompatible_factor_rate"
+msgid "Incompatible sale secondary factor and rate values for \"%(record)s\"."
+msgstr ""
+
+msgctxt "view:product.template:"
+msgid "Factor:"
+msgstr ""
+
+msgctxt "view:product.template:"
+msgid "Rate:"
+msgstr ""
+
+msgctxt "view:sale.line:"
+msgid "Quantity:"
+msgstr ""
+
+msgctxt "view:sale.line:"
+msgid "Unit Price:"
+msgstr ""
+
+msgctxt "view:sale.line:"
+msgid "Unit:"
+msgstr ""
+
+msgctxt "view:sale.product_customer:"
+msgid "Factor:"
+msgstr ""
+
+msgctxt "view:sale.product_customer:"
+msgid "Rate:"
+msgstr ""
diff --git a/modules/sale_secondary_unit/locale/nl.po b/modules/sale_secondary_unit/locale/nl.po
new file mode 100644
index 0000000000..089e432ecf
--- /dev/null
+++ b/modules/sale_secondary_unit/locale/nl.po
@@ -0,0 +1,154 @@
+#
+msgid ""
+msgstr "Content-Type: text/plain; charset=utf-8\n"
+
+msgctxt "field:product.product,sale_secondary_uom:"
+msgid "Sale Secondary UOM"
+msgstr "Verkoop Secundaire maateenheid"
+
+msgctxt "field:product.product,sale_secondary_uom_factor:"
+msgid "Sale Secondary UOM Factor"
+msgstr "secundaire maateenheid factor"
+
+msgctxt "field:product.product,sale_secondary_uom_rate:"
+msgid "Sale Secondary UOM Rate"
+msgstr "Verkoop Secundair maateenheid-tarief"
+
+msgctxt "field:product.template,sale_secondary_uom:"
+msgid "Sale Secondary UOM"
+msgstr "Verkoop Secundaire maateenheid"
+
+msgctxt "field:product.template,sale_secondary_uom_factor:"
+msgid "Sale Secondary UOM Factor"
+msgstr "Verkoop Secundaire maateenheid-factor"
+
+msgctxt "field:product.template,sale_secondary_uom_rate:"
+msgid "Sale Secondary UOM Rate"
+msgstr "Verkoop Secundair maateenheid-tarief"
+
+msgctxt "field:sale.line,product_secondary_uom_category:"
+msgid "Product Secondary UOM Category"
+msgstr "Product secundaire maateenheid categorie"
+
+msgctxt "field:sale.line,secondary_quantity:"
+msgid "Secondary Quantity"
+msgstr "Secundaire hoeveelheid"
+
+msgctxt "field:sale.line,secondary_unit:"
+msgid "Secondary Unit"
+msgstr "Secundaire eenheid"
+
+msgctxt "field:sale.line,secondary_unit_digits:"
+msgid "Secondary Unit Digits"
+msgstr "decimalen secondaire eenheid"
+
+msgctxt "field:sale.line,secondary_unit_price:"
+msgid "Secondary Unit Price"
+msgstr "secundaire eenheidsprijs"
+
+msgctxt "field:sale.line,secondary_uom_factor:"
+msgid "Secondary UOM Factor"
+msgstr "secundaire maateenheid factor"
+
+msgctxt "field:sale.line,secondary_uom_rate:"
+msgid "Secondary UOM Rate"
+msgstr "secundaire maateenheid waarde"
+
+msgctxt "field:sale.product_customer,default_uom_category:"
+msgid "Default UOM Category"
+msgstr "Standaard maateenheid-categorie"
+
+msgctxt "field:sale.product_customer,sale_secondary_uom:"
+msgid "Sale Secondary UOM"
+msgstr "Verkoop Secundaire maateenheid"
+
+msgctxt "field:sale.product_customer,sale_secondary_uom_factor:"
+msgid "Sale Secondary UOM Factor"
+msgstr "Verkoop Secundaire maateenheid-factor"
+
+msgctxt "field:sale.product_customer,sale_secondary_uom_rate:"
+msgid "Sale Secondary UOM Rate"
+msgstr "Verkoop Secundair maateenheid-tarief"
+
+msgctxt "help:product.product,sale_secondary_uom_factor:"
+msgid ""
+"The coefficient for the formula:\n"
+"1 (sale unit) = coefficient (secondary unit)"
+msgstr ""
+"De coëfficiënt voor de formule:\n"
+"1 (verkoopeenheid) = coëfficiënt (secundaire eenheid)"
+
+msgctxt "help:product.product,sale_secondary_uom_rate:"
+msgid ""
+"The coefficient for the formula:\n"
+"coefficient (sale unit) = 1 (secondary unit)"
+msgstr ""
+"De coëfficiënt voor de formule:\n"
+"coëfficiënt (verkoopeenheid) = 1 (secundaire eenheid)"
+
+msgctxt "help:product.template,sale_secondary_uom_factor:"
+msgid ""
+"The coefficient for the formula:\n"
+"1 (sale unit) = coefficient (secondary unit)"
+msgstr ""
+"De coëfficiënt voor de formule:\n"
+"1 (verkoopeenheid) = coëfficiënt (secundaire eenheid)"
+
+msgctxt "help:product.template,sale_secondary_uom_rate:"
+msgid ""
+"The coefficient for the formula:\n"
+"coefficient (sale unit) = 1 (secondary unit)"
+msgstr ""
+"De coëfficiënt voor de formule:\n"
+"coëfficiënt (verkoopeenheid) = 1 (secundaire eenheid)"
+
+msgctxt "help:sale.product_customer,sale_secondary_uom_factor:"
+msgid ""
+"The coefficient for the formula:\n"
+"1 (sale unit) = coefficient (secondary unit)"
+msgstr ""
+"De coëfficiënt voor de formule:\n"
+"1 (verkoopeenheid) = coëfficiënt (secundaire eenheid)"
+
+msgctxt "help:sale.product_customer,sale_secondary_uom_rate:"
+msgid ""
+"The coefficient for the formula:\n"
+"coefficient (sale unit) = 1 (secondary unit)"
+msgstr ""
+"De coëfficiënt voor de formule:\n"
+"coëfficiënt (verkoopeenheid) = 1 (secundaire eenheid)"
+
+msgctxt ""
+"model:ir.message,text:msg_sale_secondary_uom_incompatible_factor_rate"
+msgid "Incompatible sale secondary factor and rate values for \"%(record)s\"."
+msgstr ""
+"Incompatibele secundaire factor en waardebeoordeling (rate values ) voor "
+"\"%(record)s\"."
+
+msgctxt "view:product.template:"
+msgid "Factor:"
+msgstr "Factor:"
+
+msgctxt "view:product.template:"
+msgid "Rate:"
+msgstr "Waarde:"
+
+msgctxt "view:sale.line:"
+msgid "Quantity:"
+msgstr "Hoeveelheid:"
+
+msgctxt "view:sale.line:"
+msgid "Unit Price:"
+msgstr "Eenheid prijs:"
+
+msgctxt "view:sale.line:"
+msgid "Unit:"
+msgstr "Eenheid:"
+
+msgctxt "view:sale.product_customer:"
+msgid "Factor:"
+msgstr "Factor:"
+
+msgctxt "view:sale.product_customer:"
+msgid "Rate:"
+msgstr "Waarde:"
diff --git a/modules/sale_secondary_unit/locale/pl.po b/modules/sale_secondary_unit/locale/pl.po
new file mode 100644
index 0000000000..b91ff365cf
--- /dev/null
+++ b/modules/sale_secondary_unit/locale/pl.po
@@ -0,0 +1,140 @@
+#
+msgid ""
+msgstr "Content-Type: text/plain; charset=utf-8\n"
+
+msgctxt "field:product.product,sale_secondary_uom:"
+msgid "Sale Secondary UOM"
+msgstr ""
+
+msgctxt "field:product.product,sale_secondary_uom_factor:"
+msgid "Sale Secondary UOM Factor"
+msgstr ""
+
+msgctxt "field:product.product,sale_secondary_uom_rate:"
+msgid "Sale Secondary UOM Rate"
+msgstr ""
+
+msgctxt "field:product.template,sale_secondary_uom:"
+msgid "Sale Secondary UOM"
+msgstr ""
+
+msgctxt "field:product.template,sale_secondary_uom_factor:"
+msgid "Sale Secondary UOM Factor"
+msgstr ""
+
+msgctxt "field:product.template,sale_secondary_uom_rate:"
+msgid "Sale Secondary UOM Rate"
+msgstr ""
+
+msgctxt "field:sale.line,product_secondary_uom_category:"
+msgid "Product Secondary UOM Category"
+msgstr ""
+
+msgctxt "field:sale.line,secondary_quantity:"
+msgid "Secondary Quantity"
+msgstr ""
+
+msgctxt "field:sale.line,secondary_unit:"
+msgid "Secondary Unit"
+msgstr ""
+
+msgctxt "field:sale.line,secondary_unit_digits:"
+msgid "Secondary Unit Digits"
+msgstr ""
+
+msgctxt "field:sale.line,secondary_unit_price:"
+msgid "Secondary Unit Price"
+msgstr ""
+
+msgctxt "field:sale.line,secondary_uom_factor:"
+msgid "Secondary UOM Factor"
+msgstr ""
+
+msgctxt "field:sale.line,secondary_uom_rate:"
+msgid "Secondary UOM Rate"
+msgstr ""
+
+msgctxt "field:sale.product_customer,default_uom_category:"
+msgid "Default UOM Category"
+msgstr ""
+
+msgctxt "field:sale.product_customer,sale_secondary_uom:"
+msgid "Sale Secondary UOM"
+msgstr ""
+
+msgctxt "field:sale.product_customer,sale_secondary_uom_factor:"
+msgid "Sale Secondary UOM Factor"
+msgstr ""
+
+msgctxt "field:sale.product_customer,sale_secondary_uom_rate:"
+msgid "Sale Secondary UOM Rate"
+msgstr ""
+
+msgctxt "help:product.product,sale_secondary_uom_factor:"
+msgid ""
+"The coefficient for the formula:\n"
+"1 (sale unit) = coefficient (secondary unit)"
+msgstr ""
+
+msgctxt "help:product.product,sale_secondary_uom_rate:"
+msgid ""
+"The coefficient for the formula:\n"
+"coefficient (sale unit) = 1 (secondary unit)"
+msgstr ""
+
+msgctxt "help:product.template,sale_secondary_uom_factor:"
+msgid ""
+"The coefficient for the formula:\n"
+"1 (sale unit) = coefficient (secondary unit)"
+msgstr ""
+
+msgctxt "help:product.template,sale_secondary_uom_rate:"
+msgid ""
+"The coefficient for the formula:\n"
+"coefficient (sale unit) = 1 (secondary unit)"
+msgstr ""
+
+msgctxt "help:sale.product_customer,sale_secondary_uom_factor:"
+msgid ""
+"The coefficient for the formula:\n"
+"1 (sale unit) = coefficient (secondary unit)"
+msgstr ""
+
+msgctxt "help:sale.product_customer,sale_secondary_uom_rate:"
+msgid ""
+"The coefficient for the formula:\n"
+"coefficient (sale unit) = 1 (secondary unit)"
+msgstr ""
+
+msgctxt ""
+"model:ir.message,text:msg_sale_secondary_uom_incompatible_factor_rate"
+msgid "Incompatible sale secondary factor and rate values for \"%(record)s\"."
+msgstr ""
+
+msgctxt "view:product.template:"
+msgid "Factor:"
+msgstr ""
+
+msgctxt "view:product.template:"
+msgid "Rate:"
+msgstr ""
+
+msgctxt "view:sale.line:"
+msgid "Quantity:"
+msgstr ""
+
+msgctxt "view:sale.line:"
+msgid "Unit Price:"
+msgstr ""
+
+msgctxt "view:sale.line:"
+msgid "Unit:"
+msgstr ""
+
+msgctxt "view:sale.product_customer:"
+msgid "Factor:"
+msgstr ""
+
+msgctxt "view:sale.product_customer:"
+msgid "Rate:"
+msgstr ""
diff --git a/modules/sale_secondary_unit/locale/pt.po b/modules/sale_secondary_unit/locale/pt.po
new file mode 100644
index 0000000000..b91ff365cf
--- /dev/null
+++ b/modules/sale_secondary_unit/locale/pt.po
@@ -0,0 +1,140 @@
+#
+msgid ""
+msgstr "Content-Type: text/plain; charset=utf-8\n"
+
+msgctxt "field:product.product,sale_secondary_uom:"
+msgid "Sale Secondary UOM"
+msgstr ""
+
+msgctxt "field:product.product,sale_secondary_uom_factor:"
+msgid "Sale Secondary UOM Factor"
+msgstr ""
+
+msgctxt "field:product.product,sale_secondary_uom_rate:"
+msgid "Sale Secondary UOM Rate"
+msgstr ""
+
+msgctxt "field:product.template,sale_secondary_uom:"
+msgid "Sale Secondary UOM"
+msgstr ""
+
+msgctxt "field:product.template,sale_secondary_uom_factor:"
+msgid "Sale Secondary UOM Factor"
+msgstr ""
+
+msgctxt "field:product.template,sale_secondary_uom_rate:"
+msgid "Sale Secondary UOM Rate"
+msgstr ""
+
+msgctxt "field:sale.line,product_secondary_uom_category:"
+msgid "Product Secondary UOM Category"
+msgstr ""
+
+msgctxt "field:sale.line,secondary_quantity:"
+msgid "Secondary Quantity"
+msgstr ""
+
+msgctxt "field:sale.line,secondary_unit:"
+msgid "Secondary Unit"
+msgstr ""
+
+msgctxt "field:sale.line,secondary_unit_digits:"
+msgid "Secondary Unit Digits"
+msgstr ""
+
+msgctxt "field:sale.line,secondary_unit_price:"
+msgid "Secondary Unit Price"
+msgstr ""
+
+msgctxt "field:sale.line,secondary_uom_factor:"
+msgid "Secondary UOM Factor"
+msgstr ""
+
+msgctxt "field:sale.line,secondary_uom_rate:"
+msgid "Secondary UOM Rate"
+msgstr ""
+
+msgctxt "field:sale.product_customer,default_uom_category:"
+msgid "Default UOM Category"
+msgstr ""
+
+msgctxt "field:sale.product_customer,sale_secondary_uom:"
+msgid "Sale Secondary UOM"
+msgstr ""
+
+msgctxt "field:sale.product_customer,sale_secondary_uom_factor:"
+msgid "Sale Secondary UOM Factor"
+msgstr ""
+
+msgctxt "field:sale.product_customer,sale_secondary_uom_rate:"
+msgid "Sale Secondary UOM Rate"
+msgstr ""
+
+msgctxt "help:product.product,sale_secondary_uom_factor:"
+msgid ""
+"The coefficient for the formula:\n"
+"1 (sale unit) = coefficient (secondary unit)"
+msgstr ""
+
+msgctxt "help:product.product,sale_secondary_uom_rate:"
+msgid ""
+"The coefficient for the formula:\n"
+"coefficient (sale unit) = 1 (secondary unit)"
+msgstr ""
+
+msgctxt "help:product.template,sale_secondary_uom_factor:"
+msgid ""
+"The coefficient for the formula:\n"
+"1 (sale unit) = coefficient (secondary unit)"
+msgstr ""
+
+msgctxt "help:product.template,sale_secondary_uom_rate:"
+msgid ""
+"The coefficient for the formula:\n"
+"coefficient (sale unit) = 1 (secondary unit)"
+msgstr ""
+
+msgctxt "help:sale.product_customer,sale_secondary_uom_factor:"
+msgid ""
+"The coefficient for the formula:\n"
+"1 (sale unit) = coefficient (secondary unit)"
+msgstr ""
+
+msgctxt "help:sale.product_customer,sale_secondary_uom_rate:"
+msgid ""
+"The coefficient for the formula:\n"
+"coefficient (sale unit) = 1 (secondary unit)"
+msgstr ""
+
+msgctxt ""
+"model:ir.message,text:msg_sale_secondary_uom_incompatible_factor_rate"
+msgid "Incompatible sale secondary factor and rate values for \"%(record)s\"."
+msgstr ""
+
+msgctxt "view:product.template:"
+msgid "Factor:"
+msgstr ""
+
+msgctxt "view:product.template:"
+msgid "Rate:"
+msgstr ""
+
+msgctxt "view:sale.line:"
+msgid "Quantity:"
+msgstr ""
+
+msgctxt "view:sale.line:"
+msgid "Unit Price:"
+msgstr ""
+
+msgctxt "view:sale.line:"
+msgid "Unit:"
+msgstr ""
+
+msgctxt "view:sale.product_customer:"
+msgid "Factor:"
+msgstr ""
+
+msgctxt "view:sale.product_customer:"
+msgid "Rate:"
+msgstr ""
diff --git a/modules/sale_secondary_unit/locale/ro.po b/modules/sale_secondary_unit/locale/ro.po
new file mode 100644
index 0000000000..b91ff365cf
--- /dev/null
+++ b/modules/sale_secondary_unit/locale/ro.po
@@ -0,0 +1,140 @@
+#
+msgid ""
+msgstr "Content-Type: text/plain; charset=utf-8\n"
+
+msgctxt "field:product.product,sale_secondary_uom:"
+msgid "Sale Secondary UOM"
+msgstr ""
+
+msgctxt "field:product.product,sale_secondary_uom_factor:"
+msgid "Sale Secondary UOM Factor"
+msgstr ""
+
+msgctxt "field:product.product,sale_secondary_uom_rate:"
+msgid "Sale Secondary UOM Rate"
+msgstr ""
+
+msgctxt "field:product.template,sale_secondary_uom:"
+msgid "Sale Secondary UOM"
+msgstr ""
+
+msgctxt "field:product.template,sale_secondary_uom_factor:"
+msgid "Sale Secondary UOM Factor"
+msgstr ""
+
+msgctxt "field:product.template,sale_secondary_uom_rate:"
+msgid "Sale Secondary UOM Rate"
+msgstr ""
+
+msgctxt "field:sale.line,product_secondary_uom_category:"
+msgid "Product Secondary UOM Category"
+msgstr ""
+
+msgctxt "field:sale.line,secondary_quantity:"
+msgid "Secondary Quantity"
+msgstr ""
+
+msgctxt "field:sale.line,secondary_unit:"
+msgid "Secondary Unit"
+msgstr ""
+
+msgctxt "field:sale.line,secondary_unit_digits:"
+msgid "Secondary Unit Digits"
+msgstr ""
+
+msgctxt "field:sale.line,secondary_unit_price:"
+msgid "Secondary Unit Price"
+msgstr ""
+
+msgctxt "field:sale.line,secondary_uom_factor:"
+msgid "Secondary UOM Factor"
+msgstr ""
+
+msgctxt "field:sale.line,secondary_uom_rate:"
+msgid "Secondary UOM Rate"
+msgstr ""
+
+msgctxt "field:sale.product_customer,default_uom_category:"
+msgid "Default UOM Category"
+msgstr ""
+
+msgctxt "field:sale.product_customer,sale_secondary_uom:"
+msgid "Sale Secondary UOM"
+msgstr ""
+
+msgctxt "field:sale.product_customer,sale_secondary_uom_factor:"
+msgid "Sale Secondary UOM Factor"
+msgstr ""
+
+msgctxt "field:sale.product_customer,sale_secondary_uom_rate:"
+msgid "Sale Secondary UOM Rate"
+msgstr ""
+
+msgctxt "help:product.product,sale_secondary_uom_factor:"
+msgid ""
+"The coefficient for the formula:\n"
+"1 (sale unit) = coefficient (secondary unit)"
+msgstr ""
+
+msgctxt "help:product.product,sale_secondary_uom_rate:"
+msgid ""
+"The coefficient for the formula:\n"
+"coefficient (sale unit) = 1 (secondary unit)"
+msgstr ""
+
+msgctxt "help:product.template,sale_secondary_uom_factor:"
+msgid ""
+"The coefficient for the formula:\n"
+"1 (sale unit) = coefficient (secondary unit)"
+msgstr ""
+
+msgctxt "help:product.template,sale_secondary_uom_rate:"
+msgid ""
+"The coefficient for the formula:\n"
+"coefficient (sale unit) = 1 (secondary unit)"
+msgstr ""
+
+msgctxt "help:sale.product_customer,sale_secondary_uom_factor:"
+msgid ""
+"The coefficient for the formula:\n"
+"1 (sale unit) = coefficient (secondary unit)"
+msgstr ""
+
+msgctxt "help:sale.product_customer,sale_secondary_uom_rate:"
+msgid ""
+"The coefficient for the formula:\n"
+"coefficient (sale unit) = 1 (secondary unit)"
+msgstr ""
+
+msgctxt ""
+"model:ir.message,text:msg_sale_secondary_uom_incompatible_factor_rate"
+msgid "Incompatible sale secondary factor and rate values for \"%(record)s\"."
+msgstr ""
+
+msgctxt "view:product.template:"
+msgid "Factor:"
+msgstr ""
+
+msgctxt "view:product.template:"
+msgid "Rate:"
+msgstr ""
+
+msgctxt "view:sale.line:"
+msgid "Quantity:"
+msgstr ""
+
+msgctxt "view:sale.line:"
+msgid "Unit Price:"
+msgstr ""
+
+msgctxt "view:sale.line:"
+msgid "Unit:"
+msgstr ""
+
+msgctxt "view:sale.product_customer:"
+msgid "Factor:"
+msgstr ""
+
+msgctxt "view:sale.product_customer:"
+msgid "Rate:"
+msgstr ""
diff --git a/modules/sale_secondary_unit/locale/ru.po b/modules/sale_secondary_unit/locale/ru.po
new file mode 100644
index 0000000000..b91ff365cf
--- /dev/null
+++ b/modules/sale_secondary_unit/locale/ru.po
@@ -0,0 +1,140 @@
+#
+msgid ""
+msgstr "Content-Type: text/plain; charset=utf-8\n"
+
+msgctxt "field:product.product,sale_secondary_uom:"
+msgid "Sale Secondary UOM"
+msgstr ""
+
+msgctxt "field:product.product,sale_secondary_uom_factor:"
+msgid "Sale Secondary UOM Factor"
+msgstr ""
+
+msgctxt "field:product.product,sale_secondary_uom_rate:"
+msgid "Sale Secondary UOM Rate"
+msgstr ""
+
+msgctxt "field:product.template,sale_secondary_uom:"
+msgid "Sale Secondary UOM"
+msgstr ""
+
+msgctxt "field:product.template,sale_secondary_uom_factor:"
+msgid "Sale Secondary UOM Factor"
+msgstr ""
+
+msgctxt "field:product.template,sale_secondary_uom_rate:"
+msgid "Sale Secondary UOM Rate"
+msgstr ""
+
+msgctxt "field:sale.line,product_secondary_uom_category:"
+msgid "Product Secondary UOM Category"
+msgstr ""
+
+msgctxt "field:sale.line,secondary_quantity:"
+msgid "Secondary Quantity"
+msgstr ""
+
+msgctxt "field:sale.line,secondary_unit:"
+msgid "Secondary Unit"
+msgstr ""
+
+msgctxt "field:sale.line,secondary_unit_digits:"
+msgid "Secondary Unit Digits"
+msgstr ""
+
+msgctxt "field:sale.line,secondary_unit_price:"
+msgid "Secondary Unit Price"
+msgstr ""
+
+msgctxt "field:sale.line,secondary_uom_factor:"
+msgid "Secondary UOM Factor"
+msgstr ""
+
+msgctxt "field:sale.line,secondary_uom_rate:"
+msgid "Secondary UOM Rate"
+msgstr ""
+
+msgctxt "field:sale.product_customer,default_uom_category:"
+msgid "Default UOM Category"
+msgstr ""
+
+msgctxt "field:sale.product_customer,sale_secondary_uom:"
+msgid "Sale Secondary UOM"
+msgstr ""
+
+msgctxt "field:sale.product_customer,sale_secondary_uom_factor:"
+msgid "Sale Secondary UOM Factor"
+msgstr ""
+
+msgctxt "field:sale.product_customer,sale_secondary_uom_rate:"
+msgid "Sale Secondary UOM Rate"
+msgstr ""
+
+msgctxt "help:product.product,sale_secondary_uom_factor:"
+msgid ""
+"The coefficient for the formula:\n"
+"1 (sale unit) = coefficient (secondary unit)"
+msgstr ""
+
+msgctxt "help:product.product,sale_secondary_uom_rate:"
+msgid ""
+"The coefficient for the formula:\n"
+"coefficient (sale unit) = 1 (secondary unit)"
+msgstr ""
+
+msgctxt "help:product.template,sale_secondary_uom_factor:"
+msgid ""
+"The coefficient for the formula:\n"
+"1 (sale unit) = coefficient (secondary unit)"
+msgstr ""
+
+msgctxt "help:product.template,sale_secondary_uom_rate:"
+msgid ""
+"The coefficient for the formula:\n"
+"coefficient (sale unit) = 1 (secondary unit)"
+msgstr ""
+
+msgctxt "help:sale.product_customer,sale_secondary_uom_factor:"
+msgid ""
+"The coefficient for the formula:\n"
+"1 (sale unit) = coefficient (secondary unit)"
+msgstr ""
+
+msgctxt "help:sale.product_customer,sale_secondary_uom_rate:"
+msgid ""
+"The coefficient for the formula:\n"
+"coefficient (sale unit) = 1 (secondary unit)"
+msgstr ""
+
+msgctxt ""
+"model:ir.message,text:msg_sale_secondary_uom_incompatible_factor_rate"
+msgid "Incompatible sale secondary factor and rate values for \"%(record)s\"."
+msgstr ""
+
+msgctxt "view:product.template:"
+msgid "Factor:"
+msgstr ""
+
+msgctxt "view:product.template:"
+msgid "Rate:"
+msgstr ""
+
+msgctxt "view:sale.line:"
+msgid "Quantity:"
+msgstr ""
+
+msgctxt "view:sale.line:"
+msgid "Unit Price:"
+msgstr ""
+
+msgctxt "view:sale.line:"
+msgid "Unit:"
+msgstr ""
+
+msgctxt "view:sale.product_customer:"
+msgid "Factor:"
+msgstr ""
+
+msgctxt "view:sale.product_customer:"
+msgid "Rate:"
+msgstr ""
diff --git a/modules/sale_secondary_unit/locale/sl.po b/modules/sale_secondary_unit/locale/sl.po
new file mode 100644
index 0000000000..b91ff365cf
--- /dev/null
+++ b/modules/sale_secondary_unit/locale/sl.po
@@ -0,0 +1,140 @@
+#
+msgid ""
+msgstr "Content-Type: text/plain; charset=utf-8\n"
+
+msgctxt "field:product.product,sale_secondary_uom:"
+msgid "Sale Secondary UOM"
+msgstr ""
+
+msgctxt "field:product.product,sale_secondary_uom_factor:"
+msgid "Sale Secondary UOM Factor"
+msgstr ""
+
+msgctxt "field:product.product,sale_secondary_uom_rate:"
+msgid "Sale Secondary UOM Rate"
+msgstr ""
+
+msgctxt "field:product.template,sale_secondary_uom:"
+msgid "Sale Secondary UOM"
+msgstr ""
+
+msgctxt "field:product.template,sale_secondary_uom_factor:"
+msgid "Sale Secondary UOM Factor"
+msgstr ""
+
+msgctxt "field:product.template,sale_secondary_uom_rate:"
+msgid "Sale Secondary UOM Rate"
+msgstr ""
+
+msgctxt "field:sale.line,product_secondary_uom_category:"
+msgid "Product Secondary UOM Category"
+msgstr ""
+
+msgctxt "field:sale.line,secondary_quantity:"
+msgid "Secondary Quantity"
+msgstr ""
+
+msgctxt "field:sale.line,secondary_unit:"
+msgid "Secondary Unit"
+msgstr ""
+
+msgctxt "field:sale.line,secondary_unit_digits:"
+msgid "Secondary Unit Digits"
+msgstr ""
+
+msgctxt "field:sale.line,secondary_unit_price:"
+msgid "Secondary Unit Price"
+msgstr ""
+
+msgctxt "field:sale.line,secondary_uom_factor:"
+msgid "Secondary UOM Factor"
+msgstr ""
+
+msgctxt "field:sale.line,secondary_uom_rate:"
+msgid "Secondary UOM Rate"
+msgstr ""
+
+msgctxt "field:sale.product_customer,default_uom_category:"
+msgid "Default UOM Category"
+msgstr ""
+
+msgctxt "field:sale.product_customer,sale_secondary_uom:"
+msgid "Sale Secondary UOM"
+msgstr ""
+
+msgctxt "field:sale.product_customer,sale_secondary_uom_factor:"
+msgid "Sale Secondary UOM Factor"
+msgstr ""
+
+msgctxt "field:sale.product_customer,sale_secondary_uom_rate:"
+msgid "Sale Secondary UOM Rate"
+msgstr ""
+
+msgctxt "help:product.product,sale_secondary_uom_factor:"
+msgid ""
+"The coefficient for the formula:\n"
+"1 (sale unit) = coefficient (secondary unit)"
+msgstr ""
+
+msgctxt "help:product.product,sale_secondary_uom_rate:"
+msgid ""
+"The coefficient for the formula:\n"
+"coefficient (sale unit) = 1 (secondary unit)"
+msgstr ""
+
+msgctxt "help:product.template,sale_secondary_uom_factor:"
+msgid ""
+"The coefficient for the formula:\n"
+"1 (sale unit) = coefficient (secondary unit)"
+msgstr ""
+
+msgctxt "help:product.template,sale_secondary_uom_rate:"
+msgid ""
+"The coefficient for the formula:\n"
+"coefficient (sale unit) = 1 (secondary unit)"
+msgstr ""
+
+msgctxt "help:sale.product_customer,sale_secondary_uom_factor:"
+msgid ""
+"The coefficient for the formula:\n"
+"1 (sale unit) = coefficient (secondary unit)"
+msgstr ""
+
+msgctxt "help:sale.product_customer,sale_secondary_uom_rate:"
+msgid ""
+"The coefficient for the formula:\n"
+"coefficient (sale unit) = 1 (secondary unit)"
+msgstr ""
+
+msgctxt ""
+"model:ir.message,text:msg_sale_secondary_uom_incompatible_factor_rate"
+msgid "Incompatible sale secondary factor and rate values for \"%(record)s\"."
+msgstr ""
+
+msgctxt "view:product.template:"
+msgid "Factor:"
+msgstr ""
+
+msgctxt "view:product.template:"
+msgid "Rate:"
+msgstr ""
+
+msgctxt "view:sale.line:"
+msgid "Quantity:"
+msgstr ""
+
+msgctxt "view:sale.line:"
+msgid "Unit Price:"
+msgstr ""
+
+msgctxt "view:sale.line:"
+msgid "Unit:"
+msgstr ""
+
+msgctxt "view:sale.product_customer:"
+msgid "Factor:"
+msgstr ""
+
+msgctxt "view:sale.product_customer:"
+msgid "Rate:"
+msgstr ""
diff --git a/modules/sale_secondary_unit/locale/tr.po b/modules/sale_secondary_unit/locale/tr.po
new file mode 100644
index 0000000000..b91ff365cf
--- /dev/null
+++ b/modules/sale_secondary_unit/locale/tr.po
@@ -0,0 +1,140 @@
+#
+msgid ""
+msgstr "Content-Type: text/plain; charset=utf-8\n"
+
+msgctxt "field:product.product,sale_secondary_uom:"
+msgid "Sale Secondary UOM"
+msgstr ""
+
+msgctxt "field:product.product,sale_secondary_uom_factor:"
+msgid "Sale Secondary UOM Factor"
+msgstr ""
+
+msgctxt "field:product.product,sale_secondary_uom_rate:"
+msgid "Sale Secondary UOM Rate"
+msgstr ""
+
+msgctxt "field:product.template,sale_secondary_uom:"
+msgid "Sale Secondary UOM"
+msgstr ""
+
+msgctxt "field:product.template,sale_secondary_uom_factor:"
+msgid "Sale Secondary UOM Factor"
+msgstr ""
+
+msgctxt "field:product.template,sale_secondary_uom_rate:"
+msgid "Sale Secondary UOM Rate"
+msgstr ""
+
+msgctxt "field:sale.line,product_secondary_uom_category:"
+msgid "Product Secondary UOM Category"
+msgstr ""
+
+msgctxt "field:sale.line,secondary_quantity:"
+msgid "Secondary Quantity"
+msgstr ""
+
+msgctxt "field:sale.line,secondary_unit:"
+msgid "Secondary Unit"
+msgstr ""
+
+msgctxt "field:sale.line,secondary_unit_digits:"
+msgid "Secondary Unit Digits"
+msgstr ""
+
+msgctxt "field:sale.line,secondary_unit_price:"
+msgid "Secondary Unit Price"
+msgstr ""
+
+msgctxt "field:sale.line,secondary_uom_factor:"
+msgid "Secondary UOM Factor"
+msgstr ""
+
+msgctxt "field:sale.line,secondary_uom_rate:"
+msgid "Secondary UOM Rate"
+msgstr ""
+
+msgctxt "field:sale.product_customer,default_uom_category:"
+msgid "Default UOM Category"
+msgstr ""
+
+msgctxt "field:sale.product_customer,sale_secondary_uom:"
+msgid "Sale Secondary UOM"
+msgstr ""
+
+msgctxt "field:sale.product_customer,sale_secondary_uom_factor:"
+msgid "Sale Secondary UOM Factor"
+msgstr ""
+
+msgctxt "field:sale.product_customer,sale_secondary_uom_rate:"
+msgid "Sale Secondary UOM Rate"
+msgstr ""
+
+msgctxt "help:product.product,sale_secondary_uom_factor:"
+msgid ""
+"The coefficient for the formula:\n"
+"1 (sale unit) = coefficient (secondary unit)"
+msgstr ""
+
+msgctxt "help:product.product,sale_secondary_uom_rate:"
+msgid ""
+"The coefficient for the formula:\n"
+"coefficient (sale unit) = 1 (secondary unit)"
+msgstr ""
+
+msgctxt "help:product.template,sale_secondary_uom_factor:"
+msgid ""
+"The coefficient for the formula:\n"
+"1 (sale unit) = coefficient (secondary unit)"
+msgstr ""
+
+msgctxt "help:product.template,sale_secondary_uom_rate:"
+msgid ""
+"The coefficient for the formula:\n"
+"coefficient (sale unit) = 1 (secondary unit)"
+msgstr ""
+
+msgctxt "help:sale.product_customer,sale_secondary_uom_factor:"
+msgid ""
+"The coefficient for the formula:\n"
+"1 (sale unit) = coefficient (secondary unit)"
+msgstr ""
+
+msgctxt "help:sale.product_customer,sale_secondary_uom_rate:"
+msgid ""
+"The coefficient for the formula:\n"
+"coefficient (sale unit) = 1 (secondary unit)"
+msgstr ""
+
+msgctxt ""
+"model:ir.message,text:msg_sale_secondary_uom_incompatible_factor_rate"
+msgid "Incompatible sale secondary factor and rate values for \"%(record)s\"."
+msgstr ""
+
+msgctxt "view:product.template:"
+msgid "Factor:"
+msgstr ""
+
+msgctxt "view:product.template:"
+msgid "Rate:"
+msgstr ""
+
+msgctxt "view:sale.line:"
+msgid "Quantity:"
+msgstr ""
+
+msgctxt "view:sale.line:"
+msgid "Unit Price:"
+msgstr ""
+
+msgctxt "view:sale.line:"
+msgid "Unit:"
+msgstr ""
+
+msgctxt "view:sale.product_customer:"
+msgid "Factor:"
+msgstr ""
+
+msgctxt "view:sale.product_customer:"
+msgid "Rate:"
+msgstr ""
diff --git a/modules/sale_secondary_unit/locale/zh_CN.po b/modules/sale_secondary_unit/locale/zh_CN.po
new file mode 100644
index 0000000000..b91ff365cf
--- /dev/null
+++ b/modules/sale_secondary_unit/locale/zh_CN.po
@@ -0,0 +1,140 @@
+#
+msgid ""
+msgstr "Content-Type: text/plain; charset=utf-8\n"
+
+msgctxt "field:product.product,sale_secondary_uom:"
+msgid "Sale Secondary UOM"
+msgstr ""
+
+msgctxt "field:product.product,sale_secondary_uom_factor:"
+msgid "Sale Secondary UOM Factor"
+msgstr ""
+
+msgctxt "field:product.product,sale_secondary_uom_rate:"
+msgid "Sale Secondary UOM Rate"
+msgstr ""
+
+msgctxt "field:product.template,sale_secondary_uom:"
+msgid "Sale Secondary UOM"
+msgstr ""
+
+msgctxt "field:product.template,sale_secondary_uom_factor:"
+msgid "Sale Secondary UOM Factor"
+msgstr ""
+
+msgctxt "field:product.template,sale_secondary_uom_rate:"
+msgid "Sale Secondary UOM Rate"
+msgstr ""
+
+msgctxt "field:sale.line,product_secondary_uom_category:"
+msgid "Product Secondary UOM Category"
+msgstr ""
+
+msgctxt "field:sale.line,secondary_quantity:"
+msgid "Secondary Quantity"
+msgstr ""
+
+msgctxt "field:sale.line,secondary_unit:"
+msgid "Secondary Unit"
+msgstr ""
+
+msgctxt "field:sale.line,secondary_unit_digits:"
+msgid "Secondary Unit Digits"
+msgstr ""
+
+msgctxt "field:sale.line,secondary_unit_price:"
+msgid "Secondary Unit Price"
+msgstr ""
+
+msgctxt "field:sale.line,secondary_uom_factor:"
+msgid "Secondary UOM Factor"
+msgstr ""
+
+msgctxt "field:sale.line,secondary_uom_rate:"
+msgid "Secondary UOM Rate"
+msgstr ""
+
+msgctxt "field:sale.product_customer,default_uom_category:"
+msgid "Default UOM Category"
+msgstr ""
+
+msgctxt "field:sale.product_customer,sale_secondary_uom:"
+msgid "Sale Secondary UOM"
+msgstr ""
+
+msgctxt "field:sale.product_customer,sale_secondary_uom_factor:"
+msgid "Sale Secondary UOM Factor"
+msgstr ""
+
+msgctxt "field:sale.product_customer,sale_secondary_uom_rate:"
+msgid "Sale Secondary UOM Rate"
+msgstr ""
+
+msgctxt "help:product.product,sale_secondary_uom_factor:"
+msgid ""
+"The coefficient for the formula:\n"
+"1 (sale unit) = coefficient (secondary unit)"
+msgstr ""
+
+msgctxt "help:product.product,sale_secondary_uom_rate:"
+msgid ""
+"The coefficient for the formula:\n"
+"coefficient (sale unit) = 1 (secondary unit)"
+msgstr ""
+
+msgctxt "help:product.template,sale_secondary_uom_factor:"
+msgid ""
+"The coefficient for the formula:\n"
+"1 (sale unit) = coefficient (secondary unit)"
+msgstr ""
+
+msgctxt "help:product.template,sale_secondary_uom_rate:"
+msgid ""
+"The coefficient for the formula:\n"
+"coefficient (sale unit) = 1 (secondary unit)"
+msgstr ""
+
+msgctxt "help:sale.product_customer,sale_secondary_uom_factor:"
+msgid ""
+"The coefficient for the formula:\n"
+"1 (sale unit) = coefficient (secondary unit)"
+msgstr ""
+
+msgctxt "help:sale.product_customer,sale_secondary_uom_rate:"
+msgid ""
+"The coefficient for the formula:\n"
+"coefficient (sale unit) = 1 (secondary unit)"
+msgstr ""
+
+msgctxt ""
+"model:ir.message,text:msg_sale_secondary_uom_incompatible_factor_rate"
+msgid "Incompatible sale secondary factor and rate values for \"%(record)s\"."
+msgstr ""
+
+msgctxt "view:product.template:"
+msgid "Factor:"
+msgstr ""
+
+msgctxt "view:product.template:"
+msgid "Rate:"
+msgstr ""
+
+msgctxt "view:sale.line:"
+msgid "Quantity:"
+msgstr ""
+
+msgctxt "view:sale.line:"
+msgid "Unit Price:"
+msgstr ""
+
+msgctxt "view:sale.line:"
+msgid "Unit:"
+msgstr ""
+
+msgctxt "view:sale.product_customer:"
+msgid "Factor:"
+msgstr ""
+
+msgctxt "view:sale.product_customer:"
+msgid "Rate:"
+msgstr ""
diff --git a/modules/sale_secondary_unit/message.xml b/modules/sale_secondary_unit/message.xml
new file mode 100644
index 0000000000..1baeae518d
--- /dev/null
+++ b/modules/sale_secondary_unit/message.xml
@@ -0,0 +1,10 @@
+
+
+
+
+
+ Incompatible sale secondary factor and rate values for "%(record)s".
+
+
+
diff --git a/modules/sale_secondary_unit/product.py b/modules/sale_secondary_unit/product.py
new file mode 100644
index 0000000000..eb0ea028a9
--- /dev/null
+++ b/modules/sale_secondary_unit/product.py
@@ -0,0 +1,148 @@
+# This file is part of Tryton. The COPYRIGHT file at the top level of
+# this repository contains the full copyright notices and license terms.
+
+from trytond.i18n import gettext
+from trytond.model import fields
+from trytond.pool import PoolMeta
+from trytond.pyson import Eval, Bool
+
+from trytond.modules.product import uom_conversion_digits
+from trytond.modules.product.exceptions import UOMValidationError
+
+
+class SaleSecondaryMixin:
+ __slots__ = ()
+ sale_secondary_uom = fields.Many2One(
+ 'product.uom', "Sale Secondary UOM",
+ domain=[
+ ('category', '!=', Eval('default_uom_category')),
+ ],
+ depends=['default_uom_category'])
+ sale_secondary_uom_factor = fields.Float(
+ "Sale Secondary UOM Factor", digits=uom_conversion_digits,
+ states={
+ 'required': Bool(Eval('sale_secondary_uom')),
+ 'invisible': ~Eval('sale_secondary_uom'),
+ },
+ depends=['sale_secondary_uom'],
+ help="The coefficient for the formula:\n"
+ "1 (sale unit) = coefficient (secondary unit)")
+ sale_secondary_uom_rate = fields.Float(
+ "Sale Secondary UOM Rate", digits=uom_conversion_digits,
+ states={
+ 'required': Bool(Eval('sale_secondary_uom')),
+ 'invisible': ~Eval('sale_secondary_uom'),
+ },
+ depends=['sale_secondary_uom'],
+ help="The coefficient for the formula:\n"
+ "coefficient (sale unit) = 1 (secondary unit)")
+
+ @fields.depends('sale_secondary_uom_factor')
+ def on_change_sale_secondary_uom_factor(self):
+ if not self.sale_secondary_uom_factor:
+ self.sale_secondary_uom_rate = None
+ else:
+ self.sale_secondary_uom_rate = round(
+ 1. / self.sale_secondary_uom_factor, uom_conversion_digits[1])
+
+ @fields.depends('sale_secondary_uom_rate')
+ def on_change_sale_secondary_uom_rate(self):
+ if not self.sale_secondary_uom_rate:
+ self.sale_secondary_uom_factor = None
+ else:
+ self.sale_secondary_uom_factor = round(
+ 1. / self.sale_secondary_uom_rate, uom_conversion_digits[1])
+
+ @property
+ def sale_secondary_uom_normal_rate(self):
+ uom = self.sale_secondary_uom
+ rate = self.sale_secondary_uom_rate
+ if self.sale_uom and rate and uom:
+ if self.sale_uom.accurate_field == 'factor':
+ rate *= self.sale_uom.factor
+ else:
+ rate /= self.sale_uom.rate
+ if uom.accurate_field == 'factor':
+ rate /= uom.factor
+ else:
+ rate *= uom.rate
+ return rate
+
+ @property
+ def sale_secondary_uom_normal_factor(self):
+ uom = self.sale_secondary_uom
+ factor = self.sale_secondary_uom_factor
+ if uom and factor and self.sale_uom:
+ if uom.accurate_field == 'factor':
+ factor *= uom.factor
+ else:
+ factor /= uom.rate
+ if self.sale_uom.accurate_field == 'factor':
+ factor /= self.sale_uom.factor
+ else:
+ factor *= self.sale_uom.rate
+ return factor
+
+ @classmethod
+ def validate(cls, records):
+ super().validate(records)
+ for record in records:
+ record.check_sale_secondary_uom_factor_and_rate()
+
+ def check_sale_secondary_uom_factor_and_rate(self):
+ factor = self.sale_secondary_uom_factor
+ rate = self.sale_secondary_uom_rate
+ if factor and rate:
+ if ((rate != round(1. / factor, uom_conversion_digits[1]))
+ and factor != round(1. / rate, uom_conversion_digits[1])):
+ raise UOMValidationError(
+ gettext('sale_secondary_unit'
+ '.msg_sale_secondary_uom_incompatible_factor_rate',
+ record=self))
+
+
+class Template(SaleSecondaryMixin, metaclass=PoolMeta):
+ __name__ = 'product.template'
+
+ @classmethod
+ def __setup__(cls):
+ super().__setup__()
+ cls.sale_secondary_uom.states = {
+ 'invisible': ~Eval('salable', False),
+ }
+ cls.sale_secondary_uom.depends.append('salable')
+
+
+class Product(metaclass=PoolMeta):
+ __name__ = 'product.product'
+
+ @property
+ def sale_secondary_uom_normal_rate(self):
+ return self.template.sale_secondary_uom_normal_rate
+
+ @property
+ def sale_secondary_uom_normal_factor(self):
+ return self.template.sale_secondary_uom_normal_factor
+
+
+class ProductCustomer(SaleSecondaryMixin, metaclass=PoolMeta):
+ __name__ = 'sale.product_customer'
+
+ default_uom_category = fields.Function(
+ fields.Many2One('product.uom.category', "Default UOM Category"),
+ 'on_change_with_default_uom_category')
+
+ @fields.depends('template', '_parent_template.sale_uom',
+ 'product', '_parent_product.sale_uom')
+ def on_change_with_default_uom_category(self, name=None):
+ if self.product and self.product.sale_uom:
+ return self.product.sale_uom.category.id
+ elif self.template and self.template.sale_uom:
+ return self.template.sale_uom.category.id
+
+ @property
+ def sale_uom(self):
+ if self.product and self.product.sale_uom:
+ return self.product.sale_uom
+ elif self.template and self.template.sale_uom:
+ return self.template.sale_uom
diff --git a/modules/sale_secondary_unit/product.xml b/modules/sale_secondary_unit/product.xml
new file mode 100644
index 0000000000..2ec9333c46
--- /dev/null
+++ b/modules/sale_secondary_unit/product.xml
@@ -0,0 +1,20 @@
+
+
+
+
+
+ product.template
+
+ product_template_form
+
+
+
+
+
+ sale.product_customer
+
+ product_customer_form
+
+
+
diff --git a/modules/sale_secondary_unit/sale.py b/modules/sale_secondary_unit/sale.py
new file mode 100644
index 0000000000..a5987fa86d
--- /dev/null
+++ b/modules/sale_secondary_unit/sale.py
@@ -0,0 +1,207 @@
+# This file is part of Tryton. The COPYRIGHT file at the top level of
+# this repository contains the full copyright notices and license terms.
+from trytond.model import fields
+from trytond.pool import PoolMeta, Pool
+from trytond.pyson import Eval, If
+
+from trytond.modules.product import price_digits, round_price
+
+
+class Line(metaclass=PoolMeta):
+ __name__ = 'sale.line'
+
+ secondary_quantity = fields.Function(
+ fields.Float("Secondary Quantity",
+ digits=(16, Eval('secondary_unit_digits', 2)),
+ states={
+ 'invisible': ((Eval('type') != 'line')
+ | ~Eval('secondary_unit')),
+ 'readonly': Eval('sale_state') != 'draft',
+ },
+ depends=[
+ 'secondary_unit_digits', 'type', 'secondary_unit',
+ 'sale_state']),
+ 'on_change_with_secondary_quantity', setter='set_secondary')
+ secondary_unit = fields.Many2One(
+ 'product.uom', "Secondary Unit", ondelete='RESTRICT',
+ domain=[
+ If(Eval('sale_state') == 'draft',
+ ('category', '=', Eval('product_secondary_uom_category')),
+ ()),
+ ],
+ states={
+ 'invisible': ((Eval('type') != 'line')
+ | (~Eval('secondary_uom_factor')
+ & ~Eval('secondary_uom_rate'))),
+ 'readonly': Eval('sale_state') != 'draft',
+ },
+ depends=['product_secondary_uom_category', 'type',
+ 'secondary_uom_factor', 'secondary_uom_rate', 'sale_state'])
+ secondary_unit_price = fields.Function(
+ fields.Numeric(
+ "Secondary Unit Price", digits=price_digits,
+ states={
+ 'invisible': ((Eval('type') != 'line')
+ | ~Eval('secondary_unit')),
+ 'readonly': Eval('sale_state') != 'draft',
+ },
+ depends=['type', 'secondary_unit', 'sale_state']),
+ 'on_change_with_secondary_unit_price', setter='set_secondary')
+
+ secondary_uom_factor = fields.Float("Secondary UOM Factor")
+ secondary_uom_rate = fields.Float("Secondary UOM Rate")
+
+ secondary_unit_digits = fields.Function(
+ fields.Integer("Secondary Unit Digits"),
+ 'on_change_with_secondary_unit_digits')
+ product_secondary_uom_category = fields.Function(
+ fields.Many2One(
+ 'product.uom.category', "Product Secondary UOM Category"),
+ 'on_change_with_product_secondary_uom_category')
+
+ @fields.depends('product')
+ def _secondary_record(self):
+ if self.product and self.product.sale_secondary_uom:
+ return self.product
+
+ @fields.depends('quantity', 'unit', 'secondary_unit',
+ 'secondary_uom_factor', 'secondary_uom_rate')
+ def on_change_with_secondary_quantity(self, name=None):
+ pool = Pool()
+ Uom = pool.get('product.uom')
+ if (self.quantity and self.unit and self.secondary_unit
+ and (self.secondary_uom_factor or self.secondary_uom_rate)):
+ return Uom.compute_qty(
+ self.unit, self.quantity,
+ self.secondary_unit, round=True,
+ factor=self.secondary_uom_factor, rate=self.secondary_uom_rate)
+ else:
+ return None
+
+ @fields.depends('secondary_quantity', 'secondary_unit', 'unit',
+ 'secondary_uom_factor', 'secondary_uom_rate',
+ methods=['on_change_quantity', 'on_change_with_amount'])
+ def on_change_secondary_quantity(self):
+ pool = Pool()
+ Uom = pool.get('product.uom')
+ if (self.secondary_quantity and self.secondary_unit and self.unit
+ and (self.secondary_uom_factor or self.secondary_uom_rate)):
+ self.quantity = Uom.compute_qty(
+ self.secondary_unit, self.secondary_quantity,
+ self.unit, round=True,
+ factor=self.secondary_uom_rate, rate=self.secondary_uom_factor)
+ self.on_change_quantity()
+ self.amount = self.on_change_with_amount()
+
+ @fields.depends('unit_price', 'unit', 'secondary_unit',
+ 'secondary_uom_factor', 'secondary_uom_rate')
+ def on_change_with_secondary_unit_price(self, name=None):
+ pool = Pool()
+ Uom = pool.get('product.uom')
+ if (self.unit_price is not None and self.unit and self.secondary_unit
+ and (self.secondary_uom_factor or self.secondary_uom_rate)):
+ unit_price = Uom.compute_price(
+ self.unit, self.unit_price, self.secondary_unit,
+ factor=self.secondary_uom_factor, rate=self.secondary_uom_rate)
+ return round_price(unit_price)
+ else:
+ return None
+
+ @fields.depends('secondary_unit_price', 'secondary_unit', 'unit',
+ 'secondary_uom_factor', 'secondary_uom_rate',
+ methods=['on_change_with_amount'])
+ def on_change_secondary_unit_price(self, name=None):
+ pool = Pool()
+ Uom = pool.get('product.uom')
+ if (self.secondary_unit_price is not None
+ and self.secondary_unit and self.unit
+ and (self.secondary_uom_factor or self.secondary_uom_rate)):
+ self.unit_price = Uom.compute_price(
+ self.secondary_unit, self.secondary_unit_price, self.unit,
+ factor=self.secondary_uom_rate, rate=self.secondary_uom_factor)
+ self.unit_price = round_price(self.unit_price)
+ self.amount = self.on_change_with_amount()
+
+ @fields.depends(methods=[
+ 'on_change_secondary_quantity', 'on_change_secondary_unit_price'])
+ def on_change_secondary_unit(self):
+ self.on_change_secondary_quantity()
+ self.on_change_secondary_unit_price()
+
+ @fields.depends('secondary_unit')
+ def on_change_with_secondary_unit_digits(self, name=None):
+ if self.secondary_unit:
+ return self.secondary_unit.digits
+
+ @fields.depends(methods=['_secondary_record'])
+ def on_change_with_product_secondary_uom_category(self, name=None):
+ secondary_record = self._secondary_record()
+ if secondary_record:
+ return secondary_record.sale_secondary_uom.category.id
+
+ @classmethod
+ def set_secondary(cls, lines, name, value):
+ pass
+
+ @fields.depends('secondary_unit',
+ methods=['on_change_with_secondary_quantity', '_secondary_record'])
+ def on_change_product(self):
+ super().on_change_product()
+ secondary_record = self._secondary_record()
+ if secondary_record and self.secondary_unit:
+ secondary_uom = secondary_record.sale_secondary_uom
+ if secondary_uom:
+ if self.secondary_unit.category != secondary_uom.category:
+ self.secondary_unit = None
+
+ if secondary_record:
+ self.secondary_uom_factor = (
+ secondary_record.sale_secondary_uom_normal_factor)
+ self.secondary_uom_rate = (
+ secondary_record.sale_secondary_uom_normal_rate)
+ else:
+ self.secondary_unit = None
+ self.secondary_uom_factor = None
+ self.secondary_uom_rate = None
+ self.secondary_quantity = self.on_change_with_secondary_quantity()
+
+ def get_invoice_line(self):
+ pool = Pool()
+ InvoiceLine = pool.get('account.invoice.line')
+ lines = super().get_invoice_line()
+ if hasattr(InvoiceLine, 'secondary_unit'):
+ for line in lines:
+ if line.type != 'line':
+ continue
+ if line.unit == self.unit:
+ line.secondary_unit = self.secondary_unit
+ return lines
+
+ def get_move(self, shipment_type):
+ move = super().get_move(shipment_type)
+ if move and hasattr(move.__class__, 'secondary_unit'):
+ if move.uom == self.unit:
+ move.secondary_unit = self.secondary_unit
+ return move
+
+
+class Line_ProductCustomer(metaclass=PoolMeta):
+ __name__ = 'sale.line'
+
+ @fields.depends('product_customer')
+ def _secondary_record(self):
+ if self.product_customer and self.product_customer.sale_secondary_uom:
+ return self.product_customer
+ return super()._secondary_record()
+
+
+class OpportunityLine(metaclass=PoolMeta):
+ __name__ = 'sale.opportunity.line'
+
+ def _set_sale_line_quantity(self, sale_line):
+ super()._set_sale_line_quantity(sale_line)
+ if self.unit.category != self.product.sale_uom.category:
+ sale_line.unit = self.product.sale_uom
+ sale_line.secondary_quantity = self.quantity
+ sale_line.secondary_unit = self.unit
+ sale_line.on_change_secondary_quantity()
diff --git a/modules/sale_secondary_unit/sale.xml b/modules/sale_secondary_unit/sale.xml
new file mode 100644
index 0000000000..79b41d5492
--- /dev/null
+++ b/modules/sale_secondary_unit/sale.xml
@@ -0,0 +1,24 @@
+
+
+
+
+
+ sale.line
+
+ sale_line_form
+
+
+
+ sale.line
+
+ sale_line_tree
+
+
+
+ sale.line
+
+ sale_line_tree
+
+
+
diff --git a/modules/sale_secondary_unit/setup.py b/modules/sale_secondary_unit/setup.py
new file mode 100755
index 0000000000..71ac91e766
--- /dev/null
+++ b/modules/sale_secondary_unit/setup.py
@@ -0,0 +1,151 @@
+#!/usr/bin/env python3
+# This file is part of Tryton. The COPYRIGHT file at the top level of
+# this repository contains the full copyright notices and license terms.
+
+import io
+import os
+import re
+from configparser import ConfigParser
+from setuptools import setup, find_packages
+
+
+def read(fname):
+ return io.open(
+ os.path.join(os.path.dirname(__file__), fname),
+ 'r', encoding='utf-8').read()
+
+
+def get_require_version(name):
+ if minor_version % 2:
+ require = '%s >= %s.%s.dev0, < %s.%s'
+ else:
+ require = '%s >= %s.%s, < %s.%s'
+ require %= (name, major_version, minor_version,
+ major_version, minor_version + 1)
+ return require
+
+
+config = ConfigParser()
+config.read_file(open(os.path.join(os.path.dirname(__file__), 'tryton.cfg')))
+info = dict(config.items('tryton'))
+for key in ('depends', 'extras_depend', 'xml'):
+ if key in info:
+ info[key] = info[key].strip().splitlines()
+version = info.get('version', '0.0.1')
+major_version, minor_version, _ = version.split('.', 2)
+major_version = int(major_version)
+minor_version = int(minor_version)
+name = 'trytond_sale_secondary_unit'
+
+download_url = 'http://downloads.tryton.org/%s.%s/' % (
+ major_version, minor_version)
+if minor_version % 2:
+ version = '%s.%s.dev0' % (major_version, minor_version)
+ download_url = (
+ 'hg+http://hg.tryton.org/modules/%s#egg=%s-%s' % (
+ name[8:], name, version))
+local_version = []
+if os.environ.get('CI_JOB_ID'):
+ local_version.append(os.environ['CI_JOB_ID'])
+else:
+ for build in ['CI_BUILD_NUMBER', 'CI_JOB_NUMBER']:
+ if os.environ.get(build):
+ local_version.append(os.environ[build])
+ else:
+ local_version = []
+ break
+if local_version:
+ version += '+' + '.'.join(local_version)
+
+requires = []
+for dep in info.get('depends', []):
+ if not re.match(r'(ir|res)(\W|$)', dep):
+ requires.append(get_require_version('trytond_%s' % dep))
+requires.append(get_require_version('trytond'))
+
+tests_require = [get_require_version('proteus'),
+ get_require_version('trytond_account_invoice_secondary_unit'),
+ get_require_version('trytond_stock_secondary_unit'),
+ get_require_version('trytond_sale_product_customer')]
+dependency_links = []
+if minor_version % 2:
+ dependency_links.append(
+ 'https://trydevpi.tryton.org/?local_version='
+ + '.'.join(local_version))
+
+setup(name=name,
+ version=version,
+ description='Tryton module to add a secondary unit on sale line',
+ long_description=read('README.rst'),
+ author='Tryton',
+ author_email='bugs@tryton.org',
+ url='http://www.tryton.org/',
+ download_url=download_url,
+ project_urls={
+ "Bug Tracker": 'https://bugs.tryton.org/',
+ "Documentation": 'https://docs.tryton.org/',
+ "Forum": 'https://www.tryton.org/forum',
+ "Source Code": 'https://hg.tryton.org/modules/sale_secondary_unit',
+ },
+ keywords='tryton sale secondary unit',
+ package_dir={'trytond.modules.sale_secondary_unit': '.'},
+ packages=(
+ ['trytond.modules.sale_secondary_unit']
+ + ['trytond.modules.sale_secondary_unit.%s' % p
+ for p in find_packages()]
+ ),
+ package_data={
+ 'trytond.modules.sale_secondary_unit': (info.get('xml', [])
+ + ['tryton.cfg', 'view/*.xml', 'locale/*.po', '*.fodt',
+ 'icons/*.svg', 'tests/*.rst']),
+ },
+ classifiers=[
+ 'Development Status :: 5 - Production/Stable',
+ 'Environment :: Plugins',
+ 'Framework :: Tryton',
+ 'Intended Audience :: Developers',
+ 'Intended Audience :: Financial and Insurance Industry',
+ 'Intended Audience :: Legal Industry',
+ 'License :: OSI Approved :: '
+ 'GNU General Public License v3 or later (GPLv3+)',
+ 'Natural Language :: Bulgarian',
+ 'Natural Language :: Catalan',
+ 'Natural Language :: Chinese (Simplified)',
+ 'Natural Language :: Czech',
+ 'Natural Language :: Dutch',
+ 'Natural Language :: English',
+ 'Natural Language :: French',
+ 'Natural Language :: German',
+ 'Natural Language :: Hungarian',
+ 'Natural Language :: Indonesian',
+ 'Natural Language :: Italian',
+ 'Natural Language :: Persian',
+ 'Natural Language :: Polish',
+ 'Natural Language :: Portuguese (Brazilian)',
+ 'Natural Language :: Romanian',
+ 'Natural Language :: Russian',
+ 'Natural Language :: Slovenian',
+ 'Natural Language :: Spanish',
+ 'Operating System :: OS Independent',
+ 'Programming Language :: Python :: 3',
+ 'Programming Language :: Python :: 3.6',
+ 'Programming Language :: Python :: 3.7',
+ 'Programming Language :: Python :: 3.8',
+ 'Programming Language :: Python :: 3.9',
+ 'Programming Language :: Python :: Implementation :: CPython',
+ 'Programming Language :: Python :: Implementation :: PyPy',
+ 'Topic :: Office/Business',
+ ],
+ license='GPL-3',
+ python_requires='>=3.6',
+ install_requires=requires,
+ dependency_links=dependency_links,
+ zip_safe=False,
+ entry_points="""
+ [trytond.modules]
+ sale_secondary_unit = trytond.modules.sale_secondary_unit
+ """,
+ test_suite='tests',
+ test_loader='trytond.test_loader:Loader',
+ tests_require=tests_require,
+ )
diff --git a/modules/sale_secondary_unit/stock.py b/modules/sale_secondary_unit/stock.py
new file mode 100644
index 0000000000..6fbfd35b6a
--- /dev/null
+++ b/modules/sale_secondary_unit/stock.py
@@ -0,0 +1,35 @@
+# This file is part of Tryton. The COPYRIGHT file at the top level of
+# this repository contains the full copyright notices and license terms.
+
+from trytond.pool import PoolMeta, Pool
+
+
+class Move(metaclass=PoolMeta):
+ __name__ = 'stock.move'
+
+ def get_product_secondary_uom_category(self, name):
+ pool = Pool()
+ SaleLine = pool.get('sale.line')
+ category = super().get_product_secondary_uom_category(name)
+ if isinstance(self.origin, SaleLine):
+ if self.origin.secondary_unit:
+ category = self.origin.secondary_unit.category.id
+ return category
+
+ @property
+ def secondary_uom_factor(self):
+ pool = Pool()
+ SaleLine = pool.get('sale.line')
+ factor = super().secondary_uom_factor
+ if isinstance(self.origin, SaleLine):
+ factor = self.origin.secondary_uom_factor
+ return factor
+
+ @property
+ def secondary_uom_rate(self):
+ pool = Pool()
+ SaleLine = pool.get('sale.line')
+ factor = super().secondary_uom_rate
+ if isinstance(self.origin, SaleLine):
+ factor = self.origin.secondary_uom_rate
+ return factor
diff --git a/modules/sale_secondary_unit/stock.xml b/modules/sale_secondary_unit/stock.xml
new file mode 100644
index 0000000000..112f045972
--- /dev/null
+++ b/modules/sale_secondary_unit/stock.xml
@@ -0,0 +1,12 @@
+
+
+
+
+
+ stock.move
+
+ stock_move_list
+
+
+
diff --git a/modules/sale_secondary_unit/tests/__init__.py b/modules/sale_secondary_unit/tests/__init__.py
new file mode 100644
index 0000000000..9b2b1faa06
--- /dev/null
+++ b/modules/sale_secondary_unit/tests/__init__.py
@@ -0,0 +1,9 @@
+# This file is part of Tryton. The COPYRIGHT file at the top level of
+# this repository contains the full copyright notices and license terms.
+
+try:
+ from trytond.modules.sale_secondary_unit.tests.test_sale_secondary_unit import suite # noqa: E501
+except ImportError:
+ from .test_sale_secondary_unit import suite
+
+__all__ = ['suite']
diff --git a/modules/sale_secondary_unit/tests/scenario_sale_secondary_unit.rst b/modules/sale_secondary_unit/tests/scenario_sale_secondary_unit.rst
new file mode 100644
index 0000000000..1cbc79722d
--- /dev/null
+++ b/modules/sale_secondary_unit/tests/scenario_sale_secondary_unit.rst
@@ -0,0 +1,135 @@
+============================
+Sale Secondary Unit Scenario
+============================
+
+Imports::
+
+ >>> from decimal import Decimal
+ >>> from proteus import Model, Wizard
+ >>> from trytond.tests.tools import activate_modules
+ >>> from trytond.modules.company.tests.tools import create_company, \
+ ... get_company
+ >>> from trytond.modules.account.tests.tools import create_chart, \
+ ... get_accounts
+
+Activate modules::
+
+ >>> config = activate_modules(
+ ... ['sale_secondary_unit',
+ ... 'account_invoice_secondary_unit',
+ ... 'stock_secondary_unit'])
+
+Create company::
+
+ >>> _ = create_company()
+ >>> company = get_company()
+
+Create chart of accounts::
+
+ >>> _ = create_chart(company)
+ >>> accounts = get_accounts(company)
+
+Create customer::
+
+ >>> Party = Model.get('party.party')
+ >>> customer = Party(name="Customer")
+ >>> customer.save()
+
+Create account categories::
+
+ >>> ProductCategory = Model.get('product.category')
+ >>> account_category = ProductCategory(name="Account Category")
+ >>> account_category.accounting = True
+ >>> account_category.account_expense = accounts['expense']
+ >>> account_category.account_revenue = accounts['revenue']
+ >>> account_category.save()
+
+Create product::
+
+ >>> ProductUom = Model.get('product.uom')
+ >>> unit, = ProductUom.find([('name', '=', "Unit")])
+ >>> gr, = ProductUom.find([('name', '=', "Gram")])
+ >>> kg, = ProductUom.find([('name', '=', "Kilogram")])
+ >>> ProductTemplate = Model.get('product.template')
+
+ >>> template = ProductTemplate()
+ >>> template.name = 'product'
+ >>> template.default_uom = unit
+ >>> template.type = 'goods'
+ >>> template.salable = True
+ >>> template.sale_secondary_uom = gr
+ >>> template.sale_secondary_uom_factor = 200
+ >>> template.sale_secondary_uom_rate
+ 0.005
+ >>> template.list_price = Decimal('10')
+ >>> template.account_category = account_category
+ >>> template.save()
+ >>> product, = template.products
+
+Sale product::
+
+ >>> Sale = Model.get('sale.sale')
+ >>> sale = Sale()
+ >>> sale.party = customer
+ >>> line = sale.lines.new()
+ >>> line.type = 'comment'
+ >>> line.description = 'Comment'
+ >>> line = sale.lines.new()
+ >>> line.product = product
+ >>> line.quantity = 10
+
+Check secondary unit::
+
+ >>> line.secondary_unit = kg
+ >>> line.secondary_quantity
+ 2.0
+ >>> line.secondary_unit_price
+ Decimal('50.0000')
+ >>> line.secondary_unit_price = Decimal('40')
+ >>> line.unit_price
+ Decimal('8.0000')
+ >>> line.secondary_quantity = 1000
+ >>> line.quantity
+ 5000.0
+ >>> line.secondary_unit = gr
+ >>> line.quantity
+ 5.0
+
+Confirm sale::
+
+ >>> line.secondary_unit = kg
+ >>> line.quantity = 10
+ >>> sale.click('quote')
+ >>> sale.click('confirm')
+ >>> sale.invoice_state
+ 'waiting'
+ >>> sale.shipment_state
+ 'waiting'
+
+Check secondary unit on invoice::
+
+ >>> invoice, = sale.invoices
+ >>> _, line = invoice.lines
+ >>> line.secondary_unit == kg
+ True
+ >>> line.secondary_quantity
+ 2.0
+ >>> line.secondary_unit_price
+ Decimal('50.0000')
+
+Check secondary unit on move::
+
+ >>> move, = sale.moves
+ >>> move.secondary_unit == kg
+ True
+ >>> move.secondary_quantity
+ 2.0
+ >>> move.secondary_unit_price
+ Decimal('50.0000')
+
+ >>> shipment, = sale.shipments
+ >>> move, = shipment.inventory_moves
+ >>> move.secondary_unit == kg
+ True
+ >>> move.secondary_quantity
+ 2.0
diff --git a/modules/sale_secondary_unit/tests/test_sale_secondary_unit.py b/modules/sale_secondary_unit/tests/test_sale_secondary_unit.py
new file mode 100644
index 0000000000..4f5cdbc577
--- /dev/null
+++ b/modules/sale_secondary_unit/tests/test_sale_secondary_unit.py
@@ -0,0 +1,31 @@
+# This file is part of Tryton. The COPYRIGHT file at the top level of
+# this repository contains the full copyright notices and license terms.
+
+import unittest
+
+import doctest
+
+from trytond.tests.test_tryton import ModuleTestCase
+from trytond.tests.test_tryton import suite as test_suite
+from trytond.tests.test_tryton import doctest_teardown
+from trytond.tests.test_tryton import doctest_checker
+
+
+class SaleSecondaryUnitTestCase(ModuleTestCase):
+ 'Test Sale Secondary Unit module'
+ module = 'sale_secondary_unit'
+ extras = [
+ 'account_invoice_secondary_unit', 'stock_secondary_unit',
+ 'sale_product_customer']
+
+
+def suite():
+ suite = test_suite()
+ suite.addTests(unittest.TestLoader().loadTestsFromTestCase(
+ SaleSecondaryUnitTestCase))
+ suite.addTests(doctest.DocFileSuite(
+ 'scenario_sale_secondary_unit.rst',
+ tearDown=doctest_teardown, encoding='utf-8',
+ checker=doctest_checker,
+ optionflags=doctest.REPORT_ONLY_FIRST_FAILURE))
+ return suite
diff --git a/modules/sale_secondary_unit/tox.ini b/modules/sale_secondary_unit/tox.ini
new file mode 100644
index 0000000000..197496c0cb
--- /dev/null
+++ b/modules/sale_secondary_unit/tox.ini
@@ -0,0 +1,15 @@
+[tox]
+envlist = {py36,py37,py38,py39}-{sqlite,postgresql},pypy3-{sqlite,postgresql}
+
+[testenv]
+commands = {envpython} setup.py test
+deps =
+ {py36,py37,py38,py39}-postgresql: psycopg2 >= 2.5
+ pypy3-postgresql: psycopg2cffi >= 2.5
+ py36-sqlite: sqlitebck
+setenv =
+ sqlite: TRYTOND_DATABASE_URI={env:SQLITE_URI:sqlite://}
+ postgresql: TRYTOND_DATABASE_URI={env:POSTGRESQL_URI:postgresql://}
+ sqlite: DB_NAME={env:SQLITE_NAME::memory:}
+ postgresql: DB_NAME={env:POSTGRESQL_NAME:test}
+install_command = pip install --pre --find-links https://trydevpi.tryton.org/?local_version={env:CI_JOB_ID:{env:CI_BUILD_NUMBER}.{env:CI_JOB_NUMBER}} {opts} {packages}
diff --git a/modules/sale_secondary_unit/tryton.cfg b/modules/sale_secondary_unit/tryton.cfg
new file mode 100644
index 0000000000..931975a26e
--- /dev/null
+++ b/modules/sale_secondary_unit/tryton.cfg
@@ -0,0 +1,18 @@
+[tryton]
+version=6.0.1
+depends:
+ account_invoice
+ ir
+ product
+ sale
+ stock
+extras_depend:
+ account_invoice_secondary_unit
+ sale_opportunity
+ sale_product_customer
+ stock_secondary_unit
+xml:
+ product.xml
+ sale.xml
+ stock.xml
+ message.xml
diff --git a/modules/sale_secondary_unit/view/product_customer_form.xml b/modules/sale_secondary_unit/view/product_customer_form.xml
new file mode 100644
index 0000000000..83b8f99790
--- /dev/null
+++ b/modules/sale_secondary_unit/view/product_customer_form.xml
@@ -0,0 +1,15 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/modules/sale_secondary_unit/view/product_template_form.xml b/modules/sale_secondary_unit/view/product_template_form.xml
new file mode 100644
index 0000000000..3c0786604a
--- /dev/null
+++ b/modules/sale_secondary_unit/view/product_template_form.xml
@@ -0,0 +1,16 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/modules/sale_secondary_unit/view/sale_line_form.xml b/modules/sale_secondary_unit/view/sale_line_form.xml
new file mode 100644
index 0000000000..7d739b0b1d
--- /dev/null
+++ b/modules/sale_secondary_unit/view/sale_line_form.xml
@@ -0,0 +1,15 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/modules/sale_secondary_unit/view/sale_line_tree.xml b/modules/sale_secondary_unit/view/sale_line_tree.xml
new file mode 100644
index 0000000000..3fb140383f
--- /dev/null
+++ b/modules/sale_secondary_unit/view/sale_line_tree.xml
@@ -0,0 +1,9 @@
+
+
+
+
+
+
+
+
diff --git a/modules/sale_secondary_unit/view/stock_move_list.xml b/modules/sale_secondary_unit/view/stock_move_list.xml
new file mode 100644
index 0000000000..0f768acc8b
--- /dev/null
+++ b/modules/sale_secondary_unit/view/stock_move_list.xml
@@ -0,0 +1,8 @@
+
+
+
+
+
+
+
diff --git a/modules/sale_shipment_cost/.drone.yml b/modules/sale_shipment_cost/.drone.yml
new file mode 100644
index 0000000000..2049d30a49
--- /dev/null
+++ b/modules/sale_shipment_cost/.drone.yml
@@ -0,0 +1,68 @@
+clone:
+ hg:
+ image: plugins/hg
+ environment:
+ - HG_SHARE_POOL=/root/.cache/hg
+ volumes:
+ - cache:/root/.cache
+
+pipeline:
+ tox:
+ image: ${IMAGE}
+ environment:
+ - CFLAGS=-O0
+ - DB_CACHE=/cache
+ - TOX_TESTENV_PASSENV=CFLAGS DB_CACHE CI_BUILD_NUMBER CI_JOB_NUMBER CI_JOB_ID
+ - POSTGRESQL_URI=postgresql://postgres@postgresql:5432/
+ commands:
+ - echo "[extensions]" >> /root/.hgrc
+ - echo "hgext.share =" >> /root/.hgrc
+ - echo "[share]" >> /root/.hgrc
+ - echo "pool = /root/.cache/hg" >> /root/.hgrc
+ - pip install tox
+ - tox -e "${TOXENV}-${DATABASE}"
+ volumes:
+ - cache:/root/.cache
+ check_dist:
+ image: ${IMAGE}
+ commands:
+ - pip install twine
+ - python setup.py sdist
+ - twine check dist/*
+
+services:
+ postgresql:
+ image: postgres
+ environment:
+ - POSTGRES_HOST_AUTH_METHOD=trust
+ command: "-c fsync=off -c synchronous_commit=off -c full_page_writes=off"
+ when:
+ matrix:
+ DATABASE: postgresql
+
+matrix:
+ include:
+ - IMAGE: python:3.6
+ TOXENV: py36
+ DATABASE: sqlite
+ - IMAGE: python:3.6
+ TOXENV: py36
+ DATABASE: postgresql
+ - IMAGE: python:3.7
+ TOXENV: py37
+ DATABASE: sqlite
+ - IMAGE: python:3.7
+ TOXENV: py37
+ DATABASE: postgresql
+ - IMAGE: python:3.8
+ TOXENV: py38
+ DATABASE: sqlite
+ - IMAGE: python:3.8
+ TOXENV: py38
+ DATABASE: postgresql
+ - IMAGE: python:3.9
+ TOXENV: py39
+ DATABASE: sqlite
+ - IMAGE: python:3.9
+ TOXENV: py39
+ DATABASE: postgresql
diff --git a/modules/sale_shipment_cost/.flake8 b/modules/sale_shipment_cost/.flake8
new file mode 100644
index 0000000000..fa6b4f66d1
--- /dev/null
+++ b/modules/sale_shipment_cost/.flake8
@@ -0,0 +1,2 @@
+[flake8]
+ignore=E123,E124,E126,E128,E741,W503
diff --git a/modules/sale_shipment_cost/CHANGELOG b/modules/sale_shipment_cost/CHANGELOG
new file mode 100644
index 0000000000..ccb71e501e
--- /dev/null
+++ b/modules/sale_shipment_cost/CHANGELOG
@@ -0,0 +1,97 @@
+Version 6.0.4 - 2022-08-03
+* Bug fixes (see mercurial logs for details)
+
+Version 6.0.3 - 2022-02-16
+* Bug fixes (see mercurial logs for details)
+
+Version 6.0.2 - 2021-10-15
+* Bug fixes (see mercurial logs for details)
+
+Version 6.0.1 - 2021-09-01
+* Bug fixes (see mercurial logs for details)
+
+Version 6.0.0 - 2021-05-03
+* Bug fixes (see mercurial logs for details)
+* Allow to add a sale shipment line with cost 0
+* Add unsold shipment cost to the outgoing moves
+* Simplify manual alteration of shipment cost
+* Use purchase carrier price as cost for shipment
+* Allow shipment costs to not be sold
+* Add carrier on shipment list view
+* Exclude by default shipment cost from promotion amount
+* Allow shipment cost price to be edited
+
+Version 5.8.0 - 2020-11-02
+* Bug fixes (see mercurial logs for details)
+* Remove support for Python 3.5
+* Compute shipment cost without creating a line
+
+Version 5.6.0 - 2020-05-04
+* Bug fixes (see mercurial logs for details)
+
+Version 5.4.0 - 2019-11-04
+* Bug fixes (see mercurial logs for details)
+
+Version 5.2.0 - 2019-05-06
+* Bug fixes (see mercurial logs for details)
+
+Version 5.0.0 - 2018-10-01
+* Bug fixes (see mercurial logs for details)
+* Remove support for Python 2.7
+* Invoice shipment cost with cost method on order and invoice method on
+ shipment when at least one shipment is done.
+
+Version 4.8.0 - 2018-04-23
+* Bug fixes (see mercurial logs for details)
+* Do not compute shipment cost when not shipping goods
+* Do not recompute returned shipment cost
+* Do not match carrier selection with countries if countries are unknown
+
+Version 4.6.0 - 2017-10-30
+* Bug fixes (see mercurial logs for details)
+* Invoice shipment cost when at least one shipment is done
+* Use price_digits for storing cost
+
+Version 4.4.0 - 2017-05-01
+* Bug fixes (see mercurial logs for details)
+
+Version 4.2.0 - 2016-11-28
+* Bug fixes (see mercurial logs for details)
+* Use Carrier Selection instead of a company wise default value
+
+Version 4.0.0 - 2016-05-02
+* Bug fixes (see mercurial logs for details)
+* Add Python3 support
+
+Version 3.8.0 - 2015-11-02
+* Bug fixes (see mercurial logs for details)
+
+Version 3.6.0 - 2015-04-20
+* Bug fixes (see mercurial logs for details)
+* Add support for PyPy
+* Set sale shipment cost on sale only at quotation
+* Allow to change the carrier until the shipment is done
+
+Version 3.4.0 - 2014-10-20
+* Bug fixes (see mercurial logs for details)
+
+Version 3.2.0 - 2014-04-21
+* Bug fixes (see mercurial logs for details)
+
+Version 3.0.0 - 2013-10-21
+* Bug fixes (see mercurial logs for details)
+
+Version 2.8.0 - 2013-04-22
+* Bug fixes (see mercurial logs for details)
+
+Version 2.6.0 - 2012-10-22
+* Bug fixes (see mercurial logs for details)
+
+Version 2.4.0 - 2012-04-24
+* Bug fixes (see mercurial logs for details)
+
+Version 2.2.0 - 2011-10-25
+* Bug fixes (see mercurial logs for details)
+
+Version 2.0.0 - 2011-10-17
+* Initial release
diff --git a/modules/sale_shipment_cost/COPYRIGHT b/modules/sale_shipment_cost/COPYRIGHT
new file mode 100644
index 0000000000..c5d12b7c2d
--- /dev/null
+++ b/modules/sale_shipment_cost/COPYRIGHT
@@ -0,0 +1,17 @@
+Copyright (C) 2011-2022 Cédric Krier.
+Copyright (C) 2011-2013 Bertrand Chenal.
+Copyright (C) 2011-2022 Nicolas Évrard.
+Copyright (C) 2011-2022 B2CK SPRL.
+
+This program is free software: you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation, either version 3 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program. If not, see .
diff --git a/modules/sale_shipment_cost/LICENSE b/modules/sale_shipment_cost/LICENSE
new file mode 100644
index 0000000000..94a9ed024d
--- /dev/null
+++ b/modules/sale_shipment_cost/LICENSE
@@ -0,0 +1,674 @@
+ GNU GENERAL PUBLIC LICENSE
+ Version 3, 29 June 2007
+
+ Copyright (C) 2007 Free Software Foundation, Inc.
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+ Preamble
+
+ The GNU General Public License is a free, copyleft license for
+software and other kinds of works.
+
+ The licenses for most software and other practical works are designed
+to take away your freedom to share and change the works. By contrast,
+the GNU General Public License is intended to guarantee your freedom to
+share and change all versions of a program--to make sure it remains free
+software for all its users. We, the Free Software Foundation, use the
+GNU General Public License for most of our software; it applies also to
+any other work released this way by its authors. You can apply it to
+your programs, too.
+
+ When we speak of free software, we are referring to freedom, not
+price. Our General Public Licenses are designed to make sure that you
+have the freedom to distribute copies of free software (and charge for
+them if you wish), that you receive source code or can get it if you
+want it, that you can change the software or use pieces of it in new
+free programs, and that you know you can do these things.
+
+ To protect your rights, we need to prevent others from denying you
+these rights or asking you to surrender the rights. Therefore, you have
+certain responsibilities if you distribute copies of the software, or if
+you modify it: responsibilities to respect the freedom of others.
+
+ For example, if you distribute copies of such a program, whether
+gratis or for a fee, you must pass on to the recipients the same
+freedoms that you received. You must make sure that they, too, receive
+or can get the source code. And you must show them these terms so they
+know their rights.
+
+ Developers that use the GNU GPL protect your rights with two steps:
+(1) assert copyright on the software, and (2) offer you this License
+giving you legal permission to copy, distribute and/or modify it.
+
+ For the developers' and authors' protection, the GPL clearly explains
+that there is no warranty for this free software. For both users' and
+authors' sake, the GPL requires that modified versions be marked as
+changed, so that their problems will not be attributed erroneously to
+authors of previous versions.
+
+ Some devices are designed to deny users access to install or run
+modified versions of the software inside them, although the manufacturer
+can do so. This is fundamentally incompatible with the aim of
+protecting users' freedom to change the software. The systematic
+pattern of such abuse occurs in the area of products for individuals to
+use, which is precisely where it is most unacceptable. Therefore, we
+have designed this version of the GPL to prohibit the practice for those
+products. If such problems arise substantially in other domains, we
+stand ready to extend this provision to those domains in future versions
+of the GPL, as needed to protect the freedom of users.
+
+ Finally, every program is threatened constantly by software patents.
+States should not allow patents to restrict development and use of
+software on general-purpose computers, but in those that do, we wish to
+avoid the special danger that patents applied to a free program could
+make it effectively proprietary. To prevent this, the GPL assures that
+patents cannot be used to render the program non-free.
+
+ The precise terms and conditions for copying, distribution and
+modification follow.
+
+ TERMS AND CONDITIONS
+
+ 0. Definitions.
+
+ "This License" refers to version 3 of the GNU General Public License.
+
+ "Copyright" also means copyright-like laws that apply to other kinds of
+works, such as semiconductor masks.
+
+ "The Program" refers to any copyrightable work licensed under this
+License. Each licensee is addressed as "you". "Licensees" and
+"recipients" may be individuals or organizations.
+
+ To "modify" a work means to copy from or adapt all or part of the work
+in a fashion requiring copyright permission, other than the making of an
+exact copy. The resulting work is called a "modified version" of the
+earlier work or a work "based on" the earlier work.
+
+ A "covered work" means either the unmodified Program or a work based
+on the Program.
+
+ To "propagate" a work means to do anything with it that, without
+permission, would make you directly or secondarily liable for
+infringement under applicable copyright law, except executing it on a
+computer or modifying a private copy. Propagation includes copying,
+distribution (with or without modification), making available to the
+public, and in some countries other activities as well.
+
+ To "convey" a work means any kind of propagation that enables other
+parties to make or receive copies. Mere interaction with a user through
+a computer network, with no transfer of a copy, is not conveying.
+
+ An interactive user interface displays "Appropriate Legal Notices"
+to the extent that it includes a convenient and prominently visible
+feature that (1) displays an appropriate copyright notice, and (2)
+tells the user that there is no warranty for the work (except to the
+extent that warranties are provided), that licensees may convey the
+work under this License, and how to view a copy of this License. If
+the interface presents a list of user commands or options, such as a
+menu, a prominent item in the list meets this criterion.
+
+ 1. Source Code.
+
+ The "source code" for a work means the preferred form of the work
+for making modifications to it. "Object code" means any non-source
+form of a work.
+
+ A "Standard Interface" means an interface that either is an official
+standard defined by a recognized standards body, or, in the case of
+interfaces specified for a particular programming language, one that
+is widely used among developers working in that language.
+
+ The "System Libraries" of an executable work include anything, other
+than the work as a whole, that (a) is included in the normal form of
+packaging a Major Component, but which is not part of that Major
+Component, and (b) serves only to enable use of the work with that
+Major Component, or to implement a Standard Interface for which an
+implementation is available to the public in source code form. A
+"Major Component", in this context, means a major essential component
+(kernel, window system, and so on) of the specific operating system
+(if any) on which the executable work runs, or a compiler used to
+produce the work, or an object code interpreter used to run it.
+
+ The "Corresponding Source" for a work in object code form means all
+the source code needed to generate, install, and (for an executable
+work) run the object code and to modify the work, including scripts to
+control those activities. However, it does not include the work's
+System Libraries, or general-purpose tools or generally available free
+programs which are used unmodified in performing those activities but
+which are not part of the work. For example, Corresponding Source
+includes interface definition files associated with source files for
+the work, and the source code for shared libraries and dynamically
+linked subprograms that the work is specifically designed to require,
+such as by intimate data communication or control flow between those
+subprograms and other parts of the work.
+
+ The Corresponding Source need not include anything that users
+can regenerate automatically from other parts of the Corresponding
+Source.
+
+ The Corresponding Source for a work in source code form is that
+same work.
+
+ 2. Basic Permissions.
+
+ All rights granted under this License are granted for the term of
+copyright on the Program, and are irrevocable provided the stated
+conditions are met. This License explicitly affirms your unlimited
+permission to run the unmodified Program. The output from running a
+covered work is covered by this License only if the output, given its
+content, constitutes a covered work. This License acknowledges your
+rights of fair use or other equivalent, as provided by copyright law.
+
+ You may make, run and propagate covered works that you do not
+convey, without conditions so long as your license otherwise remains
+in force. You may convey covered works to others for the sole purpose
+of having them make modifications exclusively for you, or provide you
+with facilities for running those works, provided that you comply with
+the terms of this License in conveying all material for which you do
+not control copyright. Those thus making or running the covered works
+for you must do so exclusively on your behalf, under your direction
+and control, on terms that prohibit them from making any copies of
+your copyrighted material outside their relationship with you.
+
+ Conveying under any other circumstances is permitted solely under
+the conditions stated below. Sublicensing is not allowed; section 10
+makes it unnecessary.
+
+ 3. Protecting Users' Legal Rights From Anti-Circumvention Law.
+
+ No covered work shall be deemed part of an effective technological
+measure under any applicable law fulfilling obligations under article
+11 of the WIPO copyright treaty adopted on 20 December 1996, or
+similar laws prohibiting or restricting circumvention of such
+measures.
+
+ When you convey a covered work, you waive any legal power to forbid
+circumvention of technological measures to the extent such circumvention
+is effected by exercising rights under this License with respect to
+the covered work, and you disclaim any intention to limit operation or
+modification of the work as a means of enforcing, against the work's
+users, your or third parties' legal rights to forbid circumvention of
+technological measures.
+
+ 4. Conveying Verbatim Copies.
+
+ You may convey verbatim copies of the Program's source code as you
+receive it, in any medium, provided that you conspicuously and
+appropriately publish on each copy an appropriate copyright notice;
+keep intact all notices stating that this License and any
+non-permissive terms added in accord with section 7 apply to the code;
+keep intact all notices of the absence of any warranty; and give all
+recipients a copy of this License along with the Program.
+
+ You may charge any price or no price for each copy that you convey,
+and you may offer support or warranty protection for a fee.
+
+ 5. Conveying Modified Source Versions.
+
+ You may convey a work based on the Program, or the modifications to
+produce it from the Program, in the form of source code under the
+terms of section 4, provided that you also meet all of these conditions:
+
+ a) The work must carry prominent notices stating that you modified
+ it, and giving a relevant date.
+
+ b) The work must carry prominent notices stating that it is
+ released under this License and any conditions added under section
+ 7. This requirement modifies the requirement in section 4 to
+ "keep intact all notices".
+
+ c) You must license the entire work, as a whole, under this
+ License to anyone who comes into possession of a copy. This
+ License will therefore apply, along with any applicable section 7
+ additional terms, to the whole of the work, and all its parts,
+ regardless of how they are packaged. This License gives no
+ permission to license the work in any other way, but it does not
+ invalidate such permission if you have separately received it.
+
+ d) If the work has interactive user interfaces, each must display
+ Appropriate Legal Notices; however, if the Program has interactive
+ interfaces that do not display Appropriate Legal Notices, your
+ work need not make them do so.
+
+ A compilation of a covered work with other separate and independent
+works, which are not by their nature extensions of the covered work,
+and which are not combined with it such as to form a larger program,
+in or on a volume of a storage or distribution medium, is called an
+"aggregate" if the compilation and its resulting copyright are not
+used to limit the access or legal rights of the compilation's users
+beyond what the individual works permit. Inclusion of a covered work
+in an aggregate does not cause this License to apply to the other
+parts of the aggregate.
+
+ 6. Conveying Non-Source Forms.
+
+ You may convey a covered work in object code form under the terms
+of sections 4 and 5, provided that you also convey the
+machine-readable Corresponding Source under the terms of this License,
+in one of these ways:
+
+ a) Convey the object code in, or embodied in, a physical product
+ (including a physical distribution medium), accompanied by the
+ Corresponding Source fixed on a durable physical medium
+ customarily used for software interchange.
+
+ b) Convey the object code in, or embodied in, a physical product
+ (including a physical distribution medium), accompanied by a
+ written offer, valid for at least three years and valid for as
+ long as you offer spare parts or customer support for that product
+ model, to give anyone who possesses the object code either (1) a
+ copy of the Corresponding Source for all the software in the
+ product that is covered by this License, on a durable physical
+ medium customarily used for software interchange, for a price no
+ more than your reasonable cost of physically performing this
+ conveying of source, or (2) access to copy the
+ Corresponding Source from a network server at no charge.
+
+ c) Convey individual copies of the object code with a copy of the
+ written offer to provide the Corresponding Source. This
+ alternative is allowed only occasionally and noncommercially, and
+ only if you received the object code with such an offer, in accord
+ with subsection 6b.
+
+ d) Convey the object code by offering access from a designated
+ place (gratis or for a charge), and offer equivalent access to the
+ Corresponding Source in the same way through the same place at no
+ further charge. You need not require recipients to copy the
+ Corresponding Source along with the object code. If the place to
+ copy the object code is a network server, the Corresponding Source
+ may be on a different server (operated by you or a third party)
+ that supports equivalent copying facilities, provided you maintain
+ clear directions next to the object code saying where to find the
+ Corresponding Source. Regardless of what server hosts the
+ Corresponding Source, you remain obligated to ensure that it is
+ available for as long as needed to satisfy these requirements.
+
+ e) Convey the object code using peer-to-peer transmission, provided
+ you inform other peers where the object code and Corresponding
+ Source of the work are being offered to the general public at no
+ charge under subsection 6d.
+
+ A separable portion of the object code, whose source code is excluded
+from the Corresponding Source as a System Library, need not be
+included in conveying the object code work.
+
+ A "User Product" is either (1) a "consumer product", which means any
+tangible personal property which is normally used for personal, family,
+or household purposes, or (2) anything designed or sold for incorporation
+into a dwelling. In determining whether a product is a consumer product,
+doubtful cases shall be resolved in favor of coverage. For a particular
+product received by a particular user, "normally used" refers to a
+typical or common use of that class of product, regardless of the status
+of the particular user or of the way in which the particular user
+actually uses, or expects or is expected to use, the product. A product
+is a consumer product regardless of whether the product has substantial
+commercial, industrial or non-consumer uses, unless such uses represent
+the only significant mode of use of the product.
+
+ "Installation Information" for a User Product means any methods,
+procedures, authorization keys, or other information required to install
+and execute modified versions of a covered work in that User Product from
+a modified version of its Corresponding Source. The information must
+suffice to ensure that the continued functioning of the modified object
+code is in no case prevented or interfered with solely because
+modification has been made.
+
+ If you convey an object code work under this section in, or with, or
+specifically for use in, a User Product, and the conveying occurs as
+part of a transaction in which the right of possession and use of the
+User Product is transferred to the recipient in perpetuity or for a
+fixed term (regardless of how the transaction is characterized), the
+Corresponding Source conveyed under this section must be accompanied
+by the Installation Information. But this requirement does not apply
+if neither you nor any third party retains the ability to install
+modified object code on the User Product (for example, the work has
+been installed in ROM).
+
+ The requirement to provide Installation Information does not include a
+requirement to continue to provide support service, warranty, or updates
+for a work that has been modified or installed by the recipient, or for
+the User Product in which it has been modified or installed. Access to a
+network may be denied when the modification itself materially and
+adversely affects the operation of the network or violates the rules and
+protocols for communication across the network.
+
+ Corresponding Source conveyed, and Installation Information provided,
+in accord with this section must be in a format that is publicly
+documented (and with an implementation available to the public in
+source code form), and must require no special password or key for
+unpacking, reading or copying.
+
+ 7. Additional Terms.
+
+ "Additional permissions" are terms that supplement the terms of this
+License by making exceptions from one or more of its conditions.
+Additional permissions that are applicable to the entire Program shall
+be treated as though they were included in this License, to the extent
+that they are valid under applicable law. If additional permissions
+apply only to part of the Program, that part may be used separately
+under those permissions, but the entire Program remains governed by
+this License without regard to the additional permissions.
+
+ When you convey a copy of a covered work, you may at your option
+remove any additional permissions from that copy, or from any part of
+it. (Additional permissions may be written to require their own
+removal in certain cases when you modify the work.) You may place
+additional permissions on material, added by you to a covered work,
+for which you have or can give appropriate copyright permission.
+
+ Notwithstanding any other provision of this License, for material you
+add to a covered work, you may (if authorized by the copyright holders of
+that material) supplement the terms of this License with terms:
+
+ a) Disclaiming warranty or limiting liability differently from the
+ terms of sections 15 and 16 of this License; or
+
+ b) Requiring preservation of specified reasonable legal notices or
+ author attributions in that material or in the Appropriate Legal
+ Notices displayed by works containing it; or
+
+ c) Prohibiting misrepresentation of the origin of that material, or
+ requiring that modified versions of such material be marked in
+ reasonable ways as different from the original version; or
+
+ d) Limiting the use for publicity purposes of names of licensors or
+ authors of the material; or
+
+ e) Declining to grant rights under trademark law for use of some
+ trade names, trademarks, or service marks; or
+
+ f) Requiring indemnification of licensors and authors of that
+ material by anyone who conveys the material (or modified versions of
+ it) with contractual assumptions of liability to the recipient, for
+ any liability that these contractual assumptions directly impose on
+ those licensors and authors.
+
+ All other non-permissive additional terms are considered "further
+restrictions" within the meaning of section 10. If the Program as you
+received it, or any part of it, contains a notice stating that it is
+governed by this License along with a term that is a further
+restriction, you may remove that term. If a license document contains
+a further restriction but permits relicensing or conveying under this
+License, you may add to a covered work material governed by the terms
+of that license document, provided that the further restriction does
+not survive such relicensing or conveying.
+
+ If you add terms to a covered work in accord with this section, you
+must place, in the relevant source files, a statement of the
+additional terms that apply to those files, or a notice indicating
+where to find the applicable terms.
+
+ Additional terms, permissive or non-permissive, may be stated in the
+form of a separately written license, or stated as exceptions;
+the above requirements apply either way.
+
+ 8. Termination.
+
+ You may not propagate or modify a covered work except as expressly
+provided under this License. Any attempt otherwise to propagate or
+modify it is void, and will automatically terminate your rights under
+this License (including any patent licenses granted under the third
+paragraph of section 11).
+
+ However, if you cease all violation of this License, then your
+license from a particular copyright holder is reinstated (a)
+provisionally, unless and until the copyright holder explicitly and
+finally terminates your license, and (b) permanently, if the copyright
+holder fails to notify you of the violation by some reasonable means
+prior to 60 days after the cessation.
+
+ Moreover, your license from a particular copyright holder is
+reinstated permanently if the copyright holder notifies you of the
+violation by some reasonable means, this is the first time you have
+received notice of violation of this License (for any work) from that
+copyright holder, and you cure the violation prior to 30 days after
+your receipt of the notice.
+
+ Termination of your rights under this section does not terminate the
+licenses of parties who have received copies or rights from you under
+this License. If your rights have been terminated and not permanently
+reinstated, you do not qualify to receive new licenses for the same
+material under section 10.
+
+ 9. Acceptance Not Required for Having Copies.
+
+ You are not required to accept this License in order to receive or
+run a copy of the Program. Ancillary propagation of a covered work
+occurring solely as a consequence of using peer-to-peer transmission
+to receive a copy likewise does not require acceptance. However,
+nothing other than this License grants you permission to propagate or
+modify any covered work. These actions infringe copyright if you do
+not accept this License. Therefore, by modifying or propagating a
+covered work, you indicate your acceptance of this License to do so.
+
+ 10. Automatic Licensing of Downstream Recipients.
+
+ Each time you convey a covered work, the recipient automatically
+receives a license from the original licensors, to run, modify and
+propagate that work, subject to this License. You are not responsible
+for enforcing compliance by third parties with this License.
+
+ An "entity transaction" is a transaction transferring control of an
+organization, or substantially all assets of one, or subdividing an
+organization, or merging organizations. If propagation of a covered
+work results from an entity transaction, each party to that
+transaction who receives a copy of the work also receives whatever
+licenses to the work the party's predecessor in interest had or could
+give under the previous paragraph, plus a right to possession of the
+Corresponding Source of the work from the predecessor in interest, if
+the predecessor has it or can get it with reasonable efforts.
+
+ You may not impose any further restrictions on the exercise of the
+rights granted or affirmed under this License. For example, you may
+not impose a license fee, royalty, or other charge for exercise of
+rights granted under this License, and you may not initiate litigation
+(including a cross-claim or counterclaim in a lawsuit) alleging that
+any patent claim is infringed by making, using, selling, offering for
+sale, or importing the Program or any portion of it.
+
+ 11. Patents.
+
+ A "contributor" is a copyright holder who authorizes use under this
+License of the Program or a work on which the Program is based. The
+work thus licensed is called the contributor's "contributor version".
+
+ A contributor's "essential patent claims" are all patent claims
+owned or controlled by the contributor, whether already acquired or
+hereafter acquired, that would be infringed by some manner, permitted
+by this License, of making, using, or selling its contributor version,
+but do not include claims that would be infringed only as a
+consequence of further modification of the contributor version. For
+purposes of this definition, "control" includes the right to grant
+patent sublicenses in a manner consistent with the requirements of
+this License.
+
+ Each contributor grants you a non-exclusive, worldwide, royalty-free
+patent license under the contributor's essential patent claims, to
+make, use, sell, offer for sale, import and otherwise run, modify and
+propagate the contents of its contributor version.
+
+ In the following three paragraphs, a "patent license" is any express
+agreement or commitment, however denominated, not to enforce a patent
+(such as an express permission to practice a patent or covenant not to
+sue for patent infringement). To "grant" such a patent license to a
+party means to make such an agreement or commitment not to enforce a
+patent against the party.
+
+ If you convey a covered work, knowingly relying on a patent license,
+and the Corresponding Source of the work is not available for anyone
+to copy, free of charge and under the terms of this License, through a
+publicly available network server or other readily accessible means,
+then you must either (1) cause the Corresponding Source to be so
+available, or (2) arrange to deprive yourself of the benefit of the
+patent license for this particular work, or (3) arrange, in a manner
+consistent with the requirements of this License, to extend the patent
+license to downstream recipients. "Knowingly relying" means you have
+actual knowledge that, but for the patent license, your conveying the
+covered work in a country, or your recipient's use of the covered work
+in a country, would infringe one or more identifiable patents in that
+country that you have reason to believe are valid.
+
+ If, pursuant to or in connection with a single transaction or
+arrangement, you convey, or propagate by procuring conveyance of, a
+covered work, and grant a patent license to some of the parties
+receiving the covered work authorizing them to use, propagate, modify
+or convey a specific copy of the covered work, then the patent license
+you grant is automatically extended to all recipients of the covered
+work and works based on it.
+
+ A patent license is "discriminatory" if it does not include within
+the scope of its coverage, prohibits the exercise of, or is
+conditioned on the non-exercise of one or more of the rights that are
+specifically granted under this License. You may not convey a covered
+work if you are a party to an arrangement with a third party that is
+in the business of distributing software, under which you make payment
+to the third party based on the extent of your activity of conveying
+the work, and under which the third party grants, to any of the
+parties who would receive the covered work from you, a discriminatory
+patent license (a) in connection with copies of the covered work
+conveyed by you (or copies made from those copies), or (b) primarily
+for and in connection with specific products or compilations that
+contain the covered work, unless you entered into that arrangement,
+or that patent license was granted, prior to 28 March 2007.
+
+ Nothing in this License shall be construed as excluding or limiting
+any implied license or other defenses to infringement that may
+otherwise be available to you under applicable patent law.
+
+ 12. No Surrender of Others' Freedom.
+
+ If conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License. If you cannot convey a
+covered work so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you may
+not convey it at all. For example, if you agree to terms that obligate you
+to collect a royalty for further conveying from those to whom you convey
+the Program, the only way you could satisfy both those terms and this
+License would be to refrain entirely from conveying the Program.
+
+ 13. Use with the GNU Affero General Public License.
+
+ Notwithstanding any other provision of this License, you have
+permission to link or combine any covered work with a work licensed
+under version 3 of the GNU Affero General Public License into a single
+combined work, and to convey the resulting work. The terms of this
+License will continue to apply to the part which is the covered work,
+but the special requirements of the GNU Affero General Public License,
+section 13, concerning interaction through a network will apply to the
+combination as such.
+
+ 14. Revised Versions of this License.
+
+ The Free Software Foundation may publish revised and/or new versions of
+the GNU General Public License from time to time. Such new versions will
+be similar in spirit to the present version, but may differ in detail to
+address new problems or concerns.
+
+ Each version is given a distinguishing version number. If the
+Program specifies that a certain numbered version of the GNU General
+Public License "or any later version" applies to it, you have the
+option of following the terms and conditions either of that numbered
+version or of any later version published by the Free Software
+Foundation. If the Program does not specify a version number of the
+GNU General Public License, you may choose any version ever published
+by the Free Software Foundation.
+
+ If the Program specifies that a proxy can decide which future
+versions of the GNU General Public License can be used, that proxy's
+public statement of acceptance of a version permanently authorizes you
+to choose that version for the Program.
+
+ Later license versions may give you additional or different
+permissions. However, no additional obligations are imposed on any
+author or copyright holder as a result of your choosing to follow a
+later version.
+
+ 15. Disclaimer of Warranty.
+
+ THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY
+APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT
+HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY
+OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO,
+THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM
+IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF
+ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
+
+ 16. Limitation of Liability.
+
+ IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS
+THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY
+GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE
+USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF
+DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD
+PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS),
+EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF
+SUCH DAMAGES.
+
+ 17. Interpretation of Sections 15 and 16.
+
+ If the disclaimer of warranty and limitation of liability provided
+above cannot be given local legal effect according to their terms,
+reviewing courts shall apply local law that most closely approximates
+an absolute waiver of all civil liability in connection with the
+Program, unless a warranty or assumption of liability accompanies a
+copy of the Program in return for a fee.
+
+ END OF TERMS AND CONDITIONS
+
+ How to Apply These Terms to Your New Programs
+
+ If you develop a new program, and you want it to be of the greatest
+possible use to the public, the best way to achieve this is to make it
+free software which everyone can redistribute and change under these terms.
+
+ To do so, attach the following notices to the program. It is safest
+to attach them to the start of each source file to most effectively
+state the exclusion of warranty; and each file should have at least
+the "copyright" line and a pointer to where the full notice is found.
+
+
+ Copyright (C)
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see .
+
+Also add information on how to contact you by electronic and paper mail.
+
+ If the program does terminal interaction, make it output a short
+notice like this when it starts in an interactive mode:
+
+ Copyright (C)
+ This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
+ This is free software, and you are welcome to redistribute it
+ under certain conditions; type `show c' for details.
+
+The hypothetical commands `show w' and `show c' should show the appropriate
+parts of the General Public License. Of course, your program's commands
+might be different; for a GUI interface, you would use an "about box".
+
+ You should also get your employer (if you work as a programmer) or school,
+if any, to sign a "copyright disclaimer" for the program, if necessary.
+For more information on this, and how to apply and follow the GNU GPL, see
+.
+
+ The GNU General Public License does not permit incorporating your program
+into proprietary programs. If your program is a subroutine library, you
+may consider it more useful to permit linking proprietary applications with
+the library. If this is what you want to do, use the GNU Lesser General
+Public License instead of this License. But first, please read
+.
diff --git a/modules/sale_shipment_cost/MANIFEST.in b/modules/sale_shipment_cost/MANIFEST.in
new file mode 100644
index 0000000000..e88b2348a3
--- /dev/null
+++ b/modules/sale_shipment_cost/MANIFEST.in
@@ -0,0 +1,5 @@
+include CHANGELOG
+include COPYRIGHT
+include LICENSE
+include README.rst
+include doc/*
diff --git a/modules/sale_shipment_cost/README.rst b/modules/sale_shipment_cost/README.rst
new file mode 120000
index 0000000000..176d9c2695
--- /dev/null
+++ b/modules/sale_shipment_cost/README.rst
@@ -0,0 +1 @@
+doc/index.rst
\ No newline at end of file
diff --git a/modules/sale_shipment_cost/__init__.py b/modules/sale_shipment_cost/__init__.py
new file mode 100644
index 0000000000..034be880af
--- /dev/null
+++ b/modules/sale_shipment_cost/__init__.py
@@ -0,0 +1,23 @@
+# This file is part of Tryton. The COPYRIGHT file at the top level of
+# this repository contains the full copyright notices and license terms.
+
+from trytond.pool import Pool
+from . import sale
+from . import stock
+
+
+def register():
+ Pool.register(
+ sale.Configuration,
+ sale.ConfigurationSaleMethod,
+ sale.Sale,
+ sale.Line,
+ stock.ShipmentOut,
+ module='sale_shipment_cost', type_='model')
+ Pool.register(
+ sale.Promotion,
+ module='sale_shipment_cost', type_='model',
+ depends=['sale_promotion'])
+ Pool.register(
+ sale.ReturnSale,
+ module='sale_shipment_cost', type_='wizard')
diff --git a/modules/sale_shipment_cost/doc/index.rst b/modules/sale_shipment_cost/doc/index.rst
new file mode 100644
index 0000000000..ccda7361be
--- /dev/null
+++ b/modules/sale_shipment_cost/doc/index.rst
@@ -0,0 +1,23 @@
+Sale Shipment Cost Module
+#########################
+
+The sale_shipment_cost module adds shipment cost for sale.
+
+Two new fields are added to *Sale* and *Sale Configuration*:
+
+- *Carrier*: The carrier used for the sale.
+- *Shipment Cost Method*: The method used to compute the cost.
+
+ - *On Order*: The cost will be invoiced once for the sale.
+ - *On Shipment*: The cost will be invoiced for each shipments.
+ - *None*: The cost will not be invoiced to the customer but added to the
+ outgoing moves cost.
+
+At the quotation if a carrier is selected a new line is appended with the
+shipment cost but the added line can be modified when going back to draft.
+
+Three new fields are added to *Customer Shipment*:
+
+- *Carrier*: The carrier used for the shipment.
+- *Cost*: The cost of the shipment.
+- *Cost Currency*: The currency of the cost.
diff --git a/modules/sale_shipment_cost/exceptions.py b/modules/sale_shipment_cost/exceptions.py
new file mode 100644
index 0000000000..172a4daf87
--- /dev/null
+++ b/modules/sale_shipment_cost/exceptions.py
@@ -0,0 +1,8 @@
+# This file is part of Tryton. The COPYRIGHT file at the top level of
+# this repository contains the full copyright notices and license terms.
+
+from trytond.exceptions import UserError
+
+
+class InvoiceShipmentCostError(UserError):
+ pass
diff --git a/modules/sale_shipment_cost/locale/bg.po b/modules/sale_shipment_cost/locale/bg.po
new file mode 100644
index 0000000000..4864f12c53
--- /dev/null
+++ b/modules/sale_shipment_cost/locale/bg.po
@@ -0,0 +1,106 @@
+#
+msgid ""
+msgstr "Content-Type: text/plain; charset=utf-8\n"
+
+msgctxt "field:sale.configuration,sale_shipment_cost_method:"
+msgid "Sale Shipment Cost Method"
+msgstr "Начин на остойностяване на доставка на продажба"
+
+#, fuzzy
+msgctxt "field:sale.configuration.sale_method,sale_shipment_cost_method:"
+msgid "Sale Shipment Cost Method"
+msgstr "Начин на остойностяване на доставка на продажба"
+
+msgctxt "field:sale.line,shipment_cost:"
+msgid "Shipment Cost"
+msgstr "Стойност на пратка"
+
+msgctxt "field:sale.promotion,amount_shipment_cost_included:"
+msgid "Amount with Shipment Cost Included"
+msgstr ""
+
+msgctxt "field:sale.sale,available_carriers:"
+msgid "Available Carriers"
+msgstr ""
+
+msgctxt "field:sale.sale,carrier:"
+msgid "Carrier"
+msgstr "Превозвач"
+
+msgctxt "field:sale.sale,shipment_cost_method:"
+msgid "Shipment Cost Method"
+msgstr "Начин на остойностяване на доставка"
+
+msgctxt "field:stock.shipment.out,carrier:"
+msgid "Carrier"
+msgstr "Превозвач"
+
+msgctxt "field:stock.shipment.out,cost:"
+msgid "Cost"
+msgstr "Разход"
+
+#, fuzzy
+msgctxt "field:stock.shipment.out,cost_edit:"
+msgid "Edit Cost"
+msgstr "Стойност на пратка"
+
+msgctxt "field:stock.shipment.out,cost_invoice_line:"
+msgid "Cost Invoice Line"
+msgstr "Ред от разход от фактура"
+
+#, fuzzy
+msgctxt "field:stock.shipment.out,cost_sale:"
+msgid "Cost Sale"
+msgstr "Разход"
+
+#, fuzzy
+msgctxt "field:stock.shipment.out,cost_sale_currency:"
+msgid "Cost Sale Currency"
+msgstr "Валута при разход"
+
+#, fuzzy
+msgctxt "field:stock.shipment.out,cost_sale_currency_used:"
+msgid "Cost Sale Currency"
+msgstr "Валута при разход"
+
+#, fuzzy
+msgctxt "field:stock.shipment.out,cost_sale_used:"
+msgid "Cost Sale"
+msgstr "Разход"
+
+#, fuzzy
+msgctxt "field:stock.shipment.out,cost_used:"
+msgid "Cost"
+msgstr "Разход"
+
+msgctxt "help:stock.shipment.out,cost_edit:"
+msgid "Check to edit the cost."
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_sale_invalid_carrier"
+msgid "To confirm sale \"%(sale)s\" you must change the carrier \"%(carrier)s\"."
+msgstr ""
+
+msgctxt ""
+"model:ir.message,text:msg_shipment_cost_invoice_missing_account_revenue"
+msgid ""
+"To invoice shipment cost of \"%(shipment)s\", you must define an account "
+"revenue for product \"%(product)s\"."
+msgstr ""
+
+msgctxt "selection:sale.sale,shipment_cost_method:"
+msgid "None"
+msgstr ""
+
+msgctxt "selection:sale.sale,shipment_cost_method:"
+msgid "On Order"
+msgstr "За поръчка"
+
+msgctxt "selection:sale.sale,shipment_cost_method:"
+msgid "On Shipment"
+msgstr "За пратка"
+
+#, fuzzy
+msgctxt "view:sale.promotion:"
+msgid "Shipment Cost Included"
+msgstr "Начин на остойностяване на доставка"
diff --git a/modules/sale_shipment_cost/locale/ca.po b/modules/sale_shipment_cost/locale/ca.po
new file mode 100644
index 0000000000..aad37302e4
--- /dev/null
+++ b/modules/sale_shipment_cost/locale/ca.po
@@ -0,0 +1,102 @@
+#
+msgid ""
+msgstr "Content-Type: text/plain; charset=utf-8\n"
+
+msgctxt "field:sale.configuration,sale_shipment_cost_method:"
+msgid "Sale Shipment Cost Method"
+msgstr "Mètode de cost enviament"
+
+msgctxt "field:sale.configuration.sale_method,sale_shipment_cost_method:"
+msgid "Sale Shipment Cost Method"
+msgstr "Mètode de cost de l'enviament"
+
+msgctxt "field:sale.line,shipment_cost:"
+msgid "Shipment Cost"
+msgstr "Cost d'enviament"
+
+msgctxt "field:sale.promotion,amount_shipment_cost_included:"
+msgid "Amount with Shipment Cost Included"
+msgstr "Import amb costos d'enviament inclosos"
+
+msgctxt "field:sale.sale,available_carriers:"
+msgid "Available Carriers"
+msgstr "Transportistes disponibles"
+
+msgctxt "field:sale.sale,carrier:"
+msgid "Carrier"
+msgstr "Transportista"
+
+msgctxt "field:sale.sale,shipment_cost_method:"
+msgid "Shipment Cost Method"
+msgstr "Mètode de cost enviament"
+
+msgctxt "field:stock.shipment.out,carrier:"
+msgid "Carrier"
+msgstr "Transportista"
+
+msgctxt "field:stock.shipment.out,cost:"
+msgid "Cost"
+msgstr "Cost"
+
+msgctxt "field:stock.shipment.out,cost_edit:"
+msgid "Edit Cost"
+msgstr "Edita cost"
+
+msgctxt "field:stock.shipment.out,cost_invoice_line:"
+msgid "Cost Invoice Line"
+msgstr "Cost de la línia de factura"
+
+msgctxt "field:stock.shipment.out,cost_sale:"
+msgid "Cost Sale"
+msgstr "Cost de la venda"
+
+msgctxt "field:stock.shipment.out,cost_sale_currency:"
+msgid "Cost Sale Currency"
+msgstr "Moneda de cost de la venda"
+
+msgctxt "field:stock.shipment.out,cost_sale_currency_used:"
+msgid "Cost Sale Currency"
+msgstr "Moneda de cost de la venda"
+
+msgctxt "field:stock.shipment.out,cost_sale_used:"
+msgid "Cost Sale"
+msgstr "Cost de la venda"
+
+msgctxt "field:stock.shipment.out,cost_used:"
+msgid "Cost"
+msgstr "Cost"
+
+msgctxt "help:stock.shipment.out,cost_edit:"
+msgid "Check to edit the cost."
+msgstr "Marcar per editar el cost."
+
+msgctxt "model:ir.message,text:msg_sale_invalid_carrier"
+msgid "To confirm sale \"%(sale)s\" you must change the carrier \"%(carrier)s\"."
+msgstr ""
+"Per confirmar la venda \"%(sale)s\" heu de canviar el transportista "
+"\"%(carrier)s\"."
+
+msgctxt ""
+"model:ir.message,text:msg_shipment_cost_invoice_missing_account_revenue"
+msgid ""
+"To invoice shipment cost of \"%(shipment)s\", you must define an account "
+"revenue for product \"%(product)s\"."
+msgstr ""
+"Per facturar el cost de l'enviament \"%(shipment)s\" heu de definir un "
+"compte d'ingressos pel producte \"%(product)s\"."
+
+msgctxt "selection:sale.sale,shipment_cost_method:"
+msgid "None"
+msgstr "Cap"
+
+msgctxt "selection:sale.sale,shipment_cost_method:"
+msgid "On Order"
+msgstr "Al processar"
+
+msgctxt "selection:sale.sale,shipment_cost_method:"
+msgid "On Shipment"
+msgstr "Al enviar-ho"
+
+msgctxt "view:sale.promotion:"
+msgid "Shipment Cost Included"
+msgstr "Cost d'enviament inclos"
diff --git a/modules/sale_shipment_cost/locale/cs.po b/modules/sale_shipment_cost/locale/cs.po
new file mode 100644
index 0000000000..b95356e164
--- /dev/null
+++ b/modules/sale_shipment_cost/locale/cs.po
@@ -0,0 +1,98 @@
+#
+msgid ""
+msgstr "Content-Type: text/plain; charset=utf-8\n"
+
+msgctxt "field:sale.configuration,sale_shipment_cost_method:"
+msgid "Sale Shipment Cost Method"
+msgstr ""
+
+msgctxt "field:sale.configuration.sale_method,sale_shipment_cost_method:"
+msgid "Sale Shipment Cost Method"
+msgstr ""
+
+msgctxt "field:sale.line,shipment_cost:"
+msgid "Shipment Cost"
+msgstr ""
+
+msgctxt "field:sale.promotion,amount_shipment_cost_included:"
+msgid "Amount with Shipment Cost Included"
+msgstr ""
+
+msgctxt "field:sale.sale,available_carriers:"
+msgid "Available Carriers"
+msgstr ""
+
+msgctxt "field:sale.sale,carrier:"
+msgid "Carrier"
+msgstr ""
+
+msgctxt "field:sale.sale,shipment_cost_method:"
+msgid "Shipment Cost Method"
+msgstr ""
+
+msgctxt "field:stock.shipment.out,carrier:"
+msgid "Carrier"
+msgstr ""
+
+msgctxt "field:stock.shipment.out,cost:"
+msgid "Cost"
+msgstr ""
+
+msgctxt "field:stock.shipment.out,cost_edit:"
+msgid "Edit Cost"
+msgstr ""
+
+msgctxt "field:stock.shipment.out,cost_invoice_line:"
+msgid "Cost Invoice Line"
+msgstr ""
+
+msgctxt "field:stock.shipment.out,cost_sale:"
+msgid "Cost Sale"
+msgstr ""
+
+msgctxt "field:stock.shipment.out,cost_sale_currency:"
+msgid "Cost Sale Currency"
+msgstr ""
+
+msgctxt "field:stock.shipment.out,cost_sale_currency_used:"
+msgid "Cost Sale Currency"
+msgstr ""
+
+msgctxt "field:stock.shipment.out,cost_sale_used:"
+msgid "Cost Sale"
+msgstr ""
+
+msgctxt "field:stock.shipment.out,cost_used:"
+msgid "Cost"
+msgstr ""
+
+msgctxt "help:stock.shipment.out,cost_edit:"
+msgid "Check to edit the cost."
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_sale_invalid_carrier"
+msgid "To confirm sale \"%(sale)s\" you must change the carrier \"%(carrier)s\"."
+msgstr ""
+
+msgctxt ""
+"model:ir.message,text:msg_shipment_cost_invoice_missing_account_revenue"
+msgid ""
+"To invoice shipment cost of \"%(shipment)s\", you must define an account "
+"revenue for product \"%(product)s\"."
+msgstr ""
+
+msgctxt "selection:sale.sale,shipment_cost_method:"
+msgid "None"
+msgstr ""
+
+msgctxt "selection:sale.sale,shipment_cost_method:"
+msgid "On Order"
+msgstr ""
+
+msgctxt "selection:sale.sale,shipment_cost_method:"
+msgid "On Shipment"
+msgstr ""
+
+msgctxt "view:sale.promotion:"
+msgid "Shipment Cost Included"
+msgstr ""
diff --git a/modules/sale_shipment_cost/locale/de.po b/modules/sale_shipment_cost/locale/de.po
new file mode 100644
index 0000000000..92d9392b81
--- /dev/null
+++ b/modules/sale_shipment_cost/locale/de.po
@@ -0,0 +1,102 @@
+#
+msgid ""
+msgstr "Content-Type: text/plain; charset=utf-8\n"
+
+msgctxt "field:sale.configuration,sale_shipment_cost_method:"
+msgid "Sale Shipment Cost Method"
+msgstr "Lieferposten Kostenmethode Verkauf"
+
+msgctxt "field:sale.configuration.sale_method,sale_shipment_cost_method:"
+msgid "Sale Shipment Cost Method"
+msgstr "Lieferposten Kostenmethode Verkauf"
+
+msgctxt "field:sale.line,shipment_cost:"
+msgid "Shipment Cost"
+msgstr "Lieferposten Kosten"
+
+msgctxt "field:sale.promotion,amount_shipment_cost_included:"
+msgid "Amount with Shipment Cost Included"
+msgstr "Betrag inklusive Lieferkosten"
+
+msgctxt "field:sale.sale,available_carriers:"
+msgid "Available Carriers"
+msgstr "Verfügbare Versanddienstleister"
+
+msgctxt "field:sale.sale,carrier:"
+msgid "Carrier"
+msgstr "Versanddienstleister"
+
+msgctxt "field:sale.sale,shipment_cost_method:"
+msgid "Shipment Cost Method"
+msgstr "Lieferposten Kostenmethode"
+
+msgctxt "field:stock.shipment.out,carrier:"
+msgid "Carrier"
+msgstr "Versanddienstleister"
+
+msgctxt "field:stock.shipment.out,cost:"
+msgid "Cost"
+msgstr "Kosten"
+
+msgctxt "field:stock.shipment.out,cost_edit:"
+msgid "Edit Cost"
+msgstr "Kosten Bearbeiten"
+
+msgctxt "field:stock.shipment.out,cost_invoice_line:"
+msgid "Cost Invoice Line"
+msgstr "Rechnungsposition Kosten"
+
+msgctxt "field:stock.shipment.out,cost_sale:"
+msgid "Cost Sale"
+msgstr "Kosten Verkauf"
+
+msgctxt "field:stock.shipment.out,cost_sale_currency:"
+msgid "Cost Sale Currency"
+msgstr "Währung Kosten Verkauf"
+
+msgctxt "field:stock.shipment.out,cost_sale_currency_used:"
+msgid "Cost Sale Currency"
+msgstr "Währung Kosten Verkauf"
+
+msgctxt "field:stock.shipment.out,cost_sale_used:"
+msgid "Cost Sale"
+msgstr "Kosten Verkauf"
+
+msgctxt "field:stock.shipment.out,cost_used:"
+msgid "Cost"
+msgstr "Kosten"
+
+msgctxt "help:stock.shipment.out,cost_edit:"
+msgid "Check to edit the cost."
+msgstr "Aktivieren um die Kosten zu bearbeiten."
+
+msgctxt "model:ir.message,text:msg_sale_invalid_carrier"
+msgid "To confirm sale \"%(sale)s\" you must change the carrier \"%(carrier)s\"."
+msgstr ""
+"Damit der Verkauf \"%(sale)s\" bestätigt werden kann, muss der "
+"Versanddienstleister \"%(carrier)s\" geändert werden."
+
+msgctxt ""
+"model:ir.message,text:msg_shipment_cost_invoice_missing_account_revenue"
+msgid ""
+"To invoice shipment cost of \"%(shipment)s\", you must define an account "
+"revenue for product \"%(product)s\"."
+msgstr ""
+"Damit die Versandkosten von \"%(shipment)s\" abgerechnet werden können, muss"
+" zuerst einer Ertragskonto für Artikel \"%(product)s\" konfiguriert werden."
+
+msgctxt "selection:sale.sale,shipment_cost_method:"
+msgid "None"
+msgstr "Keine"
+
+msgctxt "selection:sale.sale,shipment_cost_method:"
+msgid "On Order"
+msgstr "Pro Auftrag"
+
+msgctxt "selection:sale.sale,shipment_cost_method:"
+msgid "On Shipment"
+msgstr "Pro Lieferposten"
+
+msgctxt "view:sale.promotion:"
+msgid "Shipment Cost Included"
+msgstr "Lieferkosten Inklusive"
diff --git a/modules/sale_shipment_cost/locale/es.po b/modules/sale_shipment_cost/locale/es.po
new file mode 100644
index 0000000000..beba2d0601
--- /dev/null
+++ b/modules/sale_shipment_cost/locale/es.po
@@ -0,0 +1,102 @@
+#
+msgid ""
+msgstr "Content-Type: text/plain; charset=utf-8\n"
+
+msgctxt "field:sale.configuration,sale_shipment_cost_method:"
+msgid "Sale Shipment Cost Method"
+msgstr "Método de coste envío"
+
+msgctxt "field:sale.configuration.sale_method,sale_shipment_cost_method:"
+msgid "Sale Shipment Cost Method"
+msgstr "Método de coste envío"
+
+msgctxt "field:sale.line,shipment_cost:"
+msgid "Shipment Cost"
+msgstr "Coste de envío"
+
+msgctxt "field:sale.promotion,amount_shipment_cost_included:"
+msgid "Amount with Shipment Cost Included"
+msgstr "Importe con costes de envío incluidos"
+
+msgctxt "field:sale.sale,available_carriers:"
+msgid "Available Carriers"
+msgstr "Transportistas disponibles"
+
+msgctxt "field:sale.sale,carrier:"
+msgid "Carrier"
+msgstr "Transportista"
+
+msgctxt "field:sale.sale,shipment_cost_method:"
+msgid "Shipment Cost Method"
+msgstr "Método de coste envío"
+
+msgctxt "field:stock.shipment.out,carrier:"
+msgid "Carrier"
+msgstr "Transportista"
+
+msgctxt "field:stock.shipment.out,cost:"
+msgid "Cost"
+msgstr "Coste"
+
+msgctxt "field:stock.shipment.out,cost_edit:"
+msgid "Edit Cost"
+msgstr "Editar coste"
+
+msgctxt "field:stock.shipment.out,cost_invoice_line:"
+msgid "Cost Invoice Line"
+msgstr "Coste de la línea de factura"
+
+msgctxt "field:stock.shipment.out,cost_sale:"
+msgid "Cost Sale"
+msgstr "Coste de la venta"
+
+msgctxt "field:stock.shipment.out,cost_sale_currency:"
+msgid "Cost Sale Currency"
+msgstr "Moneda del coste de la venta"
+
+msgctxt "field:stock.shipment.out,cost_sale_currency_used:"
+msgid "Cost Sale Currency"
+msgstr "Moneda del coste de la venta"
+
+msgctxt "field:stock.shipment.out,cost_sale_used:"
+msgid "Cost Sale"
+msgstr "Coste de la venta"
+
+msgctxt "field:stock.shipment.out,cost_used:"
+msgid "Cost"
+msgstr "Coste"
+
+msgctxt "help:stock.shipment.out,cost_edit:"
+msgid "Check to edit the cost."
+msgstr "Marcar para editar el coste."
+
+msgctxt "model:ir.message,text:msg_sale_invalid_carrier"
+msgid "To confirm sale \"%(sale)s\" you must change the carrier \"%(carrier)s\"."
+msgstr ""
+"Para confirmar la venta \"%(sale)s\" debe cambiar el transportista "
+"\"%(carrier)s\"."
+
+msgctxt ""
+"model:ir.message,text:msg_shipment_cost_invoice_missing_account_revenue"
+msgid ""
+"To invoice shipment cost of \"%(shipment)s\", you must define an account "
+"revenue for product \"%(product)s\"."
+msgstr ""
+"Para facturar el coste de envío del albarán %(shipment)s\", debe definir una"
+" cuenta de ingresos para el producto \"%(product)s\"."
+
+msgctxt "selection:sale.sale,shipment_cost_method:"
+msgid "None"
+msgstr "Ninguno"
+
+msgctxt "selection:sale.sale,shipment_cost_method:"
+msgid "On Order"
+msgstr "En el pedido"
+
+msgctxt "selection:sale.sale,shipment_cost_method:"
+msgid "On Shipment"
+msgstr "En el albarán"
+
+msgctxt "view:sale.promotion:"
+msgid "Shipment Cost Included"
+msgstr "Costes de envío incluidos"
diff --git a/modules/sale_shipment_cost/locale/es_419.po b/modules/sale_shipment_cost/locale/es_419.po
new file mode 100644
index 0000000000..5f50446154
--- /dev/null
+++ b/modules/sale_shipment_cost/locale/es_419.po
@@ -0,0 +1,105 @@
+#
+msgid ""
+msgstr "Content-Type: text/plain; charset=utf-8\n"
+
+msgctxt "field:sale.configuration,sale_shipment_cost_method:"
+msgid "Sale Shipment Cost Method"
+msgstr "Método de costo de envío de venta"
+
+msgctxt "field:sale.configuration.sale_method,sale_shipment_cost_method:"
+msgid "Sale Shipment Cost Method"
+msgstr "Método de costo de envío de venta"
+
+msgctxt "field:sale.line,shipment_cost:"
+msgid "Shipment Cost"
+msgstr "Costo de envío"
+
+msgctxt "field:sale.promotion,amount_shipment_cost_included:"
+msgid "Amount with Shipment Cost Included"
+msgstr ""
+
+msgctxt "field:sale.sale,available_carriers:"
+msgid "Available Carriers"
+msgstr ""
+
+msgctxt "field:sale.sale,carrier:"
+msgid "Carrier"
+msgstr ""
+
+msgctxt "field:sale.sale,shipment_cost_method:"
+msgid "Shipment Cost Method"
+msgstr "Método de costo de envío"
+
+msgctxt "field:stock.shipment.out,carrier:"
+msgid "Carrier"
+msgstr ""
+
+msgctxt "field:stock.shipment.out,cost:"
+msgid "Cost"
+msgstr "Costo"
+
+#, fuzzy
+msgctxt "field:stock.shipment.out,cost_edit:"
+msgid "Edit Cost"
+msgstr "Costo de envío"
+
+msgctxt "field:stock.shipment.out,cost_invoice_line:"
+msgid "Cost Invoice Line"
+msgstr "Línea de factura de costo"
+
+#, fuzzy
+msgctxt "field:stock.shipment.out,cost_sale:"
+msgid "Cost Sale"
+msgstr "Costo"
+
+#, fuzzy
+msgctxt "field:stock.shipment.out,cost_sale_currency:"
+msgid "Cost Sale Currency"
+msgstr "Moneda del costo"
+
+#, fuzzy
+msgctxt "field:stock.shipment.out,cost_sale_currency_used:"
+msgid "Cost Sale Currency"
+msgstr "Moneda del costo"
+
+#, fuzzy
+msgctxt "field:stock.shipment.out,cost_sale_used:"
+msgid "Cost Sale"
+msgstr "Costo"
+
+#, fuzzy
+msgctxt "field:stock.shipment.out,cost_used:"
+msgid "Cost"
+msgstr "Costo"
+
+msgctxt "help:stock.shipment.out,cost_edit:"
+msgid "Check to edit the cost."
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_sale_invalid_carrier"
+msgid "To confirm sale \"%(sale)s\" you must change the carrier \"%(carrier)s\"."
+msgstr ""
+
+msgctxt ""
+"model:ir.message,text:msg_shipment_cost_invoice_missing_account_revenue"
+msgid ""
+"To invoice shipment cost of \"%(shipment)s\", you must define an account "
+"revenue for product \"%(product)s\"."
+msgstr ""
+
+msgctxt "selection:sale.sale,shipment_cost_method:"
+msgid "None"
+msgstr ""
+
+msgctxt "selection:sale.sale,shipment_cost_method:"
+msgid "On Order"
+msgstr ""
+
+msgctxt "selection:sale.sale,shipment_cost_method:"
+msgid "On Shipment"
+msgstr "En el envío"
+
+#, fuzzy
+msgctxt "view:sale.promotion:"
+msgid "Shipment Cost Included"
+msgstr "Método de costo de envío"
diff --git a/modules/sale_shipment_cost/locale/et.po b/modules/sale_shipment_cost/locale/et.po
new file mode 100644
index 0000000000..9f72676213
--- /dev/null
+++ b/modules/sale_shipment_cost/locale/et.po
@@ -0,0 +1,107 @@
+#
+msgid ""
+msgstr "Content-Type: text/plain; charset=utf-8\n"
+
+msgctxt "field:sale.configuration,sale_shipment_cost_method:"
+msgid "Sale Shipment Cost Method"
+msgstr "Saadetise kulu meetod"
+
+msgctxt "field:sale.configuration.sale_method,sale_shipment_cost_method:"
+msgid "Sale Shipment Cost Method"
+msgstr "Saadetise kulu meetod"
+
+msgctxt "field:sale.line,shipment_cost:"
+msgid "Shipment Cost"
+msgstr "Saadetise kulu"
+
+msgctxt "field:sale.promotion,amount_shipment_cost_included:"
+msgid "Amount with Shipment Cost Included"
+msgstr ""
+
+msgctxt "field:sale.sale,available_carriers:"
+msgid "Available Carriers"
+msgstr "Saadaolevad vedajad"
+
+msgctxt "field:sale.sale,carrier:"
+msgid "Carrier"
+msgstr "Vedaja"
+
+msgctxt "field:sale.sale,shipment_cost_method:"
+msgid "Shipment Cost Method"
+msgstr "Saadetise kulu meetod"
+
+msgctxt "field:stock.shipment.out,carrier:"
+msgid "Carrier"
+msgstr "Vedaja"
+
+msgctxt "field:stock.shipment.out,cost:"
+msgid "Cost"
+msgstr "Kulu"
+
+#, fuzzy
+msgctxt "field:stock.shipment.out,cost_edit:"
+msgid "Edit Cost"
+msgstr "Saadetise kulu"
+
+msgctxt "field:stock.shipment.out,cost_invoice_line:"
+msgid "Cost Invoice Line"
+msgstr "Kuluarve rida"
+
+#, fuzzy
+msgctxt "field:stock.shipment.out,cost_sale:"
+msgid "Cost Sale"
+msgstr "Kulu"
+
+#, fuzzy
+msgctxt "field:stock.shipment.out,cost_sale_currency:"
+msgid "Cost Sale Currency"
+msgstr "Kulu valuuta"
+
+#, fuzzy
+msgctxt "field:stock.shipment.out,cost_sale_currency_used:"
+msgid "Cost Sale Currency"
+msgstr "Kulu valuuta"
+
+#, fuzzy
+msgctxt "field:stock.shipment.out,cost_sale_used:"
+msgid "Cost Sale"
+msgstr "Kulu"
+
+#, fuzzy
+msgctxt "field:stock.shipment.out,cost_used:"
+msgid "Cost"
+msgstr "Kulu"
+
+msgctxt "help:stock.shipment.out,cost_edit:"
+msgid "Check to edit the cost."
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_sale_invalid_carrier"
+msgid "To confirm sale \"%(sale)s\" you must change the carrier \"%(carrier)s\"."
+msgstr "Müügi \"%(sale)s\" kinnitamiseks tuleb muuta vedaja \"%(carrier)s\"."
+
+msgctxt ""
+"model:ir.message,text:msg_shipment_cost_invoice_missing_account_revenue"
+msgid ""
+"To invoice shipment cost of \"%(shipment)s\", you must define an account "
+"revenue for product \"%(product)s\"."
+msgstr ""
+"Lähetuse \"%(shipment)s\" kulu arveldamiseks tuleb määrata toote "
+"\"%(product)s\" tulukonto."
+
+msgctxt "selection:sale.sale,shipment_cost_method:"
+msgid "None"
+msgstr ""
+
+msgctxt "selection:sale.sale,shipment_cost_method:"
+msgid "On Order"
+msgstr "Tellimusel"
+
+msgctxt "selection:sale.sale,shipment_cost_method:"
+msgid "On Shipment"
+msgstr "Lähetusel"
+
+#, fuzzy
+msgctxt "view:sale.promotion:"
+msgid "Shipment Cost Included"
+msgstr "Saadetise kulu meetod"
diff --git a/modules/sale_shipment_cost/locale/fa.po b/modules/sale_shipment_cost/locale/fa.po
new file mode 100644
index 0000000000..a47d5ca23f
--- /dev/null
+++ b/modules/sale_shipment_cost/locale/fa.po
@@ -0,0 +1,109 @@
+#
+msgid ""
+msgstr "Content-Type: text/plain; charset=utf-8\n"
+
+msgctxt "field:sale.configuration,sale_shipment_cost_method:"
+msgid "Sale Shipment Cost Method"
+msgstr "متد هزینه حمل ونقل فروش"
+
+msgctxt "field:sale.configuration.sale_method,sale_shipment_cost_method:"
+msgid "Sale Shipment Cost Method"
+msgstr "متد هزینه حمل ونقل فروش"
+
+msgctxt "field:sale.line,shipment_cost:"
+msgid "Shipment Cost"
+msgstr "هزینه حمل ونقل"
+
+msgctxt "field:sale.promotion,amount_shipment_cost_included:"
+msgid "Amount with Shipment Cost Included"
+msgstr ""
+
+msgctxt "field:sale.sale,available_carriers:"
+msgid "Available Carriers"
+msgstr "حمل کننده های در دسترس"
+
+msgctxt "field:sale.sale,carrier:"
+msgid "Carrier"
+msgstr "حمل کننده"
+
+msgctxt "field:sale.sale,shipment_cost_method:"
+msgid "Shipment Cost Method"
+msgstr "متد هزینه حمل و نقل"
+
+msgctxt "field:stock.shipment.out,carrier:"
+msgid "Carrier"
+msgstr "حمل کننده"
+
+msgctxt "field:stock.shipment.out,cost:"
+msgid "Cost"
+msgstr "هزینه"
+
+#, fuzzy
+msgctxt "field:stock.shipment.out,cost_edit:"
+msgid "Edit Cost"
+msgstr "هزینه حمل ونقل"
+
+msgctxt "field:stock.shipment.out,cost_invoice_line:"
+msgid "Cost Invoice Line"
+msgstr "سطر هزینه صورتحساب"
+
+#, fuzzy
+msgctxt "field:stock.shipment.out,cost_sale:"
+msgid "Cost Sale"
+msgstr "هزینه"
+
+#, fuzzy
+msgctxt "field:stock.shipment.out,cost_sale_currency:"
+msgid "Cost Sale Currency"
+msgstr "واحد پول هزینه"
+
+#, fuzzy
+msgctxt "field:stock.shipment.out,cost_sale_currency_used:"
+msgid "Cost Sale Currency"
+msgstr "واحد پول هزینه"
+
+#, fuzzy
+msgctxt "field:stock.shipment.out,cost_sale_used:"
+msgid "Cost Sale"
+msgstr "هزینه"
+
+#, fuzzy
+msgctxt "field:stock.shipment.out,cost_used:"
+msgid "Cost"
+msgstr "هزینه"
+
+msgctxt "help:stock.shipment.out,cost_edit:"
+msgid "Check to edit the cost."
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_sale_invalid_carrier"
+msgid "To confirm sale \"%(sale)s\" you must change the carrier \"%(carrier)s\"."
+msgstr ""
+"برای تأیید فروش :\"%(sale)s\" شما باید حمل کننده :\"%(carrier)s\" را تغییر "
+"دهید."
+
+msgctxt ""
+"model:ir.message,text:msg_shipment_cost_invoice_missing_account_revenue"
+msgid ""
+"To invoice shipment cost of \"%(shipment)s\", you must define an account "
+"revenue for product \"%(product)s\"."
+msgstr ""
+"برای صورتحساب هزینه حمل و نقل :\"%(shipment)s\"شما باید یک حساب درآمد برای "
+"محصول :\"%(product)s\" تعریف کنید."
+
+msgctxt "selection:sale.sale,shipment_cost_method:"
+msgid "None"
+msgstr ""
+
+msgctxt "selection:sale.sale,shipment_cost_method:"
+msgid "On Order"
+msgstr "در دستور"
+
+msgctxt "selection:sale.sale,shipment_cost_method:"
+msgid "On Shipment"
+msgstr "در حمل ونقل"
+
+#, fuzzy
+msgctxt "view:sale.promotion:"
+msgid "Shipment Cost Included"
+msgstr "متد هزینه حمل و نقل"
diff --git a/modules/sale_shipment_cost/locale/fi.po b/modules/sale_shipment_cost/locale/fi.po
new file mode 100644
index 0000000000..b95356e164
--- /dev/null
+++ b/modules/sale_shipment_cost/locale/fi.po
@@ -0,0 +1,98 @@
+#
+msgid ""
+msgstr "Content-Type: text/plain; charset=utf-8\n"
+
+msgctxt "field:sale.configuration,sale_shipment_cost_method:"
+msgid "Sale Shipment Cost Method"
+msgstr ""
+
+msgctxt "field:sale.configuration.sale_method,sale_shipment_cost_method:"
+msgid "Sale Shipment Cost Method"
+msgstr ""
+
+msgctxt "field:sale.line,shipment_cost:"
+msgid "Shipment Cost"
+msgstr ""
+
+msgctxt "field:sale.promotion,amount_shipment_cost_included:"
+msgid "Amount with Shipment Cost Included"
+msgstr ""
+
+msgctxt "field:sale.sale,available_carriers:"
+msgid "Available Carriers"
+msgstr ""
+
+msgctxt "field:sale.sale,carrier:"
+msgid "Carrier"
+msgstr ""
+
+msgctxt "field:sale.sale,shipment_cost_method:"
+msgid "Shipment Cost Method"
+msgstr ""
+
+msgctxt "field:stock.shipment.out,carrier:"
+msgid "Carrier"
+msgstr ""
+
+msgctxt "field:stock.shipment.out,cost:"
+msgid "Cost"
+msgstr ""
+
+msgctxt "field:stock.shipment.out,cost_edit:"
+msgid "Edit Cost"
+msgstr ""
+
+msgctxt "field:stock.shipment.out,cost_invoice_line:"
+msgid "Cost Invoice Line"
+msgstr ""
+
+msgctxt "field:stock.shipment.out,cost_sale:"
+msgid "Cost Sale"
+msgstr ""
+
+msgctxt "field:stock.shipment.out,cost_sale_currency:"
+msgid "Cost Sale Currency"
+msgstr ""
+
+msgctxt "field:stock.shipment.out,cost_sale_currency_used:"
+msgid "Cost Sale Currency"
+msgstr ""
+
+msgctxt "field:stock.shipment.out,cost_sale_used:"
+msgid "Cost Sale"
+msgstr ""
+
+msgctxt "field:stock.shipment.out,cost_used:"
+msgid "Cost"
+msgstr ""
+
+msgctxt "help:stock.shipment.out,cost_edit:"
+msgid "Check to edit the cost."
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_sale_invalid_carrier"
+msgid "To confirm sale \"%(sale)s\" you must change the carrier \"%(carrier)s\"."
+msgstr ""
+
+msgctxt ""
+"model:ir.message,text:msg_shipment_cost_invoice_missing_account_revenue"
+msgid ""
+"To invoice shipment cost of \"%(shipment)s\", you must define an account "
+"revenue for product \"%(product)s\"."
+msgstr ""
+
+msgctxt "selection:sale.sale,shipment_cost_method:"
+msgid "None"
+msgstr ""
+
+msgctxt "selection:sale.sale,shipment_cost_method:"
+msgid "On Order"
+msgstr ""
+
+msgctxt "selection:sale.sale,shipment_cost_method:"
+msgid "On Shipment"
+msgstr ""
+
+msgctxt "view:sale.promotion:"
+msgid "Shipment Cost Included"
+msgstr ""
diff --git a/modules/sale_shipment_cost/locale/fr.po b/modules/sale_shipment_cost/locale/fr.po
new file mode 100644
index 0000000000..65a13610b3
--- /dev/null
+++ b/modules/sale_shipment_cost/locale/fr.po
@@ -0,0 +1,102 @@
+#
+msgid ""
+msgstr "Content-Type: text/plain; charset=utf-8\n"
+
+msgctxt "field:sale.configuration,sale_shipment_cost_method:"
+msgid "Sale Shipment Cost Method"
+msgstr "Méthode de coût de l'expédition de vente"
+
+msgctxt "field:sale.configuration.sale_method,sale_shipment_cost_method:"
+msgid "Sale Shipment Cost Method"
+msgstr "Méthode de coût de l'expédition de vente"
+
+msgctxt "field:sale.line,shipment_cost:"
+msgid "Shipment Cost"
+msgstr "Coût d'expédition"
+
+msgctxt "field:sale.promotion,amount_shipment_cost_included:"
+msgid "Amount with Shipment Cost Included"
+msgstr "Montant avec coût d'expédition inclus"
+
+msgctxt "field:sale.sale,available_carriers:"
+msgid "Available Carriers"
+msgstr "Transporteurs disponibles"
+
+msgctxt "field:sale.sale,carrier:"
+msgid "Carrier"
+msgstr "Transporteur"
+
+msgctxt "field:sale.sale,shipment_cost_method:"
+msgid "Shipment Cost Method"
+msgstr "Méthode de coût d'expédition"
+
+msgctxt "field:stock.shipment.out,carrier:"
+msgid "Carrier"
+msgstr "Transporteur"
+
+msgctxt "field:stock.shipment.out,cost:"
+msgid "Cost"
+msgstr "Coût"
+
+msgctxt "field:stock.shipment.out,cost_edit:"
+msgid "Edit Cost"
+msgstr "Modifier le coût"
+
+msgctxt "field:stock.shipment.out,cost_invoice_line:"
+msgid "Cost Invoice Line"
+msgstr "Ligne de facture du coût"
+
+msgctxt "field:stock.shipment.out,cost_sale:"
+msgid "Cost Sale"
+msgstr "Coût de la vente"
+
+msgctxt "field:stock.shipment.out,cost_sale_currency:"
+msgid "Cost Sale Currency"
+msgstr "Devise du coût de la vente"
+
+msgctxt "field:stock.shipment.out,cost_sale_currency_used:"
+msgid "Cost Sale Currency"
+msgstr "Devise du coût de la vente"
+
+msgctxt "field:stock.shipment.out,cost_sale_used:"
+msgid "Cost Sale"
+msgstr "Coût de la vente"
+
+msgctxt "field:stock.shipment.out,cost_used:"
+msgid "Cost"
+msgstr "Coût"
+
+msgctxt "help:stock.shipment.out,cost_edit:"
+msgid "Check to edit the cost."
+msgstr "Cochez pour modifier le coût."
+
+msgctxt "model:ir.message,text:msg_sale_invalid_carrier"
+msgid "To confirm sale \"%(sale)s\" you must change the carrier \"%(carrier)s\"."
+msgstr ""
+"Pour confirmer la vente « %(sale)s », vous devez changer le transporteur "
+"« %(carrier)s »."
+
+msgctxt ""
+"model:ir.message,text:msg_shipment_cost_invoice_missing_account_revenue"
+msgid ""
+"To invoice shipment cost of \"%(shipment)s\", you must define an account "
+"revenue for product \"%(product)s\"."
+msgstr ""
+"Pour facturer le coût de l'expédition « %(shipment)s », vous devez définir "
+"un compte de produits pour le produit « %(product)s »."
+
+msgctxt "selection:sale.sale,shipment_cost_method:"
+msgid "None"
+msgstr "Aucune"
+
+msgctxt "selection:sale.sale,shipment_cost_method:"
+msgid "On Order"
+msgstr "À la commande"
+
+msgctxt "selection:sale.sale,shipment_cost_method:"
+msgid "On Shipment"
+msgstr "À l'expédition"
+
+msgctxt "view:sale.promotion:"
+msgid "Shipment Cost Included"
+msgstr "Coût d'expédition inclus"
diff --git a/modules/sale_shipment_cost/locale/hu.po b/modules/sale_shipment_cost/locale/hu.po
new file mode 100644
index 0000000000..916f38ec0e
--- /dev/null
+++ b/modules/sale_shipment_cost/locale/hu.po
@@ -0,0 +1,103 @@
+#
+msgid ""
+msgstr "Content-Type: text/plain; charset=utf-8\n"
+
+msgctxt "field:sale.configuration,sale_shipment_cost_method:"
+msgid "Sale Shipment Cost Method"
+msgstr "Szállítási díj kiszámlázása"
+
+msgctxt "field:sale.configuration.sale_method,sale_shipment_cost_method:"
+msgid "Sale Shipment Cost Method"
+msgstr "Szállítási díj kiszámlázása"
+
+msgctxt "field:sale.line,shipment_cost:"
+msgid "Shipment Cost"
+msgstr ""
+
+msgctxt "field:sale.promotion,amount_shipment_cost_included:"
+msgid "Amount with Shipment Cost Included"
+msgstr ""
+
+msgctxt "field:sale.sale,available_carriers:"
+msgid "Available Carriers"
+msgstr ""
+
+msgctxt "field:sale.sale,carrier:"
+msgid "Carrier"
+msgstr "Fuvarozó"
+
+msgctxt "field:sale.sale,shipment_cost_method:"
+msgid "Shipment Cost Method"
+msgstr ""
+
+msgctxt "field:stock.shipment.out,carrier:"
+msgid "Carrier"
+msgstr "Fuvarozó"
+
+msgctxt "field:stock.shipment.out,cost:"
+msgid "Cost"
+msgstr "Költség"
+
+#, fuzzy
+msgctxt "field:stock.shipment.out,cost_edit:"
+msgid "Edit Cost"
+msgstr "Költség"
+
+msgctxt "field:stock.shipment.out,cost_invoice_line:"
+msgid "Cost Invoice Line"
+msgstr ""
+
+#, fuzzy
+msgctxt "field:stock.shipment.out,cost_sale:"
+msgid "Cost Sale"
+msgstr "Költség"
+
+msgctxt "field:stock.shipment.out,cost_sale_currency:"
+msgid "Cost Sale Currency"
+msgstr ""
+
+#, fuzzy
+msgctxt "field:stock.shipment.out,cost_sale_currency_used:"
+msgid "Cost Sale Currency"
+msgstr "Költség"
+
+msgctxt "field:stock.shipment.out,cost_sale_used:"
+msgid "Cost Sale"
+msgstr "Számlázandó díj"
+
+msgctxt "field:stock.shipment.out,cost_used:"
+msgid "Cost"
+msgstr "Költség"
+
+msgctxt "help:stock.shipment.out,cost_edit:"
+msgid "Check to edit the cost."
+msgstr ""
+"Jelölje be, ha módosítani szeretné a szállítási költséget és a "
+"továbbszámlázandó díjat."
+
+msgctxt "model:ir.message,text:msg_sale_invalid_carrier"
+msgid "To confirm sale \"%(sale)s\" you must change the carrier \"%(carrier)s\"."
+msgstr ""
+
+msgctxt ""
+"model:ir.message,text:msg_shipment_cost_invoice_missing_account_revenue"
+msgid ""
+"To invoice shipment cost of \"%(shipment)s\", you must define an account "
+"revenue for product \"%(product)s\"."
+msgstr ""
+
+msgctxt "selection:sale.sale,shipment_cost_method:"
+msgid "None"
+msgstr "nem lesz továbbszámlázva"
+
+msgctxt "selection:sale.sale,shipment_cost_method:"
+msgid "On Order"
+msgstr "rendelésenként"
+
+msgctxt "selection:sale.sale,shipment_cost_method:"
+msgid "On Shipment"
+msgstr "szállítmányonként"
+
+msgctxt "view:sale.promotion:"
+msgid "Shipment Cost Included"
+msgstr ""
diff --git a/modules/sale_shipment_cost/locale/id.po b/modules/sale_shipment_cost/locale/id.po
new file mode 100644
index 0000000000..b95356e164
--- /dev/null
+++ b/modules/sale_shipment_cost/locale/id.po
@@ -0,0 +1,98 @@
+#
+msgid ""
+msgstr "Content-Type: text/plain; charset=utf-8\n"
+
+msgctxt "field:sale.configuration,sale_shipment_cost_method:"
+msgid "Sale Shipment Cost Method"
+msgstr ""
+
+msgctxt "field:sale.configuration.sale_method,sale_shipment_cost_method:"
+msgid "Sale Shipment Cost Method"
+msgstr ""
+
+msgctxt "field:sale.line,shipment_cost:"
+msgid "Shipment Cost"
+msgstr ""
+
+msgctxt "field:sale.promotion,amount_shipment_cost_included:"
+msgid "Amount with Shipment Cost Included"
+msgstr ""
+
+msgctxt "field:sale.sale,available_carriers:"
+msgid "Available Carriers"
+msgstr ""
+
+msgctxt "field:sale.sale,carrier:"
+msgid "Carrier"
+msgstr ""
+
+msgctxt "field:sale.sale,shipment_cost_method:"
+msgid "Shipment Cost Method"
+msgstr ""
+
+msgctxt "field:stock.shipment.out,carrier:"
+msgid "Carrier"
+msgstr ""
+
+msgctxt "field:stock.shipment.out,cost:"
+msgid "Cost"
+msgstr ""
+
+msgctxt "field:stock.shipment.out,cost_edit:"
+msgid "Edit Cost"
+msgstr ""
+
+msgctxt "field:stock.shipment.out,cost_invoice_line:"
+msgid "Cost Invoice Line"
+msgstr ""
+
+msgctxt "field:stock.shipment.out,cost_sale:"
+msgid "Cost Sale"
+msgstr ""
+
+msgctxt "field:stock.shipment.out,cost_sale_currency:"
+msgid "Cost Sale Currency"
+msgstr ""
+
+msgctxt "field:stock.shipment.out,cost_sale_currency_used:"
+msgid "Cost Sale Currency"
+msgstr ""
+
+msgctxt "field:stock.shipment.out,cost_sale_used:"
+msgid "Cost Sale"
+msgstr ""
+
+msgctxt "field:stock.shipment.out,cost_used:"
+msgid "Cost"
+msgstr ""
+
+msgctxt "help:stock.shipment.out,cost_edit:"
+msgid "Check to edit the cost."
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_sale_invalid_carrier"
+msgid "To confirm sale \"%(sale)s\" you must change the carrier \"%(carrier)s\"."
+msgstr ""
+
+msgctxt ""
+"model:ir.message,text:msg_shipment_cost_invoice_missing_account_revenue"
+msgid ""
+"To invoice shipment cost of \"%(shipment)s\", you must define an account "
+"revenue for product \"%(product)s\"."
+msgstr ""
+
+msgctxt "selection:sale.sale,shipment_cost_method:"
+msgid "None"
+msgstr ""
+
+msgctxt "selection:sale.sale,shipment_cost_method:"
+msgid "On Order"
+msgstr ""
+
+msgctxt "selection:sale.sale,shipment_cost_method:"
+msgid "On Shipment"
+msgstr ""
+
+msgctxt "view:sale.promotion:"
+msgid "Shipment Cost Included"
+msgstr ""
diff --git a/modules/sale_shipment_cost/locale/it.po b/modules/sale_shipment_cost/locale/it.po
new file mode 100644
index 0000000000..8d9c52ac13
--- /dev/null
+++ b/modules/sale_shipment_cost/locale/it.po
@@ -0,0 +1,106 @@
+#
+msgid ""
+msgstr "Content-Type: text/plain; charset=utf-8\n"
+
+msgctxt "field:sale.configuration,sale_shipment_cost_method:"
+msgid "Sale Shipment Cost Method"
+msgstr "Metodo costo di spedizione per vendita"
+
+#, fuzzy
+msgctxt "field:sale.configuration.sale_method,sale_shipment_cost_method:"
+msgid "Sale Shipment Cost Method"
+msgstr "Metodo costo di spedizione per vendita"
+
+msgctxt "field:sale.line,shipment_cost:"
+msgid "Shipment Cost"
+msgstr "costo di spedizione"
+
+msgctxt "field:sale.promotion,amount_shipment_cost_included:"
+msgid "Amount with Shipment Cost Included"
+msgstr ""
+
+msgctxt "field:sale.sale,available_carriers:"
+msgid "Available Carriers"
+msgstr "Vettori disponibili"
+
+msgctxt "field:sale.sale,carrier:"
+msgid "Carrier"
+msgstr "Vettore"
+
+msgctxt "field:sale.sale,shipment_cost_method:"
+msgid "Shipment Cost Method"
+msgstr "Metodo di costo per spedizione"
+
+msgctxt "field:stock.shipment.out,carrier:"
+msgid "Carrier"
+msgstr "Vettore"
+
+msgctxt "field:stock.shipment.out,cost:"
+msgid "Cost"
+msgstr "Costo"
+
+#, fuzzy
+msgctxt "field:stock.shipment.out,cost_edit:"
+msgid "Edit Cost"
+msgstr "costo di spedizione"
+
+msgctxt "field:stock.shipment.out,cost_invoice_line:"
+msgid "Cost Invoice Line"
+msgstr "Riga fattura costo"
+
+#, fuzzy
+msgctxt "field:stock.shipment.out,cost_sale:"
+msgid "Cost Sale"
+msgstr "Costo"
+
+#, fuzzy
+msgctxt "field:stock.shipment.out,cost_sale_currency:"
+msgid "Cost Sale Currency"
+msgstr "Valuta costo"
+
+#, fuzzy
+msgctxt "field:stock.shipment.out,cost_sale_currency_used:"
+msgid "Cost Sale Currency"
+msgstr "Valuta costo"
+
+#, fuzzy
+msgctxt "field:stock.shipment.out,cost_sale_used:"
+msgid "Cost Sale"
+msgstr "Costo"
+
+#, fuzzy
+msgctxt "field:stock.shipment.out,cost_used:"
+msgid "Cost"
+msgstr "Costo"
+
+msgctxt "help:stock.shipment.out,cost_edit:"
+msgid "Check to edit the cost."
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_sale_invalid_carrier"
+msgid "To confirm sale \"%(sale)s\" you must change the carrier \"%(carrier)s\"."
+msgstr ""
+
+msgctxt ""
+"model:ir.message,text:msg_shipment_cost_invoice_missing_account_revenue"
+msgid ""
+"To invoice shipment cost of \"%(shipment)s\", you must define an account "
+"revenue for product \"%(product)s\"."
+msgstr ""
+
+msgctxt "selection:sale.sale,shipment_cost_method:"
+msgid "None"
+msgstr ""
+
+msgctxt "selection:sale.sale,shipment_cost_method:"
+msgid "On Order"
+msgstr "su Ordine"
+
+msgctxt "selection:sale.sale,shipment_cost_method:"
+msgid "On Shipment"
+msgstr "su Spedizione"
+
+#, fuzzy
+msgctxt "view:sale.promotion:"
+msgid "Shipment Cost Included"
+msgstr "Metodo di costo per spedizione"
diff --git a/modules/sale_shipment_cost/locale/lo.po b/modules/sale_shipment_cost/locale/lo.po
new file mode 100644
index 0000000000..b95356e164
--- /dev/null
+++ b/modules/sale_shipment_cost/locale/lo.po
@@ -0,0 +1,98 @@
+#
+msgid ""
+msgstr "Content-Type: text/plain; charset=utf-8\n"
+
+msgctxt "field:sale.configuration,sale_shipment_cost_method:"
+msgid "Sale Shipment Cost Method"
+msgstr ""
+
+msgctxt "field:sale.configuration.sale_method,sale_shipment_cost_method:"
+msgid "Sale Shipment Cost Method"
+msgstr ""
+
+msgctxt "field:sale.line,shipment_cost:"
+msgid "Shipment Cost"
+msgstr ""
+
+msgctxt "field:sale.promotion,amount_shipment_cost_included:"
+msgid "Amount with Shipment Cost Included"
+msgstr ""
+
+msgctxt "field:sale.sale,available_carriers:"
+msgid "Available Carriers"
+msgstr ""
+
+msgctxt "field:sale.sale,carrier:"
+msgid "Carrier"
+msgstr ""
+
+msgctxt "field:sale.sale,shipment_cost_method:"
+msgid "Shipment Cost Method"
+msgstr ""
+
+msgctxt "field:stock.shipment.out,carrier:"
+msgid "Carrier"
+msgstr ""
+
+msgctxt "field:stock.shipment.out,cost:"
+msgid "Cost"
+msgstr ""
+
+msgctxt "field:stock.shipment.out,cost_edit:"
+msgid "Edit Cost"
+msgstr ""
+
+msgctxt "field:stock.shipment.out,cost_invoice_line:"
+msgid "Cost Invoice Line"
+msgstr ""
+
+msgctxt "field:stock.shipment.out,cost_sale:"
+msgid "Cost Sale"
+msgstr ""
+
+msgctxt "field:stock.shipment.out,cost_sale_currency:"
+msgid "Cost Sale Currency"
+msgstr ""
+
+msgctxt "field:stock.shipment.out,cost_sale_currency_used:"
+msgid "Cost Sale Currency"
+msgstr ""
+
+msgctxt "field:stock.shipment.out,cost_sale_used:"
+msgid "Cost Sale"
+msgstr ""
+
+msgctxt "field:stock.shipment.out,cost_used:"
+msgid "Cost"
+msgstr ""
+
+msgctxt "help:stock.shipment.out,cost_edit:"
+msgid "Check to edit the cost."
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_sale_invalid_carrier"
+msgid "To confirm sale \"%(sale)s\" you must change the carrier \"%(carrier)s\"."
+msgstr ""
+
+msgctxt ""
+"model:ir.message,text:msg_shipment_cost_invoice_missing_account_revenue"
+msgid ""
+"To invoice shipment cost of \"%(shipment)s\", you must define an account "
+"revenue for product \"%(product)s\"."
+msgstr ""
+
+msgctxt "selection:sale.sale,shipment_cost_method:"
+msgid "None"
+msgstr ""
+
+msgctxt "selection:sale.sale,shipment_cost_method:"
+msgid "On Order"
+msgstr ""
+
+msgctxt "selection:sale.sale,shipment_cost_method:"
+msgid "On Shipment"
+msgstr ""
+
+msgctxt "view:sale.promotion:"
+msgid "Shipment Cost Included"
+msgstr ""
diff --git a/modules/sale_shipment_cost/locale/lt.po b/modules/sale_shipment_cost/locale/lt.po
new file mode 100644
index 0000000000..2dec6d3be8
--- /dev/null
+++ b/modules/sale_shipment_cost/locale/lt.po
@@ -0,0 +1,101 @@
+#
+msgid ""
+msgstr "Content-Type: text/plain; charset=utf-8\n"
+
+msgctxt "field:sale.configuration,sale_shipment_cost_method:"
+msgid "Sale Shipment Cost Method"
+msgstr ""
+
+msgctxt "field:sale.configuration.sale_method,sale_shipment_cost_method:"
+msgid "Sale Shipment Cost Method"
+msgstr ""
+
+msgctxt "field:sale.line,shipment_cost:"
+msgid "Shipment Cost"
+msgstr ""
+
+msgctxt "field:sale.promotion,amount_shipment_cost_included:"
+msgid "Amount with Shipment Cost Included"
+msgstr ""
+
+msgctxt "field:sale.sale,available_carriers:"
+msgid "Available Carriers"
+msgstr ""
+
+msgctxt "field:sale.sale,carrier:"
+msgid "Carrier"
+msgstr ""
+
+msgctxt "field:sale.sale,shipment_cost_method:"
+msgid "Shipment Cost Method"
+msgstr ""
+
+msgctxt "field:stock.shipment.out,carrier:"
+msgid "Carrier"
+msgstr ""
+
+msgctxt "field:stock.shipment.out,cost:"
+msgid "Cost"
+msgstr ""
+
+msgctxt "field:stock.shipment.out,cost_edit:"
+msgid "Edit Cost"
+msgstr ""
+
+msgctxt "field:stock.shipment.out,cost_invoice_line:"
+msgid "Cost Invoice Line"
+msgstr ""
+
+msgctxt "field:stock.shipment.out,cost_sale:"
+msgid "Cost Sale"
+msgstr ""
+
+#, fuzzy
+msgctxt "field:stock.shipment.out,cost_sale_currency:"
+msgid "Cost Sale Currency"
+msgstr "Savikainos valiuta"
+
+#, fuzzy
+msgctxt "field:stock.shipment.out,cost_sale_currency_used:"
+msgid "Cost Sale Currency"
+msgstr "Savikainos valiuta"
+
+#, fuzzy
+msgctxt "field:stock.shipment.out,cost_sale_used:"
+msgid "Cost Sale"
+msgstr "Savikainos valiuta"
+
+msgctxt "field:stock.shipment.out,cost_used:"
+msgid "Cost"
+msgstr ""
+
+msgctxt "help:stock.shipment.out,cost_edit:"
+msgid "Check to edit the cost."
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_sale_invalid_carrier"
+msgid "To confirm sale \"%(sale)s\" you must change the carrier \"%(carrier)s\"."
+msgstr ""
+
+msgctxt ""
+"model:ir.message,text:msg_shipment_cost_invoice_missing_account_revenue"
+msgid ""
+"To invoice shipment cost of \"%(shipment)s\", you must define an account "
+"revenue for product \"%(product)s\"."
+msgstr ""
+
+msgctxt "selection:sale.sale,shipment_cost_method:"
+msgid "None"
+msgstr ""
+
+msgctxt "selection:sale.sale,shipment_cost_method:"
+msgid "On Order"
+msgstr ""
+
+msgctxt "selection:sale.sale,shipment_cost_method:"
+msgid "On Shipment"
+msgstr ""
+
+msgctxt "view:sale.promotion:"
+msgid "Shipment Cost Included"
+msgstr ""
diff --git a/modules/sale_shipment_cost/locale/nl.po b/modules/sale_shipment_cost/locale/nl.po
new file mode 100644
index 0000000000..32e6723fa3
--- /dev/null
+++ b/modules/sale_shipment_cost/locale/nl.po
@@ -0,0 +1,108 @@
+#
+msgid ""
+msgstr "Content-Type: text/plain; charset=utf-8\n"
+
+msgctxt "field:sale.configuration,sale_shipment_cost_method:"
+msgid "Sale Shipment Cost Method"
+msgstr "Verkoop verzendkosten methode"
+
+msgctxt "field:sale.configuration.sale_method,sale_shipment_cost_method:"
+msgid "Sale Shipment Cost Method"
+msgstr "Verkoop verzendkosten methode"
+
+msgctxt "field:sale.line,shipment_cost:"
+msgid "Shipment Cost"
+msgstr "Verzendkosten"
+
+msgctxt "field:sale.promotion,amount_shipment_cost_included:"
+msgid "Amount with Shipment Cost Included"
+msgstr "Bedrag inclusief verzendingskosten"
+
+msgctxt "field:sale.sale,available_carriers:"
+msgid "Available Carriers"
+msgstr "Beschikbare vervoerders"
+
+msgctxt "field:sale.sale,carrier:"
+msgid "Carrier"
+msgstr "Transporteur"
+
+msgctxt "field:sale.sale,shipment_cost_method:"
+msgid "Shipment Cost Method"
+msgstr "verzendingskost methode"
+
+msgctxt "field:stock.shipment.out,carrier:"
+msgid "Carrier"
+msgstr "Transporteur"
+
+msgctxt "field:stock.shipment.out,cost:"
+msgid "Cost"
+msgstr "Kosten"
+
+#, fuzzy
+msgctxt "field:stock.shipment.out,cost_edit:"
+msgid "Edit Cost"
+msgstr "Verzendkosten"
+
+msgctxt "field:stock.shipment.out,cost_invoice_line:"
+msgid "Cost Invoice Line"
+msgstr "Kostenfactuurregel"
+
+#, fuzzy
+msgctxt "field:stock.shipment.out,cost_sale:"
+msgid "Cost Sale"
+msgstr "Kosten"
+
+#, fuzzy
+msgctxt "field:stock.shipment.out,cost_sale_currency:"
+msgid "Cost Sale Currency"
+msgstr "Kostenvaluta"
+
+#, fuzzy
+msgctxt "field:stock.shipment.out,cost_sale_currency_used:"
+msgid "Cost Sale Currency"
+msgstr "Kostenvaluta"
+
+#, fuzzy
+msgctxt "field:stock.shipment.out,cost_sale_used:"
+msgid "Cost Sale"
+msgstr "Kosten"
+
+#, fuzzy
+msgctxt "field:stock.shipment.out,cost_used:"
+msgid "Cost"
+msgstr "Kosten"
+
+msgctxt "help:stock.shipment.out,cost_edit:"
+msgid "Check to edit the cost."
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_sale_invalid_carrier"
+msgid "To confirm sale \"%(sale)s\" you must change the carrier \"%(carrier)s\"."
+msgstr ""
+"Om verkoop \"%(sale)s\" te bevestigen, moet u de vervoerder "
+"\"%(carrier)s\"wijzigen."
+
+msgctxt ""
+"model:ir.message,text:msg_shipment_cost_invoice_missing_account_revenue"
+msgid ""
+"To invoice shipment cost of \"%(shipment)s\", you must define an account "
+"revenue for product \"%(product)s\"."
+msgstr ""
+"Om verzendingskosten van \"%(shipment)s\" te factureren, moet u een "
+"omzetrekening definiëren voor product \"%(product)s\"."
+
+msgctxt "selection:sale.sale,shipment_cost_method:"
+msgid "None"
+msgstr ""
+
+msgctxt "selection:sale.sale,shipment_cost_method:"
+msgid "On Order"
+msgstr "Op bestelling"
+
+msgctxt "selection:sale.sale,shipment_cost_method:"
+msgid "On Shipment"
+msgstr "Bij verzending"
+
+msgctxt "view:sale.promotion:"
+msgid "Shipment Cost Included"
+msgstr "Verzendingskosten inbegrepen"
diff --git a/modules/sale_shipment_cost/locale/pl.po b/modules/sale_shipment_cost/locale/pl.po
new file mode 100644
index 0000000000..2d615e3ea8
--- /dev/null
+++ b/modules/sale_shipment_cost/locale/pl.po
@@ -0,0 +1,105 @@
+#
+msgid ""
+msgstr "Content-Type: text/plain; charset=utf-8\n"
+
+msgctxt "field:sale.configuration,sale_shipment_cost_method:"
+msgid "Sale Shipment Cost Method"
+msgstr ""
+
+msgctxt "field:sale.configuration.sale_method,sale_shipment_cost_method:"
+msgid "Sale Shipment Cost Method"
+msgstr ""
+
+msgctxt "field:sale.line,shipment_cost:"
+msgid "Shipment Cost"
+msgstr "Koszt wysyłki"
+
+msgctxt "field:sale.promotion,amount_shipment_cost_included:"
+msgid "Amount with Shipment Cost Included"
+msgstr ""
+
+msgctxt "field:sale.sale,available_carriers:"
+msgid "Available Carriers"
+msgstr ""
+
+msgctxt "field:sale.sale,carrier:"
+msgid "Carrier"
+msgstr ""
+
+msgctxt "field:sale.sale,shipment_cost_method:"
+msgid "Shipment Cost Method"
+msgstr ""
+
+msgctxt "field:stock.shipment.out,carrier:"
+msgid "Carrier"
+msgstr ""
+
+msgctxt "field:stock.shipment.out,cost:"
+msgid "Cost"
+msgstr "Koszt"
+
+#, fuzzy
+msgctxt "field:stock.shipment.out,cost_edit:"
+msgid "Edit Cost"
+msgstr "Koszt wysyłki"
+
+msgctxt "field:stock.shipment.out,cost_invoice_line:"
+msgid "Cost Invoice Line"
+msgstr ""
+
+#, fuzzy
+msgctxt "field:stock.shipment.out,cost_sale:"
+msgid "Cost Sale"
+msgstr "Koszt"
+
+#, fuzzy
+msgctxt "field:stock.shipment.out,cost_sale_currency:"
+msgid "Cost Sale Currency"
+msgstr "Koszt waluty"
+
+#, fuzzy
+msgctxt "field:stock.shipment.out,cost_sale_currency_used:"
+msgid "Cost Sale Currency"
+msgstr "Koszt waluty"
+
+#, fuzzy
+msgctxt "field:stock.shipment.out,cost_sale_used:"
+msgid "Cost Sale"
+msgstr "Koszt"
+
+#, fuzzy
+msgctxt "field:stock.shipment.out,cost_used:"
+msgid "Cost"
+msgstr "Koszt"
+
+msgctxt "help:stock.shipment.out,cost_edit:"
+msgid "Check to edit the cost."
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_sale_invalid_carrier"
+msgid "To confirm sale \"%(sale)s\" you must change the carrier \"%(carrier)s\"."
+msgstr ""
+
+msgctxt ""
+"model:ir.message,text:msg_shipment_cost_invoice_missing_account_revenue"
+msgid ""
+"To invoice shipment cost of \"%(shipment)s\", you must define an account "
+"revenue for product \"%(product)s\"."
+msgstr ""
+
+msgctxt "selection:sale.sale,shipment_cost_method:"
+msgid "None"
+msgstr ""
+
+msgctxt "selection:sale.sale,shipment_cost_method:"
+msgid "On Order"
+msgstr ""
+
+msgctxt "selection:sale.sale,shipment_cost_method:"
+msgid "On Shipment"
+msgstr ""
+
+#, fuzzy
+msgctxt "view:sale.promotion:"
+msgid "Shipment Cost Included"
+msgstr "Koszt wysyłki"
diff --git a/modules/sale_shipment_cost/locale/pt.po b/modules/sale_shipment_cost/locale/pt.po
new file mode 100644
index 0000000000..271f994899
--- /dev/null
+++ b/modules/sale_shipment_cost/locale/pt.po
@@ -0,0 +1,105 @@
+#
+msgid ""
+msgstr "Content-Type: text/plain; charset=utf-8\n"
+
+msgctxt "field:sale.configuration,sale_shipment_cost_method:"
+msgid "Sale Shipment Cost Method"
+msgstr "Método de Custo da Remessa ao Cliente"
+
+msgctxt "field:sale.configuration.sale_method,sale_shipment_cost_method:"
+msgid "Sale Shipment Cost Method"
+msgstr "Método de Custo da Remessa de Venda"
+
+msgctxt "field:sale.line,shipment_cost:"
+msgid "Shipment Cost"
+msgstr "Custo de remessa"
+
+msgctxt "field:sale.promotion,amount_shipment_cost_included:"
+msgid "Amount with Shipment Cost Included"
+msgstr ""
+
+msgctxt "field:sale.sale,available_carriers:"
+msgid "Available Carriers"
+msgstr "Transportadoras disponíveis"
+
+msgctxt "field:sale.sale,carrier:"
+msgid "Carrier"
+msgstr "Transportadora"
+
+msgctxt "field:sale.sale,shipment_cost_method:"
+msgid "Shipment Cost Method"
+msgstr "Método de custo de remessa"
+
+msgctxt "field:stock.shipment.out,carrier:"
+msgid "Carrier"
+msgstr "Método de custo de remessa"
+
+msgctxt "field:stock.shipment.out,cost:"
+msgid "Cost"
+msgstr "Custo"
+
+#, fuzzy
+msgctxt "field:stock.shipment.out,cost_edit:"
+msgid "Edit Cost"
+msgstr "Custo de remessa"
+
+msgctxt "field:stock.shipment.out,cost_invoice_line:"
+msgid "Cost Invoice Line"
+msgstr "Linha de custo da fatura"
+
+#, fuzzy
+msgctxt "field:stock.shipment.out,cost_sale:"
+msgid "Cost Sale"
+msgstr "Custo"
+
+#, fuzzy
+msgctxt "field:stock.shipment.out,cost_sale_currency:"
+msgid "Cost Sale Currency"
+msgstr "Moeda de custo"
+
+#, fuzzy
+msgctxt "field:stock.shipment.out,cost_sale_currency_used:"
+msgid "Cost Sale Currency"
+msgstr "Moeda de custo"
+
+#, fuzzy
+msgctxt "field:stock.shipment.out,cost_sale_used:"
+msgid "Cost Sale"
+msgstr "Custo"
+
+#, fuzzy
+msgctxt "field:stock.shipment.out,cost_used:"
+msgid "Cost"
+msgstr "Custo"
+
+msgctxt "help:stock.shipment.out,cost_edit:"
+msgid "Check to edit the cost."
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_sale_invalid_carrier"
+msgid "To confirm sale \"%(sale)s\" you must change the carrier \"%(carrier)s\"."
+msgstr ""
+
+msgctxt ""
+"model:ir.message,text:msg_shipment_cost_invoice_missing_account_revenue"
+msgid ""
+"To invoice shipment cost of \"%(shipment)s\", you must define an account "
+"revenue for product \"%(product)s\"."
+msgstr ""
+
+msgctxt "selection:sale.sale,shipment_cost_method:"
+msgid "None"
+msgstr ""
+
+msgctxt "selection:sale.sale,shipment_cost_method:"
+msgid "On Order"
+msgstr "No pedido"
+
+msgctxt "selection:sale.sale,shipment_cost_method:"
+msgid "On Shipment"
+msgstr "Na remessa"
+
+#, fuzzy
+msgctxt "view:sale.promotion:"
+msgid "Shipment Cost Included"
+msgstr "Método de custo de remessa"
diff --git a/modules/sale_shipment_cost/locale/ro.po b/modules/sale_shipment_cost/locale/ro.po
new file mode 100644
index 0000000000..b95356e164
--- /dev/null
+++ b/modules/sale_shipment_cost/locale/ro.po
@@ -0,0 +1,98 @@
+#
+msgid ""
+msgstr "Content-Type: text/plain; charset=utf-8\n"
+
+msgctxt "field:sale.configuration,sale_shipment_cost_method:"
+msgid "Sale Shipment Cost Method"
+msgstr ""
+
+msgctxt "field:sale.configuration.sale_method,sale_shipment_cost_method:"
+msgid "Sale Shipment Cost Method"
+msgstr ""
+
+msgctxt "field:sale.line,shipment_cost:"
+msgid "Shipment Cost"
+msgstr ""
+
+msgctxt "field:sale.promotion,amount_shipment_cost_included:"
+msgid "Amount with Shipment Cost Included"
+msgstr ""
+
+msgctxt "field:sale.sale,available_carriers:"
+msgid "Available Carriers"
+msgstr ""
+
+msgctxt "field:sale.sale,carrier:"
+msgid "Carrier"
+msgstr ""
+
+msgctxt "field:sale.sale,shipment_cost_method:"
+msgid "Shipment Cost Method"
+msgstr ""
+
+msgctxt "field:stock.shipment.out,carrier:"
+msgid "Carrier"
+msgstr ""
+
+msgctxt "field:stock.shipment.out,cost:"
+msgid "Cost"
+msgstr ""
+
+msgctxt "field:stock.shipment.out,cost_edit:"
+msgid "Edit Cost"
+msgstr ""
+
+msgctxt "field:stock.shipment.out,cost_invoice_line:"
+msgid "Cost Invoice Line"
+msgstr ""
+
+msgctxt "field:stock.shipment.out,cost_sale:"
+msgid "Cost Sale"
+msgstr ""
+
+msgctxt "field:stock.shipment.out,cost_sale_currency:"
+msgid "Cost Sale Currency"
+msgstr ""
+
+msgctxt "field:stock.shipment.out,cost_sale_currency_used:"
+msgid "Cost Sale Currency"
+msgstr ""
+
+msgctxt "field:stock.shipment.out,cost_sale_used:"
+msgid "Cost Sale"
+msgstr ""
+
+msgctxt "field:stock.shipment.out,cost_used:"
+msgid "Cost"
+msgstr ""
+
+msgctxt "help:stock.shipment.out,cost_edit:"
+msgid "Check to edit the cost."
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_sale_invalid_carrier"
+msgid "To confirm sale \"%(sale)s\" you must change the carrier \"%(carrier)s\"."
+msgstr ""
+
+msgctxt ""
+"model:ir.message,text:msg_shipment_cost_invoice_missing_account_revenue"
+msgid ""
+"To invoice shipment cost of \"%(shipment)s\", you must define an account "
+"revenue for product \"%(product)s\"."
+msgstr ""
+
+msgctxt "selection:sale.sale,shipment_cost_method:"
+msgid "None"
+msgstr ""
+
+msgctxt "selection:sale.sale,shipment_cost_method:"
+msgid "On Order"
+msgstr ""
+
+msgctxt "selection:sale.sale,shipment_cost_method:"
+msgid "On Shipment"
+msgstr ""
+
+msgctxt "view:sale.promotion:"
+msgid "Shipment Cost Included"
+msgstr ""
diff --git a/modules/sale_shipment_cost/locale/ru.po b/modules/sale_shipment_cost/locale/ru.po
new file mode 100644
index 0000000000..ca4e13bbe7
--- /dev/null
+++ b/modules/sale_shipment_cost/locale/ru.po
@@ -0,0 +1,104 @@
+#
+msgid ""
+msgstr "Content-Type: text/plain; charset=utf-8\n"
+
+msgctxt "field:sale.configuration,sale_shipment_cost_method:"
+msgid "Sale Shipment Cost Method"
+msgstr ""
+
+msgctxt "field:sale.configuration.sale_method,sale_shipment_cost_method:"
+msgid "Sale Shipment Cost Method"
+msgstr ""
+
+msgctxt "field:sale.line,shipment_cost:"
+msgid "Shipment Cost"
+msgstr ""
+
+msgctxt "field:sale.promotion,amount_shipment_cost_included:"
+msgid "Amount with Shipment Cost Included"
+msgstr ""
+
+msgctxt "field:sale.sale,available_carriers:"
+msgid "Available Carriers"
+msgstr ""
+
+msgctxt "field:sale.sale,carrier:"
+msgid "Carrier"
+msgstr ""
+
+msgctxt "field:sale.sale,shipment_cost_method:"
+msgid "Shipment Cost Method"
+msgstr ""
+
+msgctxt "field:stock.shipment.out,carrier:"
+msgid "Carrier"
+msgstr ""
+
+#, fuzzy
+msgctxt "field:stock.shipment.out,cost:"
+msgid "Cost"
+msgstr "Стоимость"
+
+#, fuzzy
+msgctxt "field:stock.shipment.out,cost_edit:"
+msgid "Edit Cost"
+msgstr "Стоимость"
+
+msgctxt "field:stock.shipment.out,cost_invoice_line:"
+msgid "Cost Invoice Line"
+msgstr ""
+
+#, fuzzy
+msgctxt "field:stock.shipment.out,cost_sale:"
+msgid "Cost Sale"
+msgstr "Стоимость"
+
+msgctxt "field:stock.shipment.out,cost_sale_currency:"
+msgid "Cost Sale Currency"
+msgstr ""
+
+#, fuzzy
+msgctxt "field:stock.shipment.out,cost_sale_currency_used:"
+msgid "Cost Sale Currency"
+msgstr "Стоимость"
+
+#, fuzzy
+msgctxt "field:stock.shipment.out,cost_sale_used:"
+msgid "Cost Sale"
+msgstr "Стоимость"
+
+#, fuzzy
+msgctxt "field:stock.shipment.out,cost_used:"
+msgid "Cost"
+msgstr "Стоимость"
+
+msgctxt "help:stock.shipment.out,cost_edit:"
+msgid "Check to edit the cost."
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_sale_invalid_carrier"
+msgid "To confirm sale \"%(sale)s\" you must change the carrier \"%(carrier)s\"."
+msgstr ""
+
+msgctxt ""
+"model:ir.message,text:msg_shipment_cost_invoice_missing_account_revenue"
+msgid ""
+"To invoice shipment cost of \"%(shipment)s\", you must define an account "
+"revenue for product \"%(product)s\"."
+msgstr ""
+
+msgctxt "selection:sale.sale,shipment_cost_method:"
+msgid "None"
+msgstr ""
+
+msgctxt "selection:sale.sale,shipment_cost_method:"
+msgid "On Order"
+msgstr ""
+
+msgctxt "selection:sale.sale,shipment_cost_method:"
+msgid "On Shipment"
+msgstr ""
+
+msgctxt "view:sale.promotion:"
+msgid "Shipment Cost Included"
+msgstr ""
diff --git a/modules/sale_shipment_cost/locale/sl.po b/modules/sale_shipment_cost/locale/sl.po
new file mode 100644
index 0000000000..65caacf7d5
--- /dev/null
+++ b/modules/sale_shipment_cost/locale/sl.po
@@ -0,0 +1,105 @@
+#
+msgid ""
+msgstr "Content-Type: text/plain; charset=utf-8\n"
+
+msgctxt "field:sale.configuration,sale_shipment_cost_method:"
+msgid "Sale Shipment Cost Method"
+msgstr "Obračun odpreme"
+
+msgctxt "field:sale.configuration.sale_method,sale_shipment_cost_method:"
+msgid "Sale Shipment Cost Method"
+msgstr "Obračun odpreme"
+
+msgctxt "field:sale.line,shipment_cost:"
+msgid "Shipment Cost"
+msgstr "Strošek dostave"
+
+msgctxt "field:sale.promotion,amount_shipment_cost_included:"
+msgid "Amount with Shipment Cost Included"
+msgstr ""
+
+msgctxt "field:sale.sale,available_carriers:"
+msgid "Available Carriers"
+msgstr "Razpoložljivi špediterji"
+
+msgctxt "field:sale.sale,carrier:"
+msgid "Carrier"
+msgstr "Špediter"
+
+msgctxt "field:sale.sale,shipment_cost_method:"
+msgid "Shipment Cost Method"
+msgstr "Obračun odpreme"
+
+msgctxt "field:stock.shipment.out,carrier:"
+msgid "Carrier"
+msgstr "Špediter"
+
+msgctxt "field:stock.shipment.out,cost:"
+msgid "Cost"
+msgstr "Strošek"
+
+#, fuzzy
+msgctxt "field:stock.shipment.out,cost_edit:"
+msgid "Edit Cost"
+msgstr "Strošek dostave"
+
+msgctxt "field:stock.shipment.out,cost_invoice_line:"
+msgid "Cost Invoice Line"
+msgstr "Postavka stroška"
+
+#, fuzzy
+msgctxt "field:stock.shipment.out,cost_sale:"
+msgid "Cost Sale"
+msgstr "Strošek"
+
+#, fuzzy
+msgctxt "field:stock.shipment.out,cost_sale_currency:"
+msgid "Cost Sale Currency"
+msgstr "Valuta stroška"
+
+#, fuzzy
+msgctxt "field:stock.shipment.out,cost_sale_currency_used:"
+msgid "Cost Sale Currency"
+msgstr "Valuta stroška"
+
+#, fuzzy
+msgctxt "field:stock.shipment.out,cost_sale_used:"
+msgid "Cost Sale"
+msgstr "Strošek"
+
+#, fuzzy
+msgctxt "field:stock.shipment.out,cost_used:"
+msgid "Cost"
+msgstr "Strošek"
+
+msgctxt "help:stock.shipment.out,cost_edit:"
+msgid "Check to edit the cost."
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_sale_invalid_carrier"
+msgid "To confirm sale \"%(sale)s\" you must change the carrier \"%(carrier)s\"."
+msgstr ""
+
+msgctxt ""
+"model:ir.message,text:msg_shipment_cost_invoice_missing_account_revenue"
+msgid ""
+"To invoice shipment cost of \"%(shipment)s\", you must define an account "
+"revenue for product \"%(product)s\"."
+msgstr ""
+
+msgctxt "selection:sale.sale,shipment_cost_method:"
+msgid "None"
+msgstr ""
+
+msgctxt "selection:sale.sale,shipment_cost_method:"
+msgid "On Order"
+msgstr "Po nalogu"
+
+msgctxt "selection:sale.sale,shipment_cost_method:"
+msgid "On Shipment"
+msgstr "Po odpremi"
+
+#, fuzzy
+msgctxt "view:sale.promotion:"
+msgid "Shipment Cost Included"
+msgstr "Obračun odpreme"
diff --git a/modules/sale_shipment_cost/locale/tr.po b/modules/sale_shipment_cost/locale/tr.po
new file mode 100644
index 0000000000..b95356e164
--- /dev/null
+++ b/modules/sale_shipment_cost/locale/tr.po
@@ -0,0 +1,98 @@
+#
+msgid ""
+msgstr "Content-Type: text/plain; charset=utf-8\n"
+
+msgctxt "field:sale.configuration,sale_shipment_cost_method:"
+msgid "Sale Shipment Cost Method"
+msgstr ""
+
+msgctxt "field:sale.configuration.sale_method,sale_shipment_cost_method:"
+msgid "Sale Shipment Cost Method"
+msgstr ""
+
+msgctxt "field:sale.line,shipment_cost:"
+msgid "Shipment Cost"
+msgstr ""
+
+msgctxt "field:sale.promotion,amount_shipment_cost_included:"
+msgid "Amount with Shipment Cost Included"
+msgstr ""
+
+msgctxt "field:sale.sale,available_carriers:"
+msgid "Available Carriers"
+msgstr ""
+
+msgctxt "field:sale.sale,carrier:"
+msgid "Carrier"
+msgstr ""
+
+msgctxt "field:sale.sale,shipment_cost_method:"
+msgid "Shipment Cost Method"
+msgstr ""
+
+msgctxt "field:stock.shipment.out,carrier:"
+msgid "Carrier"
+msgstr ""
+
+msgctxt "field:stock.shipment.out,cost:"
+msgid "Cost"
+msgstr ""
+
+msgctxt "field:stock.shipment.out,cost_edit:"
+msgid "Edit Cost"
+msgstr ""
+
+msgctxt "field:stock.shipment.out,cost_invoice_line:"
+msgid "Cost Invoice Line"
+msgstr ""
+
+msgctxt "field:stock.shipment.out,cost_sale:"
+msgid "Cost Sale"
+msgstr ""
+
+msgctxt "field:stock.shipment.out,cost_sale_currency:"
+msgid "Cost Sale Currency"
+msgstr ""
+
+msgctxt "field:stock.shipment.out,cost_sale_currency_used:"
+msgid "Cost Sale Currency"
+msgstr ""
+
+msgctxt "field:stock.shipment.out,cost_sale_used:"
+msgid "Cost Sale"
+msgstr ""
+
+msgctxt "field:stock.shipment.out,cost_used:"
+msgid "Cost"
+msgstr ""
+
+msgctxt "help:stock.shipment.out,cost_edit:"
+msgid "Check to edit the cost."
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_sale_invalid_carrier"
+msgid "To confirm sale \"%(sale)s\" you must change the carrier \"%(carrier)s\"."
+msgstr ""
+
+msgctxt ""
+"model:ir.message,text:msg_shipment_cost_invoice_missing_account_revenue"
+msgid ""
+"To invoice shipment cost of \"%(shipment)s\", you must define an account "
+"revenue for product \"%(product)s\"."
+msgstr ""
+
+msgctxt "selection:sale.sale,shipment_cost_method:"
+msgid "None"
+msgstr ""
+
+msgctxt "selection:sale.sale,shipment_cost_method:"
+msgid "On Order"
+msgstr ""
+
+msgctxt "selection:sale.sale,shipment_cost_method:"
+msgid "On Shipment"
+msgstr ""
+
+msgctxt "view:sale.promotion:"
+msgid "Shipment Cost Included"
+msgstr ""
diff --git a/modules/sale_shipment_cost/locale/zh_CN.po b/modules/sale_shipment_cost/locale/zh_CN.po
new file mode 100644
index 0000000000..b95356e164
--- /dev/null
+++ b/modules/sale_shipment_cost/locale/zh_CN.po
@@ -0,0 +1,98 @@
+#
+msgid ""
+msgstr "Content-Type: text/plain; charset=utf-8\n"
+
+msgctxt "field:sale.configuration,sale_shipment_cost_method:"
+msgid "Sale Shipment Cost Method"
+msgstr ""
+
+msgctxt "field:sale.configuration.sale_method,sale_shipment_cost_method:"
+msgid "Sale Shipment Cost Method"
+msgstr ""
+
+msgctxt "field:sale.line,shipment_cost:"
+msgid "Shipment Cost"
+msgstr ""
+
+msgctxt "field:sale.promotion,amount_shipment_cost_included:"
+msgid "Amount with Shipment Cost Included"
+msgstr ""
+
+msgctxt "field:sale.sale,available_carriers:"
+msgid "Available Carriers"
+msgstr ""
+
+msgctxt "field:sale.sale,carrier:"
+msgid "Carrier"
+msgstr ""
+
+msgctxt "field:sale.sale,shipment_cost_method:"
+msgid "Shipment Cost Method"
+msgstr ""
+
+msgctxt "field:stock.shipment.out,carrier:"
+msgid "Carrier"
+msgstr ""
+
+msgctxt "field:stock.shipment.out,cost:"
+msgid "Cost"
+msgstr ""
+
+msgctxt "field:stock.shipment.out,cost_edit:"
+msgid "Edit Cost"
+msgstr ""
+
+msgctxt "field:stock.shipment.out,cost_invoice_line:"
+msgid "Cost Invoice Line"
+msgstr ""
+
+msgctxt "field:stock.shipment.out,cost_sale:"
+msgid "Cost Sale"
+msgstr ""
+
+msgctxt "field:stock.shipment.out,cost_sale_currency:"
+msgid "Cost Sale Currency"
+msgstr ""
+
+msgctxt "field:stock.shipment.out,cost_sale_currency_used:"
+msgid "Cost Sale Currency"
+msgstr ""
+
+msgctxt "field:stock.shipment.out,cost_sale_used:"
+msgid "Cost Sale"
+msgstr ""
+
+msgctxt "field:stock.shipment.out,cost_used:"
+msgid "Cost"
+msgstr ""
+
+msgctxt "help:stock.shipment.out,cost_edit:"
+msgid "Check to edit the cost."
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_sale_invalid_carrier"
+msgid "To confirm sale \"%(sale)s\" you must change the carrier \"%(carrier)s\"."
+msgstr ""
+
+msgctxt ""
+"model:ir.message,text:msg_shipment_cost_invoice_missing_account_revenue"
+msgid ""
+"To invoice shipment cost of \"%(shipment)s\", you must define an account "
+"revenue for product \"%(product)s\"."
+msgstr ""
+
+msgctxt "selection:sale.sale,shipment_cost_method:"
+msgid "None"
+msgstr ""
+
+msgctxt "selection:sale.sale,shipment_cost_method:"
+msgid "On Order"
+msgstr ""
+
+msgctxt "selection:sale.sale,shipment_cost_method:"
+msgid "On Shipment"
+msgstr ""
+
+msgctxt "view:sale.promotion:"
+msgid "Shipment Cost Included"
+msgstr ""
diff --git a/modules/sale_shipment_cost/message.xml b/modules/sale_shipment_cost/message.xml
new file mode 100644
index 0000000000..7b6020a990
--- /dev/null
+++ b/modules/sale_shipment_cost/message.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+ To confirm sale "%(sale)s" you must change the carrier "%(carrier)s".
+
+
+ To invoice shipment cost of "%(shipment)s", you must define an account revenue for product "%(product)s".
+
+
+
diff --git a/modules/sale_shipment_cost/sale.py b/modules/sale_shipment_cost/sale.py
new file mode 100644
index 0000000000..2c22ebe58a
--- /dev/null
+++ b/modules/sale_shipment_cost/sale.py
@@ -0,0 +1,395 @@
+# This file is part of Tryton. The COPYRIGHT file at the top level of
+# this repository contains the full copyright notices and license terms.
+from decimal import Decimal
+
+from trytond import backend
+from trytond.i18n import gettext
+from trytond.model import ModelView, Workflow, fields
+from trytond.transaction import Transaction
+from trytond.pyson import Eval, If
+from trytond.pool import Pool, PoolMeta
+
+from trytond.modules.product import price_digits, round_price
+from trytond.modules.sale.exceptions import SaleConfirmError
+
+sale_shipment_cost_method = fields.Selection(
+ 'get_sale_shipment_cost_methods', "Sale Shipment Cost Method")
+
+
+def get_sale_methods(field_name):
+ @classmethod
+ def func(cls):
+ pool = Pool()
+ Sale = pool.get('sale.sale')
+ return Sale.fields_get([field_name])[field_name]['selection']
+ return func
+
+
+class Configuration(metaclass=PoolMeta):
+ __name__ = 'sale.configuration'
+ sale_shipment_cost_method = fields.MultiValue(sale_shipment_cost_method)
+ get_sale_shipment_cost_methods = get_sale_methods('shipment_cost_method')
+
+ @classmethod
+ def multivalue_model(cls, field):
+ pool = Pool()
+ if field == 'sale_shipment_cost_method':
+ return pool.get('sale.configuration.sale_method')
+ return super(Configuration, cls).multivalue_model(field)
+
+ @classmethod
+ def default_sale_shipment_cost_method(cls, **pattern):
+ return cls.multivalue_model(
+ 'sale_shipment_cost_method').default_sale_shipment_cost_method()
+
+
+class ConfigurationSaleMethod(metaclass=PoolMeta):
+ __name__ = 'sale.configuration.sale_method'
+ sale_shipment_cost_method = sale_shipment_cost_method
+ get_sale_shipment_cost_methods = get_sale_methods('shipment_cost_method')
+
+ @classmethod
+ def __register__(cls, module_name):
+ exist = backend.TableHandler.table_exist(cls._table)
+ if exist:
+ table = cls.__table_handler__(module_name)
+ exist &= table.column_exist('sale_shipment_cost_method')
+
+ super(ConfigurationSaleMethod, cls).__register__(module_name)
+
+ if not exist:
+ cls._migrate_property([], [], [])
+
+ @classmethod
+ def _migrate_property(cls, field_names, value_names, fields):
+ field_names.append('sale_shipment_cost_method')
+ value_names.append('sale_shipment_cost_method')
+ super(ConfigurationSaleMethod, cls)._migrate_property(
+ field_names, value_names, fields)
+
+ @classmethod
+ def default_sale_shipment_cost_method(cls):
+ return 'order'
+
+
+class Sale(metaclass=PoolMeta):
+ __name__ = 'sale.sale'
+ carrier = fields.Many2One('carrier', 'Carrier',
+ domain=[
+ If(Eval('state') == 'draft', [
+ ('carrier_product.salable', '=', True),
+ ('id', 'in', Eval('available_carriers', [])),
+ ],
+ []),
+ ],
+ states={
+ 'readonly': Eval('state') != 'draft',
+ },
+ context={
+ 'company': Eval('company', -1),
+ },
+ depends=['state', 'available_carriers', 'company'])
+ available_carriers = fields.Function(
+ fields.Many2Many('carrier', None, None, 'Available Carriers'),
+ 'on_change_with_available_carriers')
+ shipment_cost_method = fields.Selection([
+ (None, "None"),
+ ('order', 'On Order'),
+ ('shipment', 'On Shipment'),
+ ], 'Shipment Cost Method', states={
+ 'readonly': Eval('state') != 'draft',
+ }, depends=['state'])
+
+ @classmethod
+ def __register__(cls, module):
+ super().__register__(module)
+ table_h = cls.__table_handler__(module)
+ # Migration from 5.8: remove required on shipment_cost_method
+ table_h.not_null_action('shipment_cost_method', 'remove')
+
+ @classmethod
+ def default_shipment_cost_method(cls, **pattern):
+ Config = Pool().get('sale.configuration')
+ config = Config(1)
+ return config.get_multivalue(
+ 'sale_shipment_cost_method', **pattern)
+
+ @fields.depends('company')
+ def on_change_company(self):
+ super().on_change_company()
+ self.shipment_cost_method = self.default_shipment_cost_method(
+ company=self.company.id if self.company else None)
+
+ @fields.depends('warehouse', 'shipment_address')
+ def _get_carrier_selection_pattern(self):
+ pattern = {}
+ if (self.warehouse
+ and self.warehouse.address
+ and self.warehouse.address.country):
+ pattern['from_country'] = self.warehouse.address.country.id
+ else:
+ pattern['from_country'] = None
+ if self.shipment_address and self.shipment_address.country:
+ pattern['to_country'] = self.shipment_address.country.id
+ else:
+ pattern['to_country'] = None
+ return pattern
+
+ @fields.depends(methods=['_get_carrier_selection_pattern'])
+ def on_change_with_available_carriers(self, name=None):
+ pool = Pool()
+ CarrierSelection = pool.get('carrier.selection')
+
+ pattern = self._get_carrier_selection_pattern()
+ carriers = CarrierSelection.get_carriers(pattern)
+ return [c.id for c in carriers]
+
+ @fields.depends('carrier', methods=['on_change_with_available_carriers'])
+ def on_change_party(self):
+ super(Sale, self).on_change_party()
+ self.available_carriers = self.on_change_with_available_carriers()
+ if self.available_carriers and (not self.carrier
+ or self.carrier not in self.available_carriers):
+ self.carrier = self.available_carriers[0]
+ elif not self.available_carriers:
+ self.carrier = None
+
+ @fields.depends('carrier', methods=['on_change_with_available_carriers'])
+ def on_change_shipment_party(self):
+ super(Sale, self).on_change_shipment_party()
+ self.available_carriers = self.on_change_with_available_carriers()
+ if self.available_carriers and (not self.carrier
+ or self.carrier not in self.available_carriers):
+ self.carrier = self.available_carriers[0]
+ elif not self.available_carriers:
+ self.carrier = None
+
+ @fields.depends('carrier', methods=['on_change_with_available_carriers'])
+ def on_change_shipment_address(self):
+ try:
+ super_on_change = super(Sale, self).on_change_shipment_address
+ except AttributeError:
+ pass
+ else:
+ super_on_change()
+
+ self.available_carriers = self.on_change_with_available_carriers()
+ if self.available_carriers and (not self.carrier
+ or self.carrier not in self.available_carriers):
+ self.carrier = self.available_carriers[0]
+ elif not self.available_carriers:
+ self.carrier = None
+
+ @classmethod
+ @ModelView.button
+ @Workflow.transition('quotation')
+ def quote(cls, sales):
+ pool = Pool()
+ Line = pool.get('sale.line')
+ removed = []
+ for sale in sales:
+ removed.extend(sale.set_shipment_cost())
+ Line.delete(removed)
+ cls.save(sales)
+ super(Sale, cls).quote(sales)
+
+ @classmethod
+ @ModelView.button
+ @Workflow.transition('confirmed')
+ def confirm(cls, sales):
+ for sale in sales:
+ if sale.carrier and sale.carrier not in sale.available_carriers:
+ raise SaleConfirmError(
+ gettext('sale_shipment_cost.msg_sale_invalid_carrier',
+ sale=sale.rec_name,
+ carrier=sale.carrier.rec_name))
+ super(Sale, cls).confirm(sales)
+
+ def _get_carrier_context(self):
+ return {}
+
+ def compute_shipment_cost(self):
+ pool = Pool()
+ Date = pool.get('ir.date')
+ Currency = pool.get('currency.currency')
+ Move = pool.get('stock.move')
+ stockable = any(
+ line.quantity >= 0 for line in self.lines
+ if line.type == 'line'
+ and line.product
+ and line.product.type in Move.get_product_types())
+ if self.carrier and stockable:
+ with Transaction().set_context(self._get_carrier_context()):
+ cost, currency_id = self.carrier.get_sale_price()
+ today = Date.today()
+ date = self.sale_date or today
+ with Transaction().set_context(date=date):
+ return Currency.compute(
+ Currency(currency_id), cost, self.currency, round=False)
+
+ def set_shipment_cost(self):
+ cost = None
+ if self.shipment_cost_method:
+ cost = self.compute_shipment_cost()
+ removed = []
+ unit_price = None
+ lines = list(self.lines or [])
+ for line in self.lines:
+ if line.type == 'line' and line.shipment_cost is not None:
+ if line.shipment_cost == cost:
+ unit_price = line.unit_price * Decimal(str(line.quantity))
+ lines.remove(line)
+ removed.append(line)
+ if cost is not None:
+ lines.append(self.get_shipment_cost_line(
+ cost, unit_price=unit_price))
+ self.lines = lines
+ return removed
+
+ def get_shipment_cost_line(self, cost, unit_price=None):
+ pool = Pool()
+ SaleLine = pool.get('sale.line')
+
+ product = self.carrier.carrier_product
+
+ sequence = None
+ if self.lines:
+ last_line = self.lines[-1]
+ if last_line.sequence is not None:
+ sequence = last_line.sequence + 1
+
+ shipment_cost = round_price(cost)
+ cost_line = SaleLine(
+ sale=self,
+ sequence=sequence,
+ type='line',
+ product=product,
+ quantity=1, # XXX
+ unit=product.sale_uom,
+ shipment_cost=shipment_cost,
+ )
+ cost_line.on_change_product()
+ if unit_price is not None:
+ cost_line.unit_price = round_price(unit_price)
+ else:
+ cost_line.unit_price = round_price(cost)
+ if not cost_line.unit_price:
+ cost_line.quantity = 0
+ cost_line.amount = cost_line.on_change_with_amount()
+ return cost_line
+
+ @property
+ def shipment_cost_amount(self):
+ cost = Decimal(0)
+ for line in self.lines:
+ if line.type == 'line' and line.shipment_cost is not None:
+ cost += line.amount
+ return cost
+
+ def create_shipment(self, shipment_type):
+ pool = Pool()
+ Shipment = pool.get('stock.shipment.out')
+
+ shipments = super(Sale, self).create_shipment(shipment_type)
+ if shipment_type == 'out' and shipments and self.carrier:
+ for shipment in shipments:
+ shipment.carrier = self.carrier
+ Shipment.save(shipments)
+ return shipments
+
+ def create_invoice(self):
+ pool = Pool()
+ InvoiceLine = pool.get('account.invoice.line')
+ Shipment = pool.get('stock.shipment.out')
+
+ invoice = super(Sale, self).create_invoice()
+ if invoice and self.shipment_cost_method == 'shipment':
+ invoice_lines = []
+ # Copy shipments to avoid losing changes as the cache is cleared
+ # after invoice line save because shipment is a Function field
+ shipments = list(self.shipments)
+ for shipment in shipments:
+ if (shipment.state == 'done'
+ and shipment.carrier
+ and not shipment.cost_invoice_line):
+ invoice_line = shipment.get_cost_invoice_line(invoice)
+ if not invoice_line:
+ continue
+ invoice_line.invoice = invoice
+ invoice_lines.append(invoice_line)
+ shipment.cost_invoice_line = invoice_line
+ InvoiceLine.save(invoice_lines)
+ Shipment.save(shipments)
+ invoice.update_taxes()
+ return invoice
+
+
+class Line(metaclass=PoolMeta):
+ __name__ = 'sale.line'
+ shipment_cost = fields.Numeric('Shipment Cost', digits=price_digits)
+
+ def _get_invoice_line_quantity(self):
+ quantity = super()._get_invoice_line_quantity()
+ if self.shipment_cost:
+ if self.sale.shipment_cost_method == 'shipment':
+ return 0
+ elif (self.sale.shipment_cost_method == 'order'
+ and self.sale.invoice_method == 'shipment'):
+ shipments = self.sale.shipments
+ if (not shipments
+ or all(s.state != 'done' for s in shipments)):
+ return 0
+ return quantity
+
+
+class ReturnSale(metaclass=PoolMeta):
+ __name__ = 'sale.return_sale'
+
+ def do_return_(self, action):
+ pool = Pool()
+ Sale = pool.get('sale.sale')
+ SaleLine = pool.get('sale.line')
+ action, data = super(ReturnSale, self).do_return_(action)
+
+ return_sales = Sale.browse(data['res_id'])
+ lines = []
+ for sale in return_sales:
+ for line in sale.lines:
+ # Do not consider return shipment cost as a shipment cost
+ if line.shipment_cost:
+ line.shipment_cost = None
+ lines.append(line)
+ SaleLine.save(lines)
+ return action, data
+
+
+class Promotion(metaclass=PoolMeta):
+ __name__ = 'sale.promotion'
+
+ amount_shipment_cost_included = fields.Boolean(
+ "Amount with Shipment Cost Included",
+ states={
+ 'invisible': ~Eval('amount'),
+ },
+ depends=['amount'])
+
+ @classmethod
+ def default_amount_shipment_cost_included(cls):
+ return False
+
+ def get_context_formula(self, sale_line):
+ context = super(Promotion, self).get_context_formula(sale_line)
+ if sale_line and sale_line.shipment_cost:
+ context['names']['unit_price'] = sale_line.shipment_cost
+ return context
+
+ def get_sale_amount(self, sale):
+ amount = super().get_sale_amount(sale)
+ if not self.amount_shipment_cost_included:
+ amount -= sum(l.amount for l in sale.lines if l.shipment_cost)
+ if not self.untaxed_amount:
+ amount -= sum(
+ v['amount']
+ for l in sale.lines if l.shipment_cost
+ for v in l._get_taxes().values())
+ return amount
diff --git a/modules/sale_shipment_cost/sale.xml b/modules/sale_shipment_cost/sale.xml
new file mode 100644
index 0000000000..d261f951d7
--- /dev/null
+++ b/modules/sale_shipment_cost/sale.xml
@@ -0,0 +1,34 @@
+
+
+
+
+
+ sale.configuration
+
+
+ configuration_form
+
+
+
+ sale.sale
+
+
+ sale_form
+
+
+
+ sale.line
+
+
+ sale_line_tree_sequence
+
+
+
+
+ sale.promotion
+
+ promotion_form
+
+
+
diff --git a/modules/sale_shipment_cost/setup.py b/modules/sale_shipment_cost/setup.py
new file mode 100755
index 0000000000..156291259f
--- /dev/null
+++ b/modules/sale_shipment_cost/setup.py
@@ -0,0 +1,157 @@
+#!/usr/bin/env python3
+# This file is part of Tryton. The COPYRIGHT file at the top level of
+# this repository contains the full copyright notices and license terms.
+
+import io
+import os
+import re
+from configparser import ConfigParser
+from setuptools import setup, find_packages
+
+
+def read(fname):
+ return io.open(
+ os.path.join(os.path.dirname(__file__), fname),
+ 'r', encoding='utf-8').read()
+
+
+def get_require_version(name):
+ if minor_version % 2:
+ require = '%s >= %s.%s.dev0, < %s.%s'
+ else:
+ require = '%s >= %s.%s, < %s.%s'
+ require %= (name, major_version, minor_version,
+ major_version, minor_version + 1)
+ return require
+
+
+config = ConfigParser()
+config.read_file(open(os.path.join(os.path.dirname(__file__), 'tryton.cfg')))
+info = dict(config.items('tryton'))
+for key in ('depends', 'extras_depend', 'xml'):
+ if key in info:
+ info[key] = info[key].strip().splitlines()
+version = info.get('version', '0.0.1')
+major_version, minor_version, _ = version.split('.', 2)
+major_version = int(major_version)
+minor_version = int(minor_version)
+name = 'trytond_sale_shipment_cost'
+
+download_url = 'http://downloads.tryton.org/%s.%s/' % (
+ major_version, minor_version)
+if minor_version % 2:
+ version = '%s.%s.dev0' % (major_version, minor_version)
+ download_url = (
+ 'hg+http://hg.tryton.org/modules/%s#egg=%s-%s' % (
+ name[8:], name, version))
+local_version = []
+if os.environ.get('CI_JOB_ID'):
+ local_version.append(os.environ['CI_JOB_ID'])
+else:
+ for build in ['CI_BUILD_NUMBER', 'CI_JOB_NUMBER']:
+ if os.environ.get(build):
+ local_version.append(os.environ[build])
+ else:
+ local_version = []
+ break
+if local_version:
+ version += '+' + '.'.join(local_version)
+
+requires = []
+for dep in info.get('depends', []):
+ if not re.match(r'(ir|res)(\W|$)', dep):
+ requires.append(get_require_version('trytond_%s' % dep))
+requires.append(get_require_version('trytond'))
+
+tests_require = [
+ get_require_version('proteus'),
+ get_require_version('trytond_stock_shipment_cost'),
+ ]
+for dep in ['account', 'party', 'stock', 'sale_promotion']:
+ tests_require.append(get_require_version('trytond_%s' % dep))
+dependency_links = []
+if minor_version % 2:
+ dependency_links.append(
+ 'https://trydevpi.tryton.org/?local_version='
+ + '.'.join(local_version))
+
+setup(name=name,
+ version=version,
+ description='Tryton module for sale shipment cost',
+ long_description=read('README.rst'),
+ author='Tryton',
+ author_email='bugs@tryton.org',
+ url='http://www.tryton.org/',
+ download_url=download_url,
+ project_urls={
+ "Bug Tracker": 'https://bugs.tryton.org/',
+ "Documentation": 'https://docs.tryton.org/',
+ "Forum": 'https://www.tryton.org/forum',
+ "Source Code": 'https://hg.tryton.org/modules/sale_shipment_cost',
+ },
+ keywords='tryton sale shipment cost',
+ package_dir={'trytond.modules.sale_shipment_cost': '.'},
+ packages=(
+ ['trytond.modules.sale_shipment_cost']
+ + ['trytond.modules.sale_shipment_cost.%s' % p
+ for p in find_packages()]
+ ),
+ package_data={
+ 'trytond.modules.sale_shipment_cost': (info.get('xml', [])
+ + ['tryton.cfg', 'view/*.xml', 'locale/*.po', 'tests/*.rst']),
+ },
+ classifiers=[
+ 'Development Status :: 5 - Production/Stable',
+ 'Environment :: Plugins',
+ 'Framework :: Tryton',
+ 'Intended Audience :: Developers',
+ 'Intended Audience :: Financial and Insurance Industry',
+ 'Intended Audience :: Legal Industry',
+ 'Intended Audience :: Manufacturing',
+ 'License :: OSI Approved :: '
+ 'GNU General Public License v3 or later (GPLv3+)',
+ 'Natural Language :: Bulgarian',
+ 'Natural Language :: Catalan',
+ 'Natural Language :: Chinese (Simplified)',
+ 'Natural Language :: Czech',
+ 'Natural Language :: Dutch',
+ 'Natural Language :: English',
+ 'Natural Language :: Finnish',
+ 'Natural Language :: French',
+ 'Natural Language :: German',
+ 'Natural Language :: Hungarian',
+ 'Natural Language :: Indonesian',
+ 'Natural Language :: Italian',
+ 'Natural Language :: Persian',
+ 'Natural Language :: Polish',
+ 'Natural Language :: Portuguese (Brazilian)',
+ 'Natural Language :: Romanian',
+ 'Natural Language :: Russian',
+ 'Natural Language :: Slovenian',
+ 'Natural Language :: Spanish',
+ 'Natural Language :: Turkish',
+ 'Operating System :: OS Independent',
+ 'Programming Language :: Python :: 3',
+ 'Programming Language :: Python :: 3.6',
+ 'Programming Language :: Python :: 3.7',
+ 'Programming Language :: Python :: 3.8',
+ 'Programming Language :: Python :: 3.9',
+ 'Programming Language :: Python :: Implementation :: CPython',
+ 'Programming Language :: Python :: Implementation :: PyPy',
+ 'Topic :: Office/Business',
+ ],
+ license='GPL-3',
+ python_requires='>=3.6',
+ install_requires=requires,
+ extras_require={
+ },
+ dependency_links=dependency_links,
+ zip_safe=False,
+ entry_points="""
+ [trytond.modules]
+ sale_shipment_cost = trytond.modules.sale_shipment_cost
+ """,
+ test_suite='tests',
+ test_loader='trytond.test_loader:Loader',
+ tests_require=tests_require,
+ )
diff --git a/modules/sale_shipment_cost/stock.py b/modules/sale_shipment_cost/stock.py
new file mode 100644
index 0000000000..38fb34d564
--- /dev/null
+++ b/modules/sale_shipment_cost/stock.py
@@ -0,0 +1,264 @@
+# This file is part of Tryton. The COPYRIGHT file at the top level of
+# this repository contains the full copyright notices and license terms.
+from trytond.i18n import gettext
+from trytond.model import ModelView, Workflow, fields
+from trytond.pyson import Eval, Bool
+from trytond.transaction import Transaction
+from trytond.pool import Pool, PoolMeta
+
+from trytond.modules.product import price_digits, round_price
+from .exceptions import InvoiceShipmentCostError
+
+
+class ShipmentOut(metaclass=PoolMeta):
+ __name__ = 'stock.shipment.out'
+ carrier = fields.Many2One('carrier', 'Carrier', states={
+ 'readonly': ~Eval('state').in_(['draft', 'waiting', 'assigned',
+ 'picked', 'packed']),
+ },
+ depends=['state'])
+
+ cost_used = fields.Function(fields.Numeric(
+ "Cost", digits=price_digits,
+ states={
+ 'invisible': ~Eval('carrier') | Eval('cost_edit', False),
+ },
+ depends=['carrier', 'cost_edit']),
+ 'on_change_with_cost_used')
+ cost = fields.Numeric(
+ "Cost", digits=price_digits,
+ states={
+ 'invisible': ~Eval('carrier') | ~Eval('cost_edit', False),
+ 'readonly': ~Eval('state').in_(
+ ['draft', 'waiting', 'assigned', 'picked', 'packed']),
+ },
+ depends=['carrier', 'state'])
+ cost_sale_currency_used = fields.Function(fields.Many2One(
+ 'currency.currency', "Cost Sale Currency",
+ states={
+ 'invisible': ~Eval('carrier') | Eval('cost_edit', False),
+ },
+ depends=['carrier', 'cost_edit']),
+ 'on_change_with_cost_sale_currency_used')
+ cost_sale_currency = fields.Many2One(
+ 'currency.currency', "Cost Sale Currency",
+ states={
+ 'invisible': ~Eval('carrier') | ~Eval('cost_edit', False),
+ 'required': Bool(Eval('cost_sale')),
+ 'readonly': ~Eval('state').in_(
+ ['draft', 'waiting', 'assigned', 'picked', 'packed']),
+ }, depends=['carrier', 'cost_sale', 'state'])
+ cost_sale_used = fields.Function(fields.Numeric(
+ "Cost Sale", digits=price_digits,
+ states={
+ 'invisible': ~Eval('carrier') | Eval('cost_edit', False),
+ },
+ depends=['carrier', 'cost_edit']),
+ 'on_change_with_cost_sale_used')
+ cost_sale = fields.Numeric(
+ "Cost Sale", digits=price_digits,
+ states={
+ 'invisible': ~Eval('carrier') | ~Eval('cost_edit', False),
+ 'readonly': ~Eval('state').in_(
+ ['draft', 'waiting', 'assigned', 'picked', 'packed']),
+ }, depends=['carrier', 'state'])
+
+ cost_edit = fields.Boolean(
+ "Edit Cost",
+ states={
+ 'invisible': ~Eval('carrier'),
+ 'readonly': ~Eval('state').in_(
+ ['draft', 'waiting', 'assigned', 'picked', 'packed']),
+ },
+ depends=['carrier', 'state'],
+ help="Check to edit the cost.")
+
+ cost_invoice_line = fields.Many2One('account.invoice.line',
+ 'Cost Invoice Line', readonly=True)
+
+ @classmethod
+ def __register__(cls, module):
+ table_h = cls.__table_handler__(module)
+ # Migration from 5.8: rename cost into cost_sale
+ if (table_h.column_exist('cost')
+ and not table_h.column_exist('cost_sale')):
+ table_h.column_rename('cost', 'cost_sale')
+ if (table_h.column_exist('cost_currency')
+ and not table_h.column_exist('cost_sale_currency')):
+ table_h.column_rename('cost_currency', 'cost_sale_currency')
+ super().__register__(module)
+
+ def _get_carrier_context(self):
+ return {}
+
+ def get_carrier_context(self):
+ return self._get_carrier_context()
+
+ @fields.depends('carrier', 'company', methods=['_get_carrier_context'])
+ def _compute_costs(self):
+ pool = Pool()
+ Currency = pool.get('currency.currency')
+ costs = {
+ 'cost': None,
+ 'cost_sale': None,
+ 'cost_sale_currency': None,
+ }
+ if self.carrier:
+ with Transaction().set_context(self._get_carrier_context()):
+ cost, currency_id = self.carrier.get_purchase_price()
+ cost_sale, sale_currency_id = self.carrier.get_sale_price()
+ if cost is not None:
+ cost = Currency.compute(
+ Currency(currency_id), cost, self.company.currency,
+ round=False)
+ costs['cost'] = round_price(cost)
+ if cost_sale is not None:
+ costs['cost_sale'] = round_price(cost_sale)
+ costs['cost_sale_currency'] = sale_currency_id
+ return costs
+
+ @fields.depends('state', 'cost', 'cost_edit', methods=['_compute_costs'])
+ def on_change_with_cost_used(self, name=None):
+ if not self.cost_edit and self.state not in {'cancelled', 'done'}:
+ return self._compute_costs()['cost']
+ else:
+ return self.cost
+
+ @fields.depends(
+ 'state', 'cost_sale', 'cost_edit', methods=['_compute_costs'])
+ def on_change_with_cost_sale_used(self, name=None):
+ if not self.cost_edit and self.state not in {'cancelled', 'done'}:
+ return self._compute_costs()['cost_sale']
+ else:
+ return self.cost_sale
+
+ @fields.depends(
+ 'state', 'cost_sale_currency', 'cost_edit', methods=['_compute_costs'])
+ def on_change_with_cost_sale_currency_used(self, name=None):
+ if not self.cost_edit and self.state not in {'cancelled', 'done'}:
+ return self._compute_costs()['cost_sale_currency']
+ elif self.cost_sale_currency:
+ return self.cost_sale_currency.id
+
+ @fields.depends(
+ 'cost_edit', 'cost_used', 'cost_sale_used', 'cost_sale_currency_used')
+ def on_change_cost_edit(self):
+ if self.cost_edit:
+ self.cost = self.cost_used
+ self.cost_sale = self.cost_sale_used
+ self.cost_sale_currency = self.cost_sale_currency_used
+
+ def _get_cost_tax_rule_pattern(self):
+ 'Get tax rule pattern for invoice line'
+ return {}
+
+ def get_cost_invoice_line(self, invoice):
+ pool = Pool()
+ Product = pool.get('product.product')
+ Currency = pool.get('currency.currency')
+ InvoiceLine = pool.get('account.invoice.line')
+
+ if not self.cost_sale_used:
+ return
+ invoice_line = InvoiceLine()
+ product = self.carrier.carrier_product
+ invoice_line.type = 'line'
+ invoice_line.product = product
+
+ party = invoice.party
+ party_context = {}
+ if party.lang:
+ party_context['language'] = party.lang.code
+ with Transaction().set_context(party_context):
+ invoice_line.description = Product(product.id).rec_name
+
+ invoice_line.quantity = 1 # XXX
+ invoice_line.unit = product.sale_uom.id
+ cost = self.cost_sale_used
+ if invoice.currency != self.cost_sale_currency_used:
+ with Transaction().set_context(date=invoice.currency_date):
+ cost = Currency.compute(
+ self.cost_sale_currency_used, cost,
+ invoice.currency, round=False)
+ invoice_line.unit_price = round_price(cost)
+ invoice_line.currency = invoice.currency
+ invoice_line.company = invoice.company
+
+ taxes = set()
+ pattern = self._get_cost_tax_rule_pattern()
+ for tax in product.customer_taxes_used:
+ if party.customer_tax_rule:
+ tax_ids = party.customer_tax_rule.apply(tax, pattern)
+ if tax_ids:
+ taxes.update(tax_ids)
+ continue
+ taxes.add(tax.id)
+ if party.customer_tax_rule:
+ tax_ids = party.customer_tax_rule.apply(None, pattern)
+ if tax_ids:
+ taxes.update(tax_ids)
+ invoice_line.taxes = taxes
+
+ invoice_line.account = product.account_revenue_used
+ if not invoice_line.account:
+ raise InvoiceShipmentCostError(
+ gettext('sale_shipment_cost'
+ '.msg_shipment_cost_invoice_missing_account_revenue',
+ shipment=self.rec_name,
+ product=product.rec_name))
+ return invoice_line
+
+ def _get_shipment_cost(self):
+ pool = Pool()
+ Currency = pool.get('currency.currency')
+ cost = super()._get_shipment_cost()
+ methods = {
+ m.sale.shipment_cost_method for m in self.outgoing_moves if m.sale}
+ if methods == {None}:
+ cost += self.cost_used or 0
+ if 'shipment' in methods:
+ if self.cost_sale:
+ cost_sale = Currency.compute(
+ self.cost_sale_currency, self.cost_sale,
+ self.company.currency, round=False)
+ else:
+ cost_sale = 0
+ delta = cost_sale - (self.cost_used or 0)
+ if delta < 0:
+ cost -= delta
+ if 'order' in methods and self.cost_used:
+ sales = {
+ m.sale for m in self.outgoing_moves
+ if m.sale and m.sale.shipment_cost_method == 'order'}
+ for sale in sales:
+ shipment_cost = sum(
+ (s.cost_used or 0) for s in sale.shipments
+ if s.state == 'done' and s != self)
+ cost_sale = sale.shipment_cost_amount
+ if cost_sale < shipment_cost:
+ cost += self.cost_used or 0
+ elif cost_sale < shipment_cost + (self.cost_used or 0):
+ cost += shipment_cost + self.cost_used - cost_sale
+ return cost
+
+ @classmethod
+ @ModelView.button
+ @Workflow.transition('done')
+ def done(cls, shipments):
+ for shipment in shipments:
+ shipment.cost = shipment.cost_used
+ shipment.cost_sale = shipment.cost_sale_used
+ shipment.cost_sale_currency = shipment.cost_sale_currency_used
+ cls.save(shipments)
+ super().done(shipments)
+
+ @classmethod
+ @ModelView.button
+ @Workflow.transition('cancelled')
+ def cancel(cls, shipments):
+ for shipment in shipments:
+ shipment.cost = None
+ shipment.cost_sale = None
+ shipment.cost_sale_currency = None
+ cls.save(shipments)
+ super().cancel(shipments)
diff --git a/modules/sale_shipment_cost/stock.xml b/modules/sale_shipment_cost/stock.xml
new file mode 100644
index 0000000000..0c4d3fa790
--- /dev/null
+++ b/modules/sale_shipment_cost/stock.xml
@@ -0,0 +1,19 @@
+
+
+
+
+
+ stock.shipment.out
+
+
+ shipment_out_form
+
+
+
+ stock.shipment.out
+
+ shipment_out_list
+
+
+
diff --git a/modules/sale_shipment_cost/tests/__init__.py b/modules/sale_shipment_cost/tests/__init__.py
new file mode 100644
index 0000000000..c83de5cf53
--- /dev/null
+++ b/modules/sale_shipment_cost/tests/__init__.py
@@ -0,0 +1,9 @@
+# This file is part of Tryton. The COPYRIGHT file at the top level of
+# this repository contains the full copyright notices and license terms.
+
+try:
+ from trytond.modules.sale_shipment_cost.tests.test_sale_shipment_cost import suite # noqa: E501
+except ImportError:
+ from .test_sale_shipment_cost import suite
+
+__all__ = ['suite']
diff --git a/modules/sale_shipment_cost/tests/scenario_sale_shipment_cost.rst b/modules/sale_shipment_cost/tests/scenario_sale_shipment_cost.rst
new file mode 100644
index 0000000000..1d2b29237d
--- /dev/null
+++ b/modules/sale_shipment_cost/tests/scenario_sale_shipment_cost.rst
@@ -0,0 +1,333 @@
+===========================
+Sale Shipment Cost Scenario
+===========================
+
+Imports::
+
+ >>> import datetime
+ >>> from dateutil.relativedelta import relativedelta
+ >>> from decimal import Decimal
+ >>> from proteus import Model, Wizard
+ >>> from trytond.tests.tools import activate_modules
+ >>> from trytond.modules.company.tests.tools import create_company, \
+ ... get_company
+ >>> from trytond.modules.account.tests.tools import create_fiscalyear, \
+ ... create_chart, get_accounts
+ >>> from trytond.modules.account_invoice.tests.tools import \
+ ... set_fiscalyear_invoice_sequences, create_payment_term
+ >>> today = datetime.date.today()
+
+Activate modules::
+
+ >>> config = activate_modules([
+ ... 'sale_shipment_cost',
+ ... 'sale',
+ ... 'account_invoice',
+ ... ])
+
+Create company::
+
+ >>> _ = create_company()
+ >>> company = get_company()
+
+Create fiscal year::
+
+ >>> fiscalyear = set_fiscalyear_invoice_sequences(
+ ... create_fiscalyear(company))
+ >>> fiscalyear.click('create_period')
+
+Create chart of accounts::
+
+ >>> _ = create_chart(company)
+ >>> accounts = get_accounts(company)
+ >>> revenue = accounts['revenue']
+ >>> expense = accounts['expense']
+
+Create customer::
+
+ >>> Party = Model.get('party.party')
+ >>> customer = Party(name='Customer')
+ >>> customer.save()
+
+Create account category::
+
+ >>> ProductCategory = Model.get('product.category')
+ >>> account_category = ProductCategory(name="Account Category")
+ >>> account_category.accounting = True
+ >>> account_category.account_revenue = revenue
+ >>> account_category.save()
+
+Create product::
+
+ >>> ProductUom = Model.get('product.uom')
+ >>> ProductTemplate = Model.get('product.template')
+ >>> unit, = ProductUom.find([('name', '=', 'Unit')])
+
+ >>> template = ProductTemplate()
+ >>> template.name = 'Product'
+ >>> template.default_uom = unit
+ >>> template.type = 'goods'
+ >>> template.salable = True
+ >>> template.lead_time = datetime.timedelta(0)
+ >>> template.list_price = Decimal('20')
+ >>> template.account_category = account_category
+ >>> template.save()
+ >>> product, = template.products
+
+ >>> carrier_template = ProductTemplate()
+ >>> carrier_template.name = 'Carrier Product'
+ >>> carrier_template.default_uom = unit
+ >>> carrier_template.type = 'service'
+ >>> carrier_template.salable = True
+ >>> carrier_template.lead_time = datetime.timedelta(0)
+ >>> carrier_template.list_price = Decimal('3')
+ >>> carrier_template.account_category = account_category
+ >>> carrier_template.save()
+ >>> carrier_product, = carrier_template.products
+ >>> carrier_product.cost_price = Decimal('2')
+ >>> carrier_product.save()
+
+Create carrier::
+
+ >>> Carrier = Model.get('carrier')
+ >>> carrier = Carrier()
+ >>> party = Party(name='Carrier')
+ >>> party.save()
+ >>> carrier.party = party
+ >>> carrier.carrier_product = carrier_product
+ >>> carrier.save()
+
+Use it as the default carrier::
+
+ >>> CarrierSelection = Model.get('carrier.selection')
+ >>> csc = CarrierSelection(carrier=carrier)
+ >>> csc.save()
+
+Create payment term::
+
+ >>> payment_term = create_payment_term()
+ >>> payment_term.save()
+
+Sale products with cost on shipment::
+
+ >>> Sale = Model.get('sale.sale')
+ >>> sale = Sale()
+ >>> sale.party = customer
+ >>> sale.carrier = carrier
+ >>> sale.payment_term = payment_term
+ >>> sale.invoice_method = 'shipment'
+ >>> sale.shipment_cost_method = 'shipment'
+ >>> sale_line = sale.lines.new()
+ >>> sale_line.product = product
+ >>> sale_line.quantity = 5.0
+ >>> sale.click('quote')
+ >>> cost_line = sale.lines[-1]
+ >>> cost_line.product == carrier_product
+ True
+ >>> cost_line.quantity
+ 1.0
+ >>> cost_line.amount
+ Decimal('3.00')
+ >>> sale.click('confirm')
+ >>> sale.click('process')
+ >>> sale.state
+ 'processing'
+ >>> sale.untaxed_amount
+ Decimal('103.00')
+
+Send products::
+
+ >>> ShipmentOut = Model.get('stock.shipment.out')
+ >>> shipment, = sale.shipments
+ >>> shipment.carrier == carrier
+ True
+ >>> shipment.cost_used
+ Decimal('2.0000')
+ >>> shipment.cost_sale_used
+ Decimal('3.0000')
+ >>> shipment.cost_sale_currency_used == company.currency
+ True
+ >>> move, = shipment.inventory_moves
+ >>> move.quantity = 4
+ >>> shipment.cost_sale_used
+ Decimal('3.0000')
+ >>> shipment.cost_sale_currency_used == company.currency
+ True
+ >>> shipment.state
+ 'waiting'
+ >>> shipment.click('assign_force')
+ >>> shipment.state
+ 'assigned'
+ >>> shipment.click('pick')
+ >>> shipment.state
+ 'picked'
+ >>> shipment.click('pack')
+ >>> shipment.state
+ 'packed'
+ >>> shipment.click('done')
+ >>> shipment.state
+ 'done'
+
+Check customer invoice::
+
+ >>> sale.reload()
+ >>> invoice, = sale.invoices
+ >>> sorted([l.product.id for l in invoice.lines]) == \
+ ... sorted([product.id, carrier_product.id])
+ True
+ >>> invoice.untaxed_amount
+ Decimal('83.00')
+
+Send missing products::
+
+ >>> sale.reload()
+ >>> shipment, = [s for s in sale.shipments if s.state == 'waiting']
+ >>> shipment.click('assign_force')
+ >>> shipment.click('pick')
+ >>> shipment.click('pack')
+ >>> shipment.click('done')
+ >>> sale.reload()
+ >>> len(sale.invoices)
+ 2
+ >>> new_invoice, = [i for i in sale.invoices if i != invoice]
+ >>> new_invoice.untaxed_amount
+ Decimal('23.00')
+
+Sale products with cost on order::
+
+ >>> sale = Sale()
+ >>> sale.party = customer
+ >>> sale.carrier = carrier
+ >>> sale.payment_term = payment_term
+ >>> sale.invoice_method = 'order'
+ >>> sale.shipment_cost_method = 'order'
+ >>> sale_line = sale.lines.new()
+ >>> sale_line.product = product
+ >>> sale_line.quantity = 3.0
+ >>> sale.click('quote')
+ >>> cost_line = sale.lines[-1]
+ >>> cost_line.product == carrier_product
+ True
+ >>> cost_line.quantity
+ 1.0
+ >>> cost_line.amount
+ Decimal('3.00')
+ >>> sale.click('confirm')
+ >>> sale.click('process')
+ >>> sale.state
+ 'processing'
+ >>> sale.untaxed_amount
+ Decimal('63.00')
+
+Check customer shipment::
+
+ >>> shipment, = sale.shipments
+ >>> shipment.carrier == carrier
+ True
+
+Check customer invoice::
+
+ >>> sale.reload()
+ >>> invoice, = sale.invoices
+ >>> invoice.untaxed_amount
+ Decimal('63.00')
+
+Return the sale::
+
+ >>> return_sale = Wizard('sale.return_sale', [sale])
+ >>> return_sale.execute('return_')
+ >>> returned_sale, = Sale.find([
+ ... ('state', '=', 'draft'),
+ ... ])
+ >>> returned_sale.untaxed_amount
+ Decimal('-63.00')
+
+The quotation of the returned sale does not change the amount::
+
+ >>> returned_sale.click('quote')
+ >>> returned_sale.untaxed_amount
+ Decimal('-63.00')
+
+Sale products with cost on order and invoice method on shipment::
+
+ >>> sale = Sale()
+ >>> sale.party = customer
+ >>> sale.carrier = carrier
+ >>> sale.payment_term = payment_term
+ >>> sale.invoice_method = 'shipment'
+ >>> sale.shipment_cost_method = 'order'
+ >>> sale_line = sale.lines.new()
+ >>> sale_line.product = product
+ >>> sale_line.quantity = 1.0
+ >>> sale.click('quote')
+ >>> sale.click('confirm')
+ >>> sale.click('process')
+ >>> sale.state
+ 'processing'
+
+Check no customer invoice::
+
+ >>> len(sale.invoices)
+ 0
+
+Send products::
+
+ >>> shipment, = sale.shipments
+ >>> shipment.click('assign_force')
+ >>> shipment.click('pick')
+ >>> shipment.click('pack')
+ >>> shipment.click('done')
+ >>> shipment.state
+ 'done'
+
+Check customer invoice::
+
+ >>> sale.reload()
+ >>> invoice, = sale.invoices
+ >>> len(invoice.lines)
+ 2
+
+Sale products with no cost::
+
+ >>> sale = Sale()
+ >>> sale.party = customer
+ >>> sale.carrier = carrier
+ >>> sale.payment_term = payment_term
+ >>> sale.invoice_method = 'shipment'
+ >>> sale.shipment_cost_method = None
+ >>> sale_line = sale.lines.new()
+ >>> sale_line.product = product
+ >>> sale_line.quantity = 1.0
+ >>> sale.click('quote')
+ >>> len(sale.lines)
+ 1
+ >>> sale.click('confirm')
+ >>> sale.click('process')
+ >>> sale.state
+ 'processing'
+
+Check no customer invoice::
+
+ >>> len(sale.invoices)
+ 0
+
+Send products::
+
+ >>> shipment, = sale.shipments
+ >>> shipment.cost_used
+ Decimal('2.0000')
+ >>> shipment.cost_sale_used
+ Decimal('3.0000')
+ >>> shipment.click('assign_force')
+ >>> shipment.click('pick')
+ >>> shipment.click('pack')
+ >>> shipment.click('done')
+ >>> shipment.state
+ 'done'
+
+Check customer invoice::
+
+ >>> sale.reload()
+ >>> invoice, = sale.invoices
+ >>> len(invoice.lines)
+ 1
diff --git a/modules/sale_shipment_cost/tests/scenario_sale_shipment_cost_modify_price.rst b/modules/sale_shipment_cost/tests/scenario_sale_shipment_cost_modify_price.rst
new file mode 100644
index 0000000000..5df93eeaf2
--- /dev/null
+++ b/modules/sale_shipment_cost/tests/scenario_sale_shipment_cost_modify_price.rst
@@ -0,0 +1,116 @@
+========================================
+Sale Shipment Cost Modify Price Scenario
+========================================
+
+Imports::
+
+ >>> from decimal import Decimal
+ >>> from proteus import Model
+ >>> from trytond.tests.tools import activate_modules
+ >>> from trytond.modules.company.tests.tools import (
+ ... create_company, get_company)
+
+Activate modules::
+
+ >>> config = activate_modules('sale_shipment_cost')
+
+Create company::
+
+ >>> _ = create_company()
+ >>> company = get_company()
+
+Create customer::
+
+ >>> Party = Model.get('party.party')
+ >>> customer = Party(name='Customer')
+ >>> customer.save()
+
+Create account category::
+
+ >>> ProductCategory = Model.get('product.category')
+ >>> account_category = ProductCategory(name="Account Category")
+ >>> account_category.accounting = True
+ >>> account_category.save()
+
+Create product::
+
+ >>> ProductUom = Model.get('product.uom')
+ >>> ProductTemplate = Model.get('product.template')
+ >>> unit, = ProductUom.find([('name', '=', 'Unit')])
+
+ >>> template = ProductTemplate()
+ >>> template.name = 'Product'
+ >>> template.default_uom = unit
+ >>> template.type = 'goods'
+ >>> template.salable = True
+ >>> template.list_price = Decimal('20')
+ >>> template.account_category = account_category
+ >>> template.save()
+ >>> product, = template.products
+
+ >>> carrier_template = ProductTemplate()
+ >>> carrier_template.name = 'Carrier Product'
+ >>> carrier_template.default_uom = unit
+ >>> carrier_template.type = 'service'
+ >>> carrier_template.salable = True
+ >>> carrier_template.list_price = Decimal('3')
+ >>> carrier_template.account_category = account_category
+ >>> carrier_template.save()
+ >>> carrier_product, = carrier_template.products
+
+Create carrier::
+
+ >>> Carrier = Model.get('carrier')
+ >>> carrier = Carrier()
+ >>> party = Party(name='Carrier')
+ >>> party.save()
+ >>> carrier.party = party
+ >>> carrier.carrier_product = carrier_product
+ >>> carrier.save()
+
+Make a quote::
+
+ >>> Sale = Model.get('sale.sale')
+ >>> sale = Sale()
+ >>> sale.party = customer
+ >>> sale.carrier = carrier
+ >>> sale_line = sale.lines.new()
+ >>> sale_line.product = product
+ >>> sale_line.quantity = 5.0
+ >>> sale.click('quote')
+ >>> cost_line = sale.lines[-1]
+ >>> cost_line.product == carrier_product
+ True
+ >>> cost_line.quantity
+ 1.0
+ >>> cost_line.amount
+ Decimal('3.00')
+
+Change the shipment cost price::
+
+ >>> sale.click('draft')
+ >>> cost_line = sale.lines[-1]
+ >>> cost_line.unit_price = Decimal('2.00')
+ >>> sale.click('quote')
+ >>> cost_line = sale.lines[-1]
+ >>> cost_line.product == carrier_product
+ True
+ >>> cost_line.quantity
+ 1.0
+ >>> cost_line.amount
+ Decimal('2.00')
+
+Change the carrier price reset the cost line::
+
+ >>> carrier_template.list_price = Decimal('4')
+ >>> carrier_template.save()
+
+ >>> sale.click('draft')
+ >>> sale.click('quote')
+ >>> cost_line = sale.lines[-1]
+ >>> cost_line.product == carrier_product
+ True
+ >>> cost_line.quantity
+ 1.0
+ >>> cost_line.amount
+ Decimal('4.00')
diff --git a/modules/sale_shipment_cost/tests/scenario_sale_shipment_cost_promotion.rst b/modules/sale_shipment_cost/tests/scenario_sale_shipment_cost_promotion.rst
new file mode 100644
index 0000000000..fc7aa7f30a
--- /dev/null
+++ b/modules/sale_shipment_cost/tests/scenario_sale_shipment_cost_promotion.rst
@@ -0,0 +1,122 @@
+=====================================
+Sale Shipment Cost Promotion Scenario
+=====================================
+
+Imports::
+
+ >>> import datetime
+ >>> from dateutil.relativedelta import relativedelta
+ >>> from decimal import Decimal
+ >>> from proteus import Model, Wizard
+ >>> from trytond.tests.tools import activate_modules
+ >>> from trytond.modules.company.tests.tools import create_company, \
+ ... get_company
+ >>> from trytond.modules.account.tests.tools import create_fiscalyear, \
+ ... create_chart, get_accounts
+ >>> from trytond.modules.account_invoice.tests.tools import \
+ ... set_fiscalyear_invoice_sequences, create_payment_term
+ >>> today = datetime.date.today()
+
+Activate modules::
+
+ >>> config = activate_modules([
+ ... 'sale_shipment_cost',
+ ... 'sale',
+ ... 'sale_promotion',
+ ... ])
+
+Create company::
+
+ >>> _ = create_company()
+ >>> company = get_company()
+
+Create chart of accounts::
+
+ >>> _ = create_chart(company)
+ >>> accounts = get_accounts(company)
+
+Create customer::
+
+ >>> Party = Model.get('party.party')
+ >>> customer = Party(name='Customer')
+ >>> customer.save()
+
+Create account category::
+
+ >>> ProductCategory = Model.get('product.category')
+ >>> account_category = ProductCategory(name="Account Category")
+ >>> account_category.accounting = True
+ >>> account_category.account_revenue = accounts['revenue']
+ >>> account_category.save()
+
+Create product::
+
+ >>> ProductUom = Model.get('product.uom')
+ >>> ProductTemplate = Model.get('product.template')
+ >>> Product = Model.get('product.product')
+ >>> unit, = ProductUom.find([('name', '=', 'Unit')])
+
+ >>> template = ProductTemplate()
+ >>> template.name = 'Product'
+ >>> template.default_uom = unit
+ >>> template.type = 'goods'
+ >>> template.salable = True
+ >>> template.list_price = Decimal('20')
+ >>> template.account_category = account_category
+ >>> template.save()
+ >>> product, = template.products
+
+ >>> carrier_template = ProductTemplate()
+ >>> carrier_template.name = 'Carrier Product'
+ >>> carrier_template.default_uom = unit
+ >>> carrier_template.type = 'service'
+ >>> carrier_template.salable = True
+ >>> carrier_template.list_price = Decimal('3')
+ >>> carrier_template.account_category = account_category
+ >>> carrier_template.save()
+ >>> carrier_product, = carrier_template.products
+
+Create Promotion::
+
+ >>> Promotion = Model.get('sale.promotion')
+ >>> promotion = Promotion(name='product 2 free')
+ >>> promotion.amount = Decimal('101')
+ >>> promotion.amount_shipment_cost_included = False
+ >>> promotion.currency = company.currency
+ >>> promotion.products.extend([Product(carrier_product.id)])
+ >>> promotion.formula = '0.0'
+ >>> promotion.save()
+
+Create carrier::
+
+ >>> Carrier = Model.get('carrier')
+ >>> carrier = Carrier()
+ >>> party = Party(name='Carrier')
+ >>> party.save()
+ >>> carrier.party = party
+ >>> carrier.carrier_product = carrier_product
+ >>> carrier.save()
+
+Sale products without the promotion::
+
+ >>> Sale = Model.get('sale.sale')
+ >>> sale = Sale()
+ >>> sale.party = customer
+ >>> sale.carrier = carrier
+ >>> sale_line = sale.lines.new()
+ >>> sale_line.product = product
+ >>> sale_line.quantity = 5.0
+ >>> sale.click('quote')
+ >>> cost_line = sale.lines[-1]
+ >>> cost_line.amount
+ Decimal('3.00')
+
+Increase sale to get the promotion::
+
+ >>> sale.click('draft')
+ >>> line = sale.lines[0]
+ >>> line.quantity = 6.0
+ >>> sale.click('quote')
+ >>> cost_line = sale.lines[-1]
+ >>> cost_line.amount
+ Decimal('0.00')
diff --git a/modules/sale_shipment_cost/tests/scenario_sale_shipment_cost_stock.rst b/modules/sale_shipment_cost/tests/scenario_sale_shipment_cost_stock.rst
new file mode 100644
index 0000000000..6c3a881c76
--- /dev/null
+++ b/modules/sale_shipment_cost/tests/scenario_sale_shipment_cost_stock.rst
@@ -0,0 +1,190 @@
+=================================
+Sale Shipment Cost Stock Scenario
+=================================
+
+Imports::
+
+ >>> from decimal import Decimal
+ >>> from proteus import Model
+ >>> from trytond.tests.tools import activate_modules
+ >>> from trytond.modules.company.tests.tools import (
+ ... create_company, get_company)
+ >>> from trytond.modules.account.tests.tools import (
+ ... create_chart, get_accounts)
+
+Activate modules::
+
+ >>> config = activate_modules([
+ ... 'sale_shipment_cost',
+ ... 'sale',
+ ... 'stock_shipment_cost',
+ ... ])
+
+ >>> Carrier = Model.get('carrier')
+ >>> CarrierSelection = Model.get('carrier.selection')
+ >>> Party = Model.get('party.party')
+ >>> ProductCategory = Model.get('product.category')
+ >>> ProductTemplate = Model.get('product.template')
+ >>> ProductUom = Model.get('product.uom')
+ >>> Sale = Model.get('sale.sale')
+ >>> ShipmentOut = Model.get('stock.shipment.out')
+
+Create company::
+
+ >>> _ = create_company()
+ >>> company = get_company()
+
+Create chart of accounts::
+
+ >>> _ = create_chart(company)
+ >>> accounts = get_accounts(company)
+
+Create customer::
+
+ >>> customer = Party(name='Customer')
+ >>> customer.save()
+
+Create account category::
+
+ >>> account_category = ProductCategory(name="Account Category")
+ >>> account_category.accounting = True
+ >>> account_category.account_revenue = accounts['revenue']
+ >>> account_category.save()
+
+Create product::
+
+ >>> unit, = ProductUom.find([('name', '=', 'Unit')])
+
+ >>> template = ProductTemplate()
+ >>> template.name = 'Product'
+ >>> template.default_uom = unit
+ >>> template.type = 'goods'
+ >>> template.salable = True
+ >>> template.list_price = Decimal('20')
+ >>> template.account_category = account_category
+ >>> template.save()
+ >>> product, = template.products
+
+ >>> carrier_template = ProductTemplate()
+ >>> carrier_template.name = 'Carrier Product'
+ >>> carrier_template.default_uom = unit
+ >>> carrier_template.type = 'service'
+ >>> carrier_template.salable = True
+ >>> carrier_template.list_price = Decimal('2')
+ >>> carrier_template.account_category = account_category
+ >>> carrier_template.save()
+ >>> carrier_product, = carrier_template.products
+ >>> carrier_product.cost_price = Decimal('5')
+ >>> carrier_product.save()
+
+Create carrier::
+
+ >>> carrier = Carrier()
+ >>> party = Party(name='Carrier')
+ >>> party.save()
+ >>> carrier.party = party
+ >>> carrier.carrier_product = carrier_product
+ >>> carrier.save()
+
+Use it as the default carrier::
+
+ >>> csc = CarrierSelection(carrier=carrier)
+ >>> csc.save()
+
+
+Sell product with no shipment cost::
+
+ >>> sale = Sale()
+ >>> sale.party = customer
+ >>> sale.carrier = carrier
+ >>> sale.shipment_cost_method = None
+ >>> line = sale.lines.new()
+ >>> line.product = product
+ >>> line.quantity = 1
+ >>> sale.click('quote')
+ >>> len(sale.lines)
+ 1
+ >>> sale.click('confirm')
+ >>> sale.click('process')
+ >>> sale.state
+ 'processing'
+
+ >>> shipment, = sale.shipments
+ >>> shipment.cost_used
+ Decimal('5.0000')
+ >>> shipment.click('assign_force')
+ >>> shipment.click('pick')
+ >>> shipment.click('pack')
+ >>> shipment.click('done')
+ >>> shipment.state
+ 'done'
+ >>> move, = shipment.outgoing_moves
+ >>> move.shipment_out_cost_price
+ Decimal('5.0000')
+
+Sell product with cost on shipment::
+
+ >>> sale = Sale()
+ >>> sale.party = customer
+ >>> sale.carrier = carrier
+ >>> sale.shipment_cost_method = 'shipment'
+ >>> line = sale.lines.new()
+ >>> line.product = product
+ >>> line.quantity = 1
+ >>> sale.click('quote')
+ >>> len(sale.lines)
+ 2
+ >>> sale.click('confirm')
+ >>> sale.click('process')
+ >>> sale.state
+ 'processing'
+
+ >>> shipment, = sale.shipments
+ >>> shipment.cost_used
+ Decimal('5.0000')
+ >>> shipment.cost_sale_used
+ Decimal('2.0000')
+ >>> shipment.click('assign_force')
+ >>> shipment.click('pick')
+ >>> shipment.click('pack')
+ >>> shipment.click('done')
+ >>> shipment.state
+ 'done'
+ >>> move, = shipment.outgoing_moves
+ >>> move.shipment_out_cost_price
+ Decimal('3.0000')
+
+Sell product with cost on order::
+
+ >>> sale = Sale()
+ >>> sale.party = customer
+ >>> sale.carrier = carrier
+ >>> sale.shipment_cost_method = 'order'
+ >>> line = sale.lines.new()
+ >>> line.product = product
+ >>> line.quantity = 1
+ >>> sale.click('quote')
+ >>> len(sale.lines)
+ 2
+ >>> sale.click('draft')
+ >>> sale.lines[-1].unit_price = Decimal('3.0000')
+ >>> sale.click('quote')
+ >>> sale.lines[-1].unit_price
+ Decimal('3.0000')
+ >>> sale.click('confirm')
+ >>> sale.click('process')
+ >>> sale.state
+ 'processing'
+
+ >>> shipment, = sale.shipments
+ >>> shipment.cost_used
+ Decimal('5.0000')
+ >>> shipment.click('assign_force')
+ >>> shipment.click('pick')
+ >>> shipment.click('pack')
+ >>> shipment.click('done')
+ >>> shipment.state
+ 'done'
+ >>> move, = shipment.outgoing_moves
+ >>> move.shipment_out_cost_price
+ Decimal('2.0000')
diff --git a/modules/sale_shipment_cost/tests/test_sale_shipment_cost.py b/modules/sale_shipment_cost/tests/test_sale_shipment_cost.py
new file mode 100644
index 0000000000..e8f5886d3a
--- /dev/null
+++ b/modules/sale_shipment_cost/tests/test_sale_shipment_cost.py
@@ -0,0 +1,40 @@
+# This file is part of Tryton. The COPYRIGHT file at the top level of
+# this repository contains the full copyright notices and license terms.
+import unittest
+import doctest
+import trytond.tests.test_tryton
+from trytond.tests.test_tryton import ModuleTestCase
+from trytond.tests.test_tryton import doctest_teardown
+from trytond.tests.test_tryton import doctest_checker
+
+
+class SaleShipmentCostTestCase(ModuleTestCase):
+ 'Test Sale Shipment Cost module'
+ module = 'sale_shipment_cost'
+ extras = ['sale_promotion']
+
+
+def suite():
+ suite = trytond.tests.test_tryton.suite()
+ suite.addTests(unittest.TestLoader().loadTestsFromTestCase(
+ SaleShipmentCostTestCase))
+ suite.addTests(doctest.DocFileSuite('scenario_sale_shipment_cost.rst',
+ tearDown=doctest_teardown, encoding='utf-8',
+ checker=doctest_checker,
+ optionflags=doctest.REPORT_ONLY_FIRST_FAILURE))
+ suite.addTests(doctest.DocFileSuite(
+ 'scenario_sale_shipment_cost_modify_price.rst',
+ tearDown=doctest_teardown, encoding='utf-8',
+ checker=doctest_checker,
+ optionflags=doctest.REPORT_ONLY_FIRST_FAILURE))
+ suite.addTests(doctest.DocFileSuite(
+ 'scenario_sale_shipment_cost_promotion.rst',
+ tearDown=doctest_teardown, encoding='utf-8',
+ checker=doctest_checker,
+ optionflags=doctest.REPORT_ONLY_FIRST_FAILURE))
+ suite.addTests(doctest.DocFileSuite(
+ 'scenario_sale_shipment_cost_stock.rst',
+ tearDown=doctest_teardown, encoding='utf-8',
+ checker=doctest_checker,
+ optionflags=doctest.REPORT_ONLY_FIRST_FAILURE))
+ return suite
diff --git a/modules/sale_shipment_cost/tox.ini b/modules/sale_shipment_cost/tox.ini
new file mode 100644
index 0000000000..197496c0cb
--- /dev/null
+++ b/modules/sale_shipment_cost/tox.ini
@@ -0,0 +1,15 @@
+[tox]
+envlist = {py36,py37,py38,py39}-{sqlite,postgresql},pypy3-{sqlite,postgresql}
+
+[testenv]
+commands = {envpython} setup.py test
+deps =
+ {py36,py37,py38,py39}-postgresql: psycopg2 >= 2.5
+ pypy3-postgresql: psycopg2cffi >= 2.5
+ py36-sqlite: sqlitebck
+setenv =
+ sqlite: TRYTOND_DATABASE_URI={env:SQLITE_URI:sqlite://}
+ postgresql: TRYTOND_DATABASE_URI={env:POSTGRESQL_URI:postgresql://}
+ sqlite: DB_NAME={env:SQLITE_NAME::memory:}
+ postgresql: DB_NAME={env:POSTGRESQL_NAME:test}
+install_command = pip install --pre --find-links https://trydevpi.tryton.org/?local_version={env:CI_JOB_ID:{env:CI_BUILD_NUMBER}.{env:CI_JOB_NUMBER}} {opts} {packages}
diff --git a/modules/sale_shipment_cost/tryton.cfg b/modules/sale_shipment_cost/tryton.cfg
new file mode 100644
index 0000000000..db4848a145
--- /dev/null
+++ b/modules/sale_shipment_cost/tryton.cfg
@@ -0,0 +1,18 @@
+[tryton]
+version=6.0.5
+depends:
+ account_invoice
+ carrier
+ currency
+ ir
+ product
+ res
+ sale
+ stock
+extras_depend:
+ sale_promotion
+ stock_shipment_cost
+xml:
+ sale.xml
+ stock.xml
+ message.xml
diff --git a/modules/sale_shipment_cost/view/configuration_form.xml b/modules/sale_shipment_cost/view/configuration_form.xml
new file mode 100644
index 0000000000..3deae196f8
--- /dev/null
+++ b/modules/sale_shipment_cost/view/configuration_form.xml
@@ -0,0 +1,9 @@
+
+
+
+
+
+
+
+
diff --git a/modules/sale_shipment_cost/view/promotion_form.xml b/modules/sale_shipment_cost/view/promotion_form.xml
new file mode 100644
index 0000000000..67d5e46326
--- /dev/null
+++ b/modules/sale_shipment_cost/view/promotion_form.xml
@@ -0,0 +1,9 @@
+
+
+
+
+
+
+
+
diff --git a/modules/sale_shipment_cost/view/sale_form.xml b/modules/sale_shipment_cost/view/sale_form.xml
new file mode 100644
index 0000000000..3f16667126
--- /dev/null
+++ b/modules/sale_shipment_cost/view/sale_form.xml
@@ -0,0 +1,16 @@
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/modules/sale_shipment_cost/view/sale_line_tree_sequence.xml b/modules/sale_shipment_cost/view/sale_line_tree_sequence.xml
new file mode 100644
index 0000000000..07430f101a
--- /dev/null
+++ b/modules/sale_shipment_cost/view/sale_line_tree_sequence.xml
@@ -0,0 +1,8 @@
+
+
+
+
+
+
+
diff --git a/modules/sale_shipment_cost/view/shipment_out_form.xml b/modules/sale_shipment_cost/view/shipment_out_form.xml
new file mode 100644
index 0000000000..2c47f20b21
--- /dev/null
+++ b/modules/sale_shipment_cost/view/shipment_out_form.xml
@@ -0,0 +1,22 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/modules/sale_shipment_cost/view/shipment_out_list.xml b/modules/sale_shipment_cost/view/shipment_out_list.xml
new file mode 100644
index 0000000000..2e517974d1
--- /dev/null
+++ b/modules/sale_shipment_cost/view/shipment_out_list.xml
@@ -0,0 +1,8 @@
+
+
+
+
+
+
+
diff --git a/modules/sale_shipment_grouping/.drone.yml b/modules/sale_shipment_grouping/.drone.yml
new file mode 100644
index 0000000000..2049d30a49
--- /dev/null
+++ b/modules/sale_shipment_grouping/.drone.yml
@@ -0,0 +1,68 @@
+clone:
+ hg:
+ image: plugins/hg
+ environment:
+ - HG_SHARE_POOL=/root/.cache/hg
+ volumes:
+ - cache:/root/.cache
+
+pipeline:
+ tox:
+ image: ${IMAGE}
+ environment:
+ - CFLAGS=-O0
+ - DB_CACHE=/cache
+ - TOX_TESTENV_PASSENV=CFLAGS DB_CACHE CI_BUILD_NUMBER CI_JOB_NUMBER CI_JOB_ID
+ - POSTGRESQL_URI=postgresql://postgres@postgresql:5432/
+ commands:
+ - echo "[extensions]" >> /root/.hgrc
+ - echo "hgext.share =" >> /root/.hgrc
+ - echo "[share]" >> /root/.hgrc
+ - echo "pool = /root/.cache/hg" >> /root/.hgrc
+ - pip install tox
+ - tox -e "${TOXENV}-${DATABASE}"
+ volumes:
+ - cache:/root/.cache
+ check_dist:
+ image: ${IMAGE}
+ commands:
+ - pip install twine
+ - python setup.py sdist
+ - twine check dist/*
+
+services:
+ postgresql:
+ image: postgres
+ environment:
+ - POSTGRES_HOST_AUTH_METHOD=trust
+ command: "-c fsync=off -c synchronous_commit=off -c full_page_writes=off"
+ when:
+ matrix:
+ DATABASE: postgresql
+
+matrix:
+ include:
+ - IMAGE: python:3.6
+ TOXENV: py36
+ DATABASE: sqlite
+ - IMAGE: python:3.6
+ TOXENV: py36
+ DATABASE: postgresql
+ - IMAGE: python:3.7
+ TOXENV: py37
+ DATABASE: sqlite
+ - IMAGE: python:3.7
+ TOXENV: py37
+ DATABASE: postgresql
+ - IMAGE: python:3.8
+ TOXENV: py38
+ DATABASE: sqlite
+ - IMAGE: python:3.8
+ TOXENV: py38
+ DATABASE: postgresql
+ - IMAGE: python:3.9
+ TOXENV: py39
+ DATABASE: sqlite
+ - IMAGE: python:3.9
+ TOXENV: py39
+ DATABASE: postgresql
diff --git a/modules/sale_shipment_grouping/.flake8 b/modules/sale_shipment_grouping/.flake8
new file mode 100644
index 0000000000..fa6b4f66d1
--- /dev/null
+++ b/modules/sale_shipment_grouping/.flake8
@@ -0,0 +1,2 @@
+[flake8]
+ignore=E123,E124,E126,E128,E741,W503
diff --git a/modules/sale_shipment_grouping/CHANGELOG b/modules/sale_shipment_grouping/CHANGELOG
new file mode 100644
index 0000000000..10f5e1317f
--- /dev/null
+++ b/modules/sale_shipment_grouping/CHANGELOG
@@ -0,0 +1,48 @@
+Version 6.0.0 - 2021-05-03
+* Bug fixes (see mercurial logs for details)
+
+Version 5.8.0 - 2020-11-02
+* Bug fixes (see mercurial logs for details)
+* Remove support for Python 3.5
+
+Version 5.6.0 - 2020-05-04
+* Bug fixes (see mercurial logs for details)
+
+Version 5.4.0 - 2019-11-04
+* Bug fixes (see mercurial logs for details)
+
+Version 5.2.0 - 2019-05-06
+* Bug fixes (see mercurial logs for details)
+
+Version 5.0.0 - 2018-10-01
+* Bug fixes (see mercurial logs for details)
+* Remove support for Python 2.7
+
+Version 4.8.0 - 2018-04-23
+* Bug fixes (see mercurial logs for details)
+
+Version 4.6.0 - 2017-10-30
+* Bug fixes (see mercurial logs for details)
+* Add default shipment grouping method
+
+Version 4.4.0 - 2017-05-01
+* Bug fixes (see mercurial logs for details)
+
+Version 4.2.0 - 2016-11-28
+* Bug fixes (see mercurial logs for details)
+
+Version 4.0.0 - 2016-05-02
+* Bug fixes (see mercurial logs for details)
+* Add Python3 support
+
+Version 3.8.0 - 2015-11-02
+* Bug fixes (see mercurial logs for details)
+
+Version 3.6.0 - 2015-04-20
+* Bug fixes (see mercurial logs for details)
+* Add support for PyPy
+Version 3.4.0 - 2014-10-20
+* Bug fixes (see mercurial logs for details)
+
+Version 3.2.0 - 2014-04-21
+* Initial release
diff --git a/modules/sale_shipment_grouping/COPYRIGHT b/modules/sale_shipment_grouping/COPYRIGHT
new file mode 100644
index 0000000000..1ef72414d6
--- /dev/null
+++ b/modules/sale_shipment_grouping/COPYRIGHT
@@ -0,0 +1,15 @@
+Copyright (C) 2014-2017 Nicolas Évrard.
+Copyright (C) 2014-2021 B2CK SPRL.
+
+This program is free software: you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation, either version 3 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program. If not, see .
diff --git a/modules/sale_shipment_grouping/LICENSE b/modules/sale_shipment_grouping/LICENSE
new file mode 100644
index 0000000000..94a9ed024d
--- /dev/null
+++ b/modules/sale_shipment_grouping/LICENSE
@@ -0,0 +1,674 @@
+ GNU GENERAL PUBLIC LICENSE
+ Version 3, 29 June 2007
+
+ Copyright (C) 2007 Free Software Foundation, Inc.
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+ Preamble
+
+ The GNU General Public License is a free, copyleft license for
+software and other kinds of works.
+
+ The licenses for most software and other practical works are designed
+to take away your freedom to share and change the works. By contrast,
+the GNU General Public License is intended to guarantee your freedom to
+share and change all versions of a program--to make sure it remains free
+software for all its users. We, the Free Software Foundation, use the
+GNU General Public License for most of our software; it applies also to
+any other work released this way by its authors. You can apply it to
+your programs, too.
+
+ When we speak of free software, we are referring to freedom, not
+price. Our General Public Licenses are designed to make sure that you
+have the freedom to distribute copies of free software (and charge for
+them if you wish), that you receive source code or can get it if you
+want it, that you can change the software or use pieces of it in new
+free programs, and that you know you can do these things.
+
+ To protect your rights, we need to prevent others from denying you
+these rights or asking you to surrender the rights. Therefore, you have
+certain responsibilities if you distribute copies of the software, or if
+you modify it: responsibilities to respect the freedom of others.
+
+ For example, if you distribute copies of such a program, whether
+gratis or for a fee, you must pass on to the recipients the same
+freedoms that you received. You must make sure that they, too, receive
+or can get the source code. And you must show them these terms so they
+know their rights.
+
+ Developers that use the GNU GPL protect your rights with two steps:
+(1) assert copyright on the software, and (2) offer you this License
+giving you legal permission to copy, distribute and/or modify it.
+
+ For the developers' and authors' protection, the GPL clearly explains
+that there is no warranty for this free software. For both users' and
+authors' sake, the GPL requires that modified versions be marked as
+changed, so that their problems will not be attributed erroneously to
+authors of previous versions.
+
+ Some devices are designed to deny users access to install or run
+modified versions of the software inside them, although the manufacturer
+can do so. This is fundamentally incompatible with the aim of
+protecting users' freedom to change the software. The systematic
+pattern of such abuse occurs in the area of products for individuals to
+use, which is precisely where it is most unacceptable. Therefore, we
+have designed this version of the GPL to prohibit the practice for those
+products. If such problems arise substantially in other domains, we
+stand ready to extend this provision to those domains in future versions
+of the GPL, as needed to protect the freedom of users.
+
+ Finally, every program is threatened constantly by software patents.
+States should not allow patents to restrict development and use of
+software on general-purpose computers, but in those that do, we wish to
+avoid the special danger that patents applied to a free program could
+make it effectively proprietary. To prevent this, the GPL assures that
+patents cannot be used to render the program non-free.
+
+ The precise terms and conditions for copying, distribution and
+modification follow.
+
+ TERMS AND CONDITIONS
+
+ 0. Definitions.
+
+ "This License" refers to version 3 of the GNU General Public License.
+
+ "Copyright" also means copyright-like laws that apply to other kinds of
+works, such as semiconductor masks.
+
+ "The Program" refers to any copyrightable work licensed under this
+License. Each licensee is addressed as "you". "Licensees" and
+"recipients" may be individuals or organizations.
+
+ To "modify" a work means to copy from or adapt all or part of the work
+in a fashion requiring copyright permission, other than the making of an
+exact copy. The resulting work is called a "modified version" of the
+earlier work or a work "based on" the earlier work.
+
+ A "covered work" means either the unmodified Program or a work based
+on the Program.
+
+ To "propagate" a work means to do anything with it that, without
+permission, would make you directly or secondarily liable for
+infringement under applicable copyright law, except executing it on a
+computer or modifying a private copy. Propagation includes copying,
+distribution (with or without modification), making available to the
+public, and in some countries other activities as well.
+
+ To "convey" a work means any kind of propagation that enables other
+parties to make or receive copies. Mere interaction with a user through
+a computer network, with no transfer of a copy, is not conveying.
+
+ An interactive user interface displays "Appropriate Legal Notices"
+to the extent that it includes a convenient and prominently visible
+feature that (1) displays an appropriate copyright notice, and (2)
+tells the user that there is no warranty for the work (except to the
+extent that warranties are provided), that licensees may convey the
+work under this License, and how to view a copy of this License. If
+the interface presents a list of user commands or options, such as a
+menu, a prominent item in the list meets this criterion.
+
+ 1. Source Code.
+
+ The "source code" for a work means the preferred form of the work
+for making modifications to it. "Object code" means any non-source
+form of a work.
+
+ A "Standard Interface" means an interface that either is an official
+standard defined by a recognized standards body, or, in the case of
+interfaces specified for a particular programming language, one that
+is widely used among developers working in that language.
+
+ The "System Libraries" of an executable work include anything, other
+than the work as a whole, that (a) is included in the normal form of
+packaging a Major Component, but which is not part of that Major
+Component, and (b) serves only to enable use of the work with that
+Major Component, or to implement a Standard Interface for which an
+implementation is available to the public in source code form. A
+"Major Component", in this context, means a major essential component
+(kernel, window system, and so on) of the specific operating system
+(if any) on which the executable work runs, or a compiler used to
+produce the work, or an object code interpreter used to run it.
+
+ The "Corresponding Source" for a work in object code form means all
+the source code needed to generate, install, and (for an executable
+work) run the object code and to modify the work, including scripts to
+control those activities. However, it does not include the work's
+System Libraries, or general-purpose tools or generally available free
+programs which are used unmodified in performing those activities but
+which are not part of the work. For example, Corresponding Source
+includes interface definition files associated with source files for
+the work, and the source code for shared libraries and dynamically
+linked subprograms that the work is specifically designed to require,
+such as by intimate data communication or control flow between those
+subprograms and other parts of the work.
+
+ The Corresponding Source need not include anything that users
+can regenerate automatically from other parts of the Corresponding
+Source.
+
+ The Corresponding Source for a work in source code form is that
+same work.
+
+ 2. Basic Permissions.
+
+ All rights granted under this License are granted for the term of
+copyright on the Program, and are irrevocable provided the stated
+conditions are met. This License explicitly affirms your unlimited
+permission to run the unmodified Program. The output from running a
+covered work is covered by this License only if the output, given its
+content, constitutes a covered work. This License acknowledges your
+rights of fair use or other equivalent, as provided by copyright law.
+
+ You may make, run and propagate covered works that you do not
+convey, without conditions so long as your license otherwise remains
+in force. You may convey covered works to others for the sole purpose
+of having them make modifications exclusively for you, or provide you
+with facilities for running those works, provided that you comply with
+the terms of this License in conveying all material for which you do
+not control copyright. Those thus making or running the covered works
+for you must do so exclusively on your behalf, under your direction
+and control, on terms that prohibit them from making any copies of
+your copyrighted material outside their relationship with you.
+
+ Conveying under any other circumstances is permitted solely under
+the conditions stated below. Sublicensing is not allowed; section 10
+makes it unnecessary.
+
+ 3. Protecting Users' Legal Rights From Anti-Circumvention Law.
+
+ No covered work shall be deemed part of an effective technological
+measure under any applicable law fulfilling obligations under article
+11 of the WIPO copyright treaty adopted on 20 December 1996, or
+similar laws prohibiting or restricting circumvention of such
+measures.
+
+ When you convey a covered work, you waive any legal power to forbid
+circumvention of technological measures to the extent such circumvention
+is effected by exercising rights under this License with respect to
+the covered work, and you disclaim any intention to limit operation or
+modification of the work as a means of enforcing, against the work's
+users, your or third parties' legal rights to forbid circumvention of
+technological measures.
+
+ 4. Conveying Verbatim Copies.
+
+ You may convey verbatim copies of the Program's source code as you
+receive it, in any medium, provided that you conspicuously and
+appropriately publish on each copy an appropriate copyright notice;
+keep intact all notices stating that this License and any
+non-permissive terms added in accord with section 7 apply to the code;
+keep intact all notices of the absence of any warranty; and give all
+recipients a copy of this License along with the Program.
+
+ You may charge any price or no price for each copy that you convey,
+and you may offer support or warranty protection for a fee.
+
+ 5. Conveying Modified Source Versions.
+
+ You may convey a work based on the Program, or the modifications to
+produce it from the Program, in the form of source code under the
+terms of section 4, provided that you also meet all of these conditions:
+
+ a) The work must carry prominent notices stating that you modified
+ it, and giving a relevant date.
+
+ b) The work must carry prominent notices stating that it is
+ released under this License and any conditions added under section
+ 7. This requirement modifies the requirement in section 4 to
+ "keep intact all notices".
+
+ c) You must license the entire work, as a whole, under this
+ License to anyone who comes into possession of a copy. This
+ License will therefore apply, along with any applicable section 7
+ additional terms, to the whole of the work, and all its parts,
+ regardless of how they are packaged. This License gives no
+ permission to license the work in any other way, but it does not
+ invalidate such permission if you have separately received it.
+
+ d) If the work has interactive user interfaces, each must display
+ Appropriate Legal Notices; however, if the Program has interactive
+ interfaces that do not display Appropriate Legal Notices, your
+ work need not make them do so.
+
+ A compilation of a covered work with other separate and independent
+works, which are not by their nature extensions of the covered work,
+and which are not combined with it such as to form a larger program,
+in or on a volume of a storage or distribution medium, is called an
+"aggregate" if the compilation and its resulting copyright are not
+used to limit the access or legal rights of the compilation's users
+beyond what the individual works permit. Inclusion of a covered work
+in an aggregate does not cause this License to apply to the other
+parts of the aggregate.
+
+ 6. Conveying Non-Source Forms.
+
+ You may convey a covered work in object code form under the terms
+of sections 4 and 5, provided that you also convey the
+machine-readable Corresponding Source under the terms of this License,
+in one of these ways:
+
+ a) Convey the object code in, or embodied in, a physical product
+ (including a physical distribution medium), accompanied by the
+ Corresponding Source fixed on a durable physical medium
+ customarily used for software interchange.
+
+ b) Convey the object code in, or embodied in, a physical product
+ (including a physical distribution medium), accompanied by a
+ written offer, valid for at least three years and valid for as
+ long as you offer spare parts or customer support for that product
+ model, to give anyone who possesses the object code either (1) a
+ copy of the Corresponding Source for all the software in the
+ product that is covered by this License, on a durable physical
+ medium customarily used for software interchange, for a price no
+ more than your reasonable cost of physically performing this
+ conveying of source, or (2) access to copy the
+ Corresponding Source from a network server at no charge.
+
+ c) Convey individual copies of the object code with a copy of the
+ written offer to provide the Corresponding Source. This
+ alternative is allowed only occasionally and noncommercially, and
+ only if you received the object code with such an offer, in accord
+ with subsection 6b.
+
+ d) Convey the object code by offering access from a designated
+ place (gratis or for a charge), and offer equivalent access to the
+ Corresponding Source in the same way through the same place at no
+ further charge. You need not require recipients to copy the
+ Corresponding Source along with the object code. If the place to
+ copy the object code is a network server, the Corresponding Source
+ may be on a different server (operated by you or a third party)
+ that supports equivalent copying facilities, provided you maintain
+ clear directions next to the object code saying where to find the
+ Corresponding Source. Regardless of what server hosts the
+ Corresponding Source, you remain obligated to ensure that it is
+ available for as long as needed to satisfy these requirements.
+
+ e) Convey the object code using peer-to-peer transmission, provided
+ you inform other peers where the object code and Corresponding
+ Source of the work are being offered to the general public at no
+ charge under subsection 6d.
+
+ A separable portion of the object code, whose source code is excluded
+from the Corresponding Source as a System Library, need not be
+included in conveying the object code work.
+
+ A "User Product" is either (1) a "consumer product", which means any
+tangible personal property which is normally used for personal, family,
+or household purposes, or (2) anything designed or sold for incorporation
+into a dwelling. In determining whether a product is a consumer product,
+doubtful cases shall be resolved in favor of coverage. For a particular
+product received by a particular user, "normally used" refers to a
+typical or common use of that class of product, regardless of the status
+of the particular user or of the way in which the particular user
+actually uses, or expects or is expected to use, the product. A product
+is a consumer product regardless of whether the product has substantial
+commercial, industrial or non-consumer uses, unless such uses represent
+the only significant mode of use of the product.
+
+ "Installation Information" for a User Product means any methods,
+procedures, authorization keys, or other information required to install
+and execute modified versions of a covered work in that User Product from
+a modified version of its Corresponding Source. The information must
+suffice to ensure that the continued functioning of the modified object
+code is in no case prevented or interfered with solely because
+modification has been made.
+
+ If you convey an object code work under this section in, or with, or
+specifically for use in, a User Product, and the conveying occurs as
+part of a transaction in which the right of possession and use of the
+User Product is transferred to the recipient in perpetuity or for a
+fixed term (regardless of how the transaction is characterized), the
+Corresponding Source conveyed under this section must be accompanied
+by the Installation Information. But this requirement does not apply
+if neither you nor any third party retains the ability to install
+modified object code on the User Product (for example, the work has
+been installed in ROM).
+
+ The requirement to provide Installation Information does not include a
+requirement to continue to provide support service, warranty, or updates
+for a work that has been modified or installed by the recipient, or for
+the User Product in which it has been modified or installed. Access to a
+network may be denied when the modification itself materially and
+adversely affects the operation of the network or violates the rules and
+protocols for communication across the network.
+
+ Corresponding Source conveyed, and Installation Information provided,
+in accord with this section must be in a format that is publicly
+documented (and with an implementation available to the public in
+source code form), and must require no special password or key for
+unpacking, reading or copying.
+
+ 7. Additional Terms.
+
+ "Additional permissions" are terms that supplement the terms of this
+License by making exceptions from one or more of its conditions.
+Additional permissions that are applicable to the entire Program shall
+be treated as though they were included in this License, to the extent
+that they are valid under applicable law. If additional permissions
+apply only to part of the Program, that part may be used separately
+under those permissions, but the entire Program remains governed by
+this License without regard to the additional permissions.
+
+ When you convey a copy of a covered work, you may at your option
+remove any additional permissions from that copy, or from any part of
+it. (Additional permissions may be written to require their own
+removal in certain cases when you modify the work.) You may place
+additional permissions on material, added by you to a covered work,
+for which you have or can give appropriate copyright permission.
+
+ Notwithstanding any other provision of this License, for material you
+add to a covered work, you may (if authorized by the copyright holders of
+that material) supplement the terms of this License with terms:
+
+ a) Disclaiming warranty or limiting liability differently from the
+ terms of sections 15 and 16 of this License; or
+
+ b) Requiring preservation of specified reasonable legal notices or
+ author attributions in that material or in the Appropriate Legal
+ Notices displayed by works containing it; or
+
+ c) Prohibiting misrepresentation of the origin of that material, or
+ requiring that modified versions of such material be marked in
+ reasonable ways as different from the original version; or
+
+ d) Limiting the use for publicity purposes of names of licensors or
+ authors of the material; or
+
+ e) Declining to grant rights under trademark law for use of some
+ trade names, trademarks, or service marks; or
+
+ f) Requiring indemnification of licensors and authors of that
+ material by anyone who conveys the material (or modified versions of
+ it) with contractual assumptions of liability to the recipient, for
+ any liability that these contractual assumptions directly impose on
+ those licensors and authors.
+
+ All other non-permissive additional terms are considered "further
+restrictions" within the meaning of section 10. If the Program as you
+received it, or any part of it, contains a notice stating that it is
+governed by this License along with a term that is a further
+restriction, you may remove that term. If a license document contains
+a further restriction but permits relicensing or conveying under this
+License, you may add to a covered work material governed by the terms
+of that license document, provided that the further restriction does
+not survive such relicensing or conveying.
+
+ If you add terms to a covered work in accord with this section, you
+must place, in the relevant source files, a statement of the
+additional terms that apply to those files, or a notice indicating
+where to find the applicable terms.
+
+ Additional terms, permissive or non-permissive, may be stated in the
+form of a separately written license, or stated as exceptions;
+the above requirements apply either way.
+
+ 8. Termination.
+
+ You may not propagate or modify a covered work except as expressly
+provided under this License. Any attempt otherwise to propagate or
+modify it is void, and will automatically terminate your rights under
+this License (including any patent licenses granted under the third
+paragraph of section 11).
+
+ However, if you cease all violation of this License, then your
+license from a particular copyright holder is reinstated (a)
+provisionally, unless and until the copyright holder explicitly and
+finally terminates your license, and (b) permanently, if the copyright
+holder fails to notify you of the violation by some reasonable means
+prior to 60 days after the cessation.
+
+ Moreover, your license from a particular copyright holder is
+reinstated permanently if the copyright holder notifies you of the
+violation by some reasonable means, this is the first time you have
+received notice of violation of this License (for any work) from that
+copyright holder, and you cure the violation prior to 30 days after
+your receipt of the notice.
+
+ Termination of your rights under this section does not terminate the
+licenses of parties who have received copies or rights from you under
+this License. If your rights have been terminated and not permanently
+reinstated, you do not qualify to receive new licenses for the same
+material under section 10.
+
+ 9. Acceptance Not Required for Having Copies.
+
+ You are not required to accept this License in order to receive or
+run a copy of the Program. Ancillary propagation of a covered work
+occurring solely as a consequence of using peer-to-peer transmission
+to receive a copy likewise does not require acceptance. However,
+nothing other than this License grants you permission to propagate or
+modify any covered work. These actions infringe copyright if you do
+not accept this License. Therefore, by modifying or propagating a
+covered work, you indicate your acceptance of this License to do so.
+
+ 10. Automatic Licensing of Downstream Recipients.
+
+ Each time you convey a covered work, the recipient automatically
+receives a license from the original licensors, to run, modify and
+propagate that work, subject to this License. You are not responsible
+for enforcing compliance by third parties with this License.
+
+ An "entity transaction" is a transaction transferring control of an
+organization, or substantially all assets of one, or subdividing an
+organization, or merging organizations. If propagation of a covered
+work results from an entity transaction, each party to that
+transaction who receives a copy of the work also receives whatever
+licenses to the work the party's predecessor in interest had or could
+give under the previous paragraph, plus a right to possession of the
+Corresponding Source of the work from the predecessor in interest, if
+the predecessor has it or can get it with reasonable efforts.
+
+ You may not impose any further restrictions on the exercise of the
+rights granted or affirmed under this License. For example, you may
+not impose a license fee, royalty, or other charge for exercise of
+rights granted under this License, and you may not initiate litigation
+(including a cross-claim or counterclaim in a lawsuit) alleging that
+any patent claim is infringed by making, using, selling, offering for
+sale, or importing the Program or any portion of it.
+
+ 11. Patents.
+
+ A "contributor" is a copyright holder who authorizes use under this
+License of the Program or a work on which the Program is based. The
+work thus licensed is called the contributor's "contributor version".
+
+ A contributor's "essential patent claims" are all patent claims
+owned or controlled by the contributor, whether already acquired or
+hereafter acquired, that would be infringed by some manner, permitted
+by this License, of making, using, or selling its contributor version,
+but do not include claims that would be infringed only as a
+consequence of further modification of the contributor version. For
+purposes of this definition, "control" includes the right to grant
+patent sublicenses in a manner consistent with the requirements of
+this License.
+
+ Each contributor grants you a non-exclusive, worldwide, royalty-free
+patent license under the contributor's essential patent claims, to
+make, use, sell, offer for sale, import and otherwise run, modify and
+propagate the contents of its contributor version.
+
+ In the following three paragraphs, a "patent license" is any express
+agreement or commitment, however denominated, not to enforce a patent
+(such as an express permission to practice a patent or covenant not to
+sue for patent infringement). To "grant" such a patent license to a
+party means to make such an agreement or commitment not to enforce a
+patent against the party.
+
+ If you convey a covered work, knowingly relying on a patent license,
+and the Corresponding Source of the work is not available for anyone
+to copy, free of charge and under the terms of this License, through a
+publicly available network server or other readily accessible means,
+then you must either (1) cause the Corresponding Source to be so
+available, or (2) arrange to deprive yourself of the benefit of the
+patent license for this particular work, or (3) arrange, in a manner
+consistent with the requirements of this License, to extend the patent
+license to downstream recipients. "Knowingly relying" means you have
+actual knowledge that, but for the patent license, your conveying the
+covered work in a country, or your recipient's use of the covered work
+in a country, would infringe one or more identifiable patents in that
+country that you have reason to believe are valid.
+
+ If, pursuant to or in connection with a single transaction or
+arrangement, you convey, or propagate by procuring conveyance of, a
+covered work, and grant a patent license to some of the parties
+receiving the covered work authorizing them to use, propagate, modify
+or convey a specific copy of the covered work, then the patent license
+you grant is automatically extended to all recipients of the covered
+work and works based on it.
+
+ A patent license is "discriminatory" if it does not include within
+the scope of its coverage, prohibits the exercise of, or is
+conditioned on the non-exercise of one or more of the rights that are
+specifically granted under this License. You may not convey a covered
+work if you are a party to an arrangement with a third party that is
+in the business of distributing software, under which you make payment
+to the third party based on the extent of your activity of conveying
+the work, and under which the third party grants, to any of the
+parties who would receive the covered work from you, a discriminatory
+patent license (a) in connection with copies of the covered work
+conveyed by you (or copies made from those copies), or (b) primarily
+for and in connection with specific products or compilations that
+contain the covered work, unless you entered into that arrangement,
+or that patent license was granted, prior to 28 March 2007.
+
+ Nothing in this License shall be construed as excluding or limiting
+any implied license or other defenses to infringement that may
+otherwise be available to you under applicable patent law.
+
+ 12. No Surrender of Others' Freedom.
+
+ If conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License. If you cannot convey a
+covered work so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you may
+not convey it at all. For example, if you agree to terms that obligate you
+to collect a royalty for further conveying from those to whom you convey
+the Program, the only way you could satisfy both those terms and this
+License would be to refrain entirely from conveying the Program.
+
+ 13. Use with the GNU Affero General Public License.
+
+ Notwithstanding any other provision of this License, you have
+permission to link or combine any covered work with a work licensed
+under version 3 of the GNU Affero General Public License into a single
+combined work, and to convey the resulting work. The terms of this
+License will continue to apply to the part which is the covered work,
+but the special requirements of the GNU Affero General Public License,
+section 13, concerning interaction through a network will apply to the
+combination as such.
+
+ 14. Revised Versions of this License.
+
+ The Free Software Foundation may publish revised and/or new versions of
+the GNU General Public License from time to time. Such new versions will
+be similar in spirit to the present version, but may differ in detail to
+address new problems or concerns.
+
+ Each version is given a distinguishing version number. If the
+Program specifies that a certain numbered version of the GNU General
+Public License "or any later version" applies to it, you have the
+option of following the terms and conditions either of that numbered
+version or of any later version published by the Free Software
+Foundation. If the Program does not specify a version number of the
+GNU General Public License, you may choose any version ever published
+by the Free Software Foundation.
+
+ If the Program specifies that a proxy can decide which future
+versions of the GNU General Public License can be used, that proxy's
+public statement of acceptance of a version permanently authorizes you
+to choose that version for the Program.
+
+ Later license versions may give you additional or different
+permissions. However, no additional obligations are imposed on any
+author or copyright holder as a result of your choosing to follow a
+later version.
+
+ 15. Disclaimer of Warranty.
+
+ THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY
+APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT
+HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY
+OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO,
+THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM
+IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF
+ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
+
+ 16. Limitation of Liability.
+
+ IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS
+THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY
+GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE
+USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF
+DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD
+PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS),
+EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF
+SUCH DAMAGES.
+
+ 17. Interpretation of Sections 15 and 16.
+
+ If the disclaimer of warranty and limitation of liability provided
+above cannot be given local legal effect according to their terms,
+reviewing courts shall apply local law that most closely approximates
+an absolute waiver of all civil liability in connection with the
+Program, unless a warranty or assumption of liability accompanies a
+copy of the Program in return for a fee.
+
+ END OF TERMS AND CONDITIONS
+
+ How to Apply These Terms to Your New Programs
+
+ If you develop a new program, and you want it to be of the greatest
+possible use to the public, the best way to achieve this is to make it
+free software which everyone can redistribute and change under these terms.
+
+ To do so, attach the following notices to the program. It is safest
+to attach them to the start of each source file to most effectively
+state the exclusion of warranty; and each file should have at least
+the "copyright" line and a pointer to where the full notice is found.
+
+
+ Copyright (C)
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see .
+
+Also add information on how to contact you by electronic and paper mail.
+
+ If the program does terminal interaction, make it output a short
+notice like this when it starts in an interactive mode:
+
+ Copyright (C)
+ This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
+ This is free software, and you are welcome to redistribute it
+ under certain conditions; type `show c' for details.
+
+The hypothetical commands `show w' and `show c' should show the appropriate
+parts of the General Public License. Of course, your program's commands
+might be different; for a GUI interface, you would use an "about box".
+
+ You should also get your employer (if you work as a programmer) or school,
+if any, to sign a "copyright disclaimer" for the program, if necessary.
+For more information on this, and how to apply and follow the GNU GPL, see
+.
+
+ The GNU General Public License does not permit incorporating your program
+into proprietary programs. If your program is a subroutine library, you
+may consider it more useful to permit linking proprietary applications with
+the library. If this is what you want to do, use the GNU Lesser General
+Public License instead of this License. But first, please read
+.
diff --git a/modules/sale_shipment_grouping/MANIFEST.in b/modules/sale_shipment_grouping/MANIFEST.in
new file mode 100644
index 0000000000..e88b2348a3
--- /dev/null
+++ b/modules/sale_shipment_grouping/MANIFEST.in
@@ -0,0 +1,5 @@
+include CHANGELOG
+include COPYRIGHT
+include LICENSE
+include README.rst
+include doc/*
diff --git a/modules/sale_shipment_grouping/README.rst b/modules/sale_shipment_grouping/README.rst
new file mode 120000
index 0000000000..176d9c2695
--- /dev/null
+++ b/modules/sale_shipment_grouping/README.rst
@@ -0,0 +1 @@
+doc/index.rst
\ No newline at end of file
diff --git a/modules/sale_shipment_grouping/__init__.py b/modules/sale_shipment_grouping/__init__.py
new file mode 100644
index 0000000000..4df575d8a1
--- /dev/null
+++ b/modules/sale_shipment_grouping/__init__.py
@@ -0,0 +1,17 @@
+# This file is part of Tryton. The COPYRIGHT file at the top level of
+# this repository contains the full copyright notices and license terms.
+
+from trytond.pool import Pool
+from . import party
+from . import sale
+from . import configuration
+
+
+def register():
+ Pool.register(
+ party.Party,
+ party.PartySaleShipmentGroupingMethod,
+ sale.Sale,
+ configuration.Configuration,
+ configuration.ConfigurationSaleMethod,
+ module='sale_shipment_grouping', type_='model')
diff --git a/modules/sale_shipment_grouping/configuration.py b/modules/sale_shipment_grouping/configuration.py
new file mode 100644
index 0000000000..81410bd6a5
--- /dev/null
+++ b/modules/sale_shipment_grouping/configuration.py
@@ -0,0 +1,38 @@
+# This file is part of Tryton. The COPYRIGHT file at the top level of
+# this repository contains the full copyright notices and license terms.
+from trytond.model import fields
+from trytond.pool import Pool, PoolMeta
+
+sale_shipment_grouping_method = fields.Selection(
+ 'get_sale_shipment_grouping_methods', "Sale Shipment Grouping Method",
+ help="The default shipment grouping method for new customers.")
+
+
+@classmethod
+def get_sale_shipment_grouping_methods(cls):
+ pool = Pool()
+ Party = pool.get('party.party')
+ field_name = 'sale_shipment_grouping_method'
+ return Party.fields_get([field_name])[field_name]['selection']
+
+
+class Configuration(metaclass=PoolMeta):
+ __name__ = 'sale.configuration'
+
+ sale_shipment_grouping_method = fields.MultiValue(
+ sale_shipment_grouping_method)
+ get_sale_shipment_grouping_methods = get_sale_shipment_grouping_methods
+
+ @classmethod
+ def multivalue_model(cls, field):
+ pool = Pool()
+ if field == 'sale_shipment_grouping_method':
+ return pool.get('sale.configuration.sale_method')
+ return super(Configuration, cls).multivalue_model(field)
+
+
+class ConfigurationSaleMethod(metaclass=PoolMeta):
+ __name__ = 'sale.configuration.sale_method'
+
+ sale_shipment_grouping_method = sale_shipment_grouping_method
+ get_sale_shipment_grouping_methods = get_sale_shipment_grouping_methods
diff --git a/modules/sale_shipment_grouping/configuration.xml b/modules/sale_shipment_grouping/configuration.xml
new file mode 100644
index 0000000000..1be072a305
--- /dev/null
+++ b/modules/sale_shipment_grouping/configuration.xml
@@ -0,0 +1,12 @@
+
+
+
+
+
+ sale.configuration
+
+ configuration_form
+
+
+
diff --git a/modules/sale_shipment_grouping/doc/index.rst b/modules/sale_shipment_grouping/doc/index.rst
new file mode 100644
index 0000000000..17f3aec994
--- /dev/null
+++ b/modules/sale_shipment_grouping/doc/index.rst
@@ -0,0 +1,13 @@
+Sale Shipment Grouping Module
+#############################
+
+The ``sale_shipment_grouping`` module adds an option to define how stock moves
+generated from sales will be grouped.
+
+A field is added to the *Party*:
+
+- *Sale Shipment Grouping Method*: The method used when grouping stock moves.
+
+If the Standard method is used, stock moves generated will be added to the
+first matching shipment found. If no shipment matches sale attributes then a
+new one will be created.
diff --git a/modules/sale_shipment_grouping/locale/bg.po b/modules/sale_shipment_grouping/locale/bg.po
new file mode 100644
index 0000000000..94f3ed2982
--- /dev/null
+++ b/modules/sale_shipment_grouping/locale/bg.po
@@ -0,0 +1,55 @@
+#
+msgid ""
+msgstr "Content-Type: text/plain; charset=utf-8\n"
+
+msgctxt "field:party.party,sale_shipment_grouping_method:"
+msgid "Sale Shipment Grouping Method"
+msgstr ""
+
+msgctxt "field:party.party,sale_shipment_grouping_methods:"
+msgid "Sale Shipment Grouping Methods"
+msgstr ""
+
+msgctxt "field:party.party.sale_shipment_grouping_method,party:"
+msgid "Party"
+msgstr ""
+
+msgctxt ""
+"field:party.party.sale_shipment_grouping_method,sale_shipment_grouping_method:"
+msgid "Sale Shipment Grouping Method"
+msgstr ""
+
+msgctxt "field:sale.configuration,sale_shipment_grouping_method:"
+msgid "Sale Shipment Grouping Method"
+msgstr ""
+
+msgctxt "field:sale.configuration.sale_method,sale_shipment_grouping_method:"
+msgid "Sale Shipment Grouping Method"
+msgstr ""
+
+msgctxt "help:sale.configuration,sale_shipment_grouping_method:"
+msgid "The default shipment grouping method for new customers."
+msgstr ""
+
+msgctxt "help:sale.configuration.sale_method,sale_shipment_grouping_method:"
+msgid "The default shipment grouping method for new customers."
+msgstr ""
+
+msgctxt "model:party.party.sale_shipment_grouping_method,name:"
+msgid "Party Sale Shipment Grouping Method"
+msgstr ""
+
+#, fuzzy
+msgctxt "selection:party.party,sale_shipment_grouping_method:"
+msgid "None"
+msgstr "Няма"
+
+#, fuzzy
+msgctxt "selection:party.party,sale_shipment_grouping_method:"
+msgid "Standard"
+msgstr "Стандартен"
+
+#, fuzzy
+msgctxt "view:party.party:"
+msgid "Shipments"
+msgstr "Изпращания"
diff --git a/modules/sale_shipment_grouping/locale/ca.po b/modules/sale_shipment_grouping/locale/ca.po
new file mode 100644
index 0000000000..c23beffe60
--- /dev/null
+++ b/modules/sale_shipment_grouping/locale/ca.po
@@ -0,0 +1,52 @@
+#
+msgid ""
+msgstr "Content-Type: text/plain; charset=utf-8\n"
+
+msgctxt "field:party.party,sale_shipment_grouping_method:"
+msgid "Sale Shipment Grouping Method"
+msgstr "Mètode d'agrupació albarans de venda"
+
+msgctxt "field:party.party,sale_shipment_grouping_methods:"
+msgid "Sale Shipment Grouping Methods"
+msgstr "Mètodes d'agrupació albarans de venda"
+
+msgctxt "field:party.party.sale_shipment_grouping_method,party:"
+msgid "Party"
+msgstr "Tercer"
+
+msgctxt ""
+"field:party.party.sale_shipment_grouping_method,sale_shipment_grouping_method:"
+msgid "Sale Shipment Grouping Method"
+msgstr "Mètode d'agrupació albarans de venda"
+
+msgctxt "field:sale.configuration,sale_shipment_grouping_method:"
+msgid "Sale Shipment Grouping Method"
+msgstr "Mètode d'agrupació albarans de venda"
+
+msgctxt "field:sale.configuration.sale_method,sale_shipment_grouping_method:"
+msgid "Sale Shipment Grouping Method"
+msgstr "Mètode d'agrupació albarans de venda"
+
+msgctxt "help:sale.configuration,sale_shipment_grouping_method:"
+msgid "The default shipment grouping method for new customers."
+msgstr "El mètode d'agrupació per defecte per als nous clients."
+
+msgctxt "help:sale.configuration.sale_method,sale_shipment_grouping_method:"
+msgid "The default shipment grouping method for new customers."
+msgstr "El mètode d'agrupació per defecte per als nous clients."
+
+msgctxt "model:party.party.sale_shipment_grouping_method,name:"
+msgid "Party Sale Shipment Grouping Method"
+msgstr "Mètode d'agrupació albarans de venda"
+
+msgctxt "selection:party.party,sale_shipment_grouping_method:"
+msgid "None"
+msgstr "Cap"
+
+msgctxt "selection:party.party,sale_shipment_grouping_method:"
+msgid "Standard"
+msgstr "Estàndard"
+
+msgctxt "view:party.party:"
+msgid "Shipments"
+msgstr "Albarans"
diff --git a/modules/sale_shipment_grouping/locale/cs.po b/modules/sale_shipment_grouping/locale/cs.po
new file mode 100644
index 0000000000..8c00f67902
--- /dev/null
+++ b/modules/sale_shipment_grouping/locale/cs.po
@@ -0,0 +1,52 @@
+#
+msgid ""
+msgstr "Content-Type: text/plain; charset=utf-8\n"
+
+msgctxt "field:party.party,sale_shipment_grouping_method:"
+msgid "Sale Shipment Grouping Method"
+msgstr ""
+
+msgctxt "field:party.party,sale_shipment_grouping_methods:"
+msgid "Sale Shipment Grouping Methods"
+msgstr ""
+
+msgctxt "field:party.party.sale_shipment_grouping_method,party:"
+msgid "Party"
+msgstr ""
+
+msgctxt ""
+"field:party.party.sale_shipment_grouping_method,sale_shipment_grouping_method:"
+msgid "Sale Shipment Grouping Method"
+msgstr ""
+
+msgctxt "field:sale.configuration,sale_shipment_grouping_method:"
+msgid "Sale Shipment Grouping Method"
+msgstr ""
+
+msgctxt "field:sale.configuration.sale_method,sale_shipment_grouping_method:"
+msgid "Sale Shipment Grouping Method"
+msgstr ""
+
+msgctxt "help:sale.configuration,sale_shipment_grouping_method:"
+msgid "The default shipment grouping method for new customers."
+msgstr ""
+
+msgctxt "help:sale.configuration.sale_method,sale_shipment_grouping_method:"
+msgid "The default shipment grouping method for new customers."
+msgstr ""
+
+msgctxt "model:party.party.sale_shipment_grouping_method,name:"
+msgid "Party Sale Shipment Grouping Method"
+msgstr ""
+
+msgctxt "selection:party.party,sale_shipment_grouping_method:"
+msgid "None"
+msgstr ""
+
+msgctxt "selection:party.party,sale_shipment_grouping_method:"
+msgid "Standard"
+msgstr ""
+
+msgctxt "view:party.party:"
+msgid "Shipments"
+msgstr ""
diff --git a/modules/sale_shipment_grouping/locale/de.po b/modules/sale_shipment_grouping/locale/de.po
new file mode 100644
index 0000000000..ac663cb05d
--- /dev/null
+++ b/modules/sale_shipment_grouping/locale/de.po
@@ -0,0 +1,52 @@
+#
+msgid ""
+msgstr "Content-Type: text/plain; charset=utf-8\n"
+
+msgctxt "field:party.party,sale_shipment_grouping_method:"
+msgid "Sale Shipment Grouping Method"
+msgstr "Gruppierungsmethode Lieferposten (Verkauf)"
+
+msgctxt "field:party.party,sale_shipment_grouping_methods:"
+msgid "Sale Shipment Grouping Methods"
+msgstr "Gruppierungsmethode Lieferposten (Verkauf)"
+
+msgctxt "field:party.party.sale_shipment_grouping_method,party:"
+msgid "Party"
+msgstr "Partei"
+
+msgctxt ""
+"field:party.party.sale_shipment_grouping_method,sale_shipment_grouping_method:"
+msgid "Sale Shipment Grouping Method"
+msgstr "Gruppierungsmethode Lieferposten (Verkauf)"
+
+msgctxt "field:sale.configuration,sale_shipment_grouping_method:"
+msgid "Sale Shipment Grouping Method"
+msgstr "Gruppierungsmethode Lieferposten (Verkauf)"
+
+msgctxt "field:sale.configuration.sale_method,sale_shipment_grouping_method:"
+msgid "Sale Shipment Grouping Method"
+msgstr "Gruppierungsmethode Lieferposten (Verkauf)"
+
+msgctxt "help:sale.configuration,sale_shipment_grouping_method:"
+msgid "The default shipment grouping method for new customers."
+msgstr "Die Standard-Gruppierungsmethode der Lieferposten für neue Kunden."
+
+msgctxt "help:sale.configuration.sale_method,sale_shipment_grouping_method:"
+msgid "The default shipment grouping method for new customers."
+msgstr "Die Standard-Gruppierungsmethode der Lieferposten für neue Kunden."
+
+msgctxt "model:party.party.sale_shipment_grouping_method,name:"
+msgid "Party Sale Shipment Grouping Method"
+msgstr "Gruppierungsmethode Lieferposten (Verkauf)"
+
+msgctxt "selection:party.party,sale_shipment_grouping_method:"
+msgid "None"
+msgstr "Keine"
+
+msgctxt "selection:party.party,sale_shipment_grouping_method:"
+msgid "Standard"
+msgstr "Standard"
+
+msgctxt "view:party.party:"
+msgid "Shipments"
+msgstr "Lieferposten"
diff --git a/modules/sale_shipment_grouping/locale/es.po b/modules/sale_shipment_grouping/locale/es.po
new file mode 100644
index 0000000000..e77db4cd37
--- /dev/null
+++ b/modules/sale_shipment_grouping/locale/es.po
@@ -0,0 +1,54 @@
+#
+msgid ""
+msgstr "Content-Type: text/plain; charset=utf-8\n"
+
+msgctxt "field:party.party,sale_shipment_grouping_method:"
+msgid "Sale Shipment Grouping Method"
+msgstr "Método agrupación albaranes de venta"
+
+msgctxt "field:party.party,sale_shipment_grouping_methods:"
+msgid "Sale Shipment Grouping Methods"
+msgstr "Método agrupación albaranes de venta"
+
+msgctxt "field:party.party.sale_shipment_grouping_method,party:"
+msgid "Party"
+msgstr "Tercero"
+
+msgctxt ""
+"field:party.party.sale_shipment_grouping_method,sale_shipment_grouping_method:"
+msgid "Sale Shipment Grouping Method"
+msgstr "Método agrupación albaranes de venta"
+
+msgctxt "field:sale.configuration,sale_shipment_grouping_method:"
+msgid "Sale Shipment Grouping Method"
+msgstr "Método agrupación albaranes de venta"
+
+msgctxt "field:sale.configuration.sale_method,sale_shipment_grouping_method:"
+msgid "Sale Shipment Grouping Method"
+msgstr "Método agrupación albaranes de venta"
+
+msgctxt "help:sale.configuration,sale_shipment_grouping_method:"
+msgid "The default shipment grouping method for new customers."
+msgstr ""
+"El método de agrupación de albaranes por defecto para los nuevos clientes."
+
+msgctxt "help:sale.configuration.sale_method,sale_shipment_grouping_method:"
+msgid "The default shipment grouping method for new customers."
+msgstr ""
+"El método de agrupación de albaranes por defecto para los nuevos clientes."
+
+msgctxt "model:party.party.sale_shipment_grouping_method,name:"
+msgid "Party Sale Shipment Grouping Method"
+msgstr "Método agrupación albaranes de venta"
+
+msgctxt "selection:party.party,sale_shipment_grouping_method:"
+msgid "None"
+msgstr "Ninguno"
+
+msgctxt "selection:party.party,sale_shipment_grouping_method:"
+msgid "Standard"
+msgstr "Estándar"
+
+msgctxt "view:party.party:"
+msgid "Shipments"
+msgstr "Albaranes"
diff --git a/modules/sale_shipment_grouping/locale/es_419.po b/modules/sale_shipment_grouping/locale/es_419.po
new file mode 100644
index 0000000000..11da18c820
--- /dev/null
+++ b/modules/sale_shipment_grouping/locale/es_419.po
@@ -0,0 +1,52 @@
+#
+msgid ""
+msgstr "Content-Type: text/plain; charset=utf-8\n"
+
+msgctxt "field:party.party,sale_shipment_grouping_method:"
+msgid "Sale Shipment Grouping Method"
+msgstr "Método de agrupación de guías de remisión de venta"
+
+msgctxt "field:party.party,sale_shipment_grouping_methods:"
+msgid "Sale Shipment Grouping Methods"
+msgstr "Método de agrupación de guías de remisión de venta"
+
+msgctxt "field:party.party.sale_shipment_grouping_method,party:"
+msgid "Party"
+msgstr ""
+
+msgctxt ""
+"field:party.party.sale_shipment_grouping_method,sale_shipment_grouping_method:"
+msgid "Sale Shipment Grouping Method"
+msgstr "Método de agrupación de guías de remisión de venta"
+
+msgctxt "field:sale.configuration,sale_shipment_grouping_method:"
+msgid "Sale Shipment Grouping Method"
+msgstr "Método de agrupación de guías de remisión de venta"
+
+msgctxt "field:sale.configuration.sale_method,sale_shipment_grouping_method:"
+msgid "Sale Shipment Grouping Method"
+msgstr "Método de agrupación de guías de remisión de venta"
+
+msgctxt "help:sale.configuration,sale_shipment_grouping_method:"
+msgid "The default shipment grouping method for new customers."
+msgstr ""
+
+msgctxt "help:sale.configuration.sale_method,sale_shipment_grouping_method:"
+msgid "The default shipment grouping method for new customers."
+msgstr ""
+
+msgctxt "model:party.party.sale_shipment_grouping_method,name:"
+msgid "Party Sale Shipment Grouping Method"
+msgstr "Método de agrupación de guías de remisión de venta"
+
+msgctxt "selection:party.party,sale_shipment_grouping_method:"
+msgid "None"
+msgstr ""
+
+msgctxt "selection:party.party,sale_shipment_grouping_method:"
+msgid "Standard"
+msgstr ""
+
+msgctxt "view:party.party:"
+msgid "Shipments"
+msgstr "Guías de remisión"
diff --git a/modules/sale_shipment_grouping/locale/et.po b/modules/sale_shipment_grouping/locale/et.po
new file mode 100644
index 0000000000..54e58f1551
--- /dev/null
+++ b/modules/sale_shipment_grouping/locale/et.po
@@ -0,0 +1,52 @@
+#
+msgid ""
+msgstr "Content-Type: text/plain; charset=utf-8\n"
+
+msgctxt "field:party.party,sale_shipment_grouping_method:"
+msgid "Sale Shipment Grouping Method"
+msgstr "Lähetuste grupeerimise meetod"
+
+msgctxt "field:party.party,sale_shipment_grouping_methods:"
+msgid "Sale Shipment Grouping Methods"
+msgstr "Lähetuse grupeerimise meetodid"
+
+msgctxt "field:party.party.sale_shipment_grouping_method,party:"
+msgid "Party"
+msgstr "Osapool"
+
+msgctxt ""
+"field:party.party.sale_shipment_grouping_method,sale_shipment_grouping_method:"
+msgid "Sale Shipment Grouping Method"
+msgstr "Lähetuse grupeerimise meetod"
+
+msgctxt "field:sale.configuration,sale_shipment_grouping_method:"
+msgid "Sale Shipment Grouping Method"
+msgstr "Lähetuse grupeerimise meetod"
+
+msgctxt "field:sale.configuration.sale_method,sale_shipment_grouping_method:"
+msgid "Sale Shipment Grouping Method"
+msgstr "Lähetuse grupeerimise meetod"
+
+msgctxt "help:sale.configuration,sale_shipment_grouping_method:"
+msgid "The default shipment grouping method for new customers."
+msgstr "Vaikimisi lähetuse grupeerimise meetod uutele klientidele."
+
+msgctxt "help:sale.configuration.sale_method,sale_shipment_grouping_method:"
+msgid "The default shipment grouping method for new customers."
+msgstr "Vaikimisi lähetuse grupeerimise meetod uutele klientidele."
+
+msgctxt "model:party.party.sale_shipment_grouping_method,name:"
+msgid "Party Sale Shipment Grouping Method"
+msgstr "Osapoole lähetuse grupeerimise meetod"
+
+msgctxt "selection:party.party,sale_shipment_grouping_method:"
+msgid "None"
+msgstr "Mitte"
+
+msgctxt "selection:party.party,sale_shipment_grouping_method:"
+msgid "Standard"
+msgstr "Standard"
+
+msgctxt "view:party.party:"
+msgid "Shipments"
+msgstr "Lähetused"
diff --git a/modules/sale_shipment_grouping/locale/fa.po b/modules/sale_shipment_grouping/locale/fa.po
new file mode 100644
index 0000000000..7a4fae5be8
--- /dev/null
+++ b/modules/sale_shipment_grouping/locale/fa.po
@@ -0,0 +1,52 @@
+#
+msgid ""
+msgstr "Content-Type: text/plain; charset=utf-8\n"
+
+msgctxt "field:party.party,sale_shipment_grouping_method:"
+msgid "Sale Shipment Grouping Method"
+msgstr "متد گروهبندی حمل ونقل فروش"
+
+msgctxt "field:party.party,sale_shipment_grouping_methods:"
+msgid "Sale Shipment Grouping Methods"
+msgstr "متدهای گروهبندی حمل ونقل فروش"
+
+msgctxt "field:party.party.sale_shipment_grouping_method,party:"
+msgid "Party"
+msgstr "نهاد/سازمان"
+
+msgctxt ""
+"field:party.party.sale_shipment_grouping_method,sale_shipment_grouping_method:"
+msgid "Sale Shipment Grouping Method"
+msgstr "متد گروهبندی حمل ونقل فروش"
+
+msgctxt "field:sale.configuration,sale_shipment_grouping_method:"
+msgid "Sale Shipment Grouping Method"
+msgstr "متد گروهبندی حمل ونقل فروش"
+
+msgctxt "field:sale.configuration.sale_method,sale_shipment_grouping_method:"
+msgid "Sale Shipment Grouping Method"
+msgstr "متد گروهبندی حمل ونقل فروش"
+
+msgctxt "help:sale.configuration,sale_shipment_grouping_method:"
+msgid "The default shipment grouping method for new customers."
+msgstr "متد گروهبندی حمل ونقل پیش فرض برای مشتریان جدید."
+
+msgctxt "help:sale.configuration.sale_method,sale_shipment_grouping_method:"
+msgid "The default shipment grouping method for new customers."
+msgstr "متد گروهبندی حمل ونقل پیش فرض برای مشتریان جدید."
+
+msgctxt "model:party.party.sale_shipment_grouping_method,name:"
+msgid "Party Sale Shipment Grouping Method"
+msgstr "متد گروهبندی حمل ونقل فروش نهاد/سازمان"
+
+msgctxt "selection:party.party,sale_shipment_grouping_method:"
+msgid "None"
+msgstr "هیجکدام"
+
+msgctxt "selection:party.party,sale_shipment_grouping_method:"
+msgid "Standard"
+msgstr "استاندارد"
+
+msgctxt "view:party.party:"
+msgid "Shipments"
+msgstr "محموله ها"
diff --git a/modules/sale_shipment_grouping/locale/fi.po b/modules/sale_shipment_grouping/locale/fi.po
new file mode 100644
index 0000000000..8c00f67902
--- /dev/null
+++ b/modules/sale_shipment_grouping/locale/fi.po
@@ -0,0 +1,52 @@
+#
+msgid ""
+msgstr "Content-Type: text/plain; charset=utf-8\n"
+
+msgctxt "field:party.party,sale_shipment_grouping_method:"
+msgid "Sale Shipment Grouping Method"
+msgstr ""
+
+msgctxt "field:party.party,sale_shipment_grouping_methods:"
+msgid "Sale Shipment Grouping Methods"
+msgstr ""
+
+msgctxt "field:party.party.sale_shipment_grouping_method,party:"
+msgid "Party"
+msgstr ""
+
+msgctxt ""
+"field:party.party.sale_shipment_grouping_method,sale_shipment_grouping_method:"
+msgid "Sale Shipment Grouping Method"
+msgstr ""
+
+msgctxt "field:sale.configuration,sale_shipment_grouping_method:"
+msgid "Sale Shipment Grouping Method"
+msgstr ""
+
+msgctxt "field:sale.configuration.sale_method,sale_shipment_grouping_method:"
+msgid "Sale Shipment Grouping Method"
+msgstr ""
+
+msgctxt "help:sale.configuration,sale_shipment_grouping_method:"
+msgid "The default shipment grouping method for new customers."
+msgstr ""
+
+msgctxt "help:sale.configuration.sale_method,sale_shipment_grouping_method:"
+msgid "The default shipment grouping method for new customers."
+msgstr ""
+
+msgctxt "model:party.party.sale_shipment_grouping_method,name:"
+msgid "Party Sale Shipment Grouping Method"
+msgstr ""
+
+msgctxt "selection:party.party,sale_shipment_grouping_method:"
+msgid "None"
+msgstr ""
+
+msgctxt "selection:party.party,sale_shipment_grouping_method:"
+msgid "Standard"
+msgstr ""
+
+msgctxt "view:party.party:"
+msgid "Shipments"
+msgstr ""
diff --git a/modules/sale_shipment_grouping/locale/fr.po b/modules/sale_shipment_grouping/locale/fr.po
new file mode 100644
index 0000000000..53af1ce777
--- /dev/null
+++ b/modules/sale_shipment_grouping/locale/fr.po
@@ -0,0 +1,56 @@
+#
+msgid ""
+msgstr "Content-Type: text/plain; charset=utf-8\n"
+
+msgctxt "field:party.party,sale_shipment_grouping_method:"
+msgid "Sale Shipment Grouping Method"
+msgstr "Méthode de regroupement des expéditions de vente"
+
+msgctxt "field:party.party,sale_shipment_grouping_methods:"
+msgid "Sale Shipment Grouping Methods"
+msgstr "Méthodes de regroupement des expéditions de vente"
+
+msgctxt "field:party.party.sale_shipment_grouping_method,party:"
+msgid "Party"
+msgstr "Tiers"
+
+msgctxt ""
+"field:party.party.sale_shipment_grouping_method,sale_shipment_grouping_method:"
+msgid "Sale Shipment Grouping Method"
+msgstr "Méthode de regroupement des expéditions de vente"
+
+msgctxt "field:sale.configuration,sale_shipment_grouping_method:"
+msgid "Sale Shipment Grouping Method"
+msgstr "Méthode de regroupement des expéditions de vente"
+
+msgctxt "field:sale.configuration.sale_method,sale_shipment_grouping_method:"
+msgid "Sale Shipment Grouping Method"
+msgstr "Méthode de regroupement des expéditions de vente"
+
+msgctxt "help:sale.configuration,sale_shipment_grouping_method:"
+msgid "The default shipment grouping method for new customers."
+msgstr ""
+"La méthode de regroupement d'expédition par défaut pour les nouveaux "
+"clients."
+
+msgctxt "help:sale.configuration.sale_method,sale_shipment_grouping_method:"
+msgid "The default shipment grouping method for new customers."
+msgstr ""
+"La méthode de regroupement d'expédition par défaut pour les nouveaux "
+"clients."
+
+msgctxt "model:party.party.sale_shipment_grouping_method,name:"
+msgid "Party Sale Shipment Grouping Method"
+msgstr "Méthode de regroupement des expéditions de vente du tiers"
+
+msgctxt "selection:party.party,sale_shipment_grouping_method:"
+msgid "None"
+msgstr "Aucune"
+
+msgctxt "selection:party.party,sale_shipment_grouping_method:"
+msgid "Standard"
+msgstr "Standard"
+
+msgctxt "view:party.party:"
+msgid "Shipments"
+msgstr "Expéditions"
diff --git a/modules/sale_shipment_grouping/locale/hu.po b/modules/sale_shipment_grouping/locale/hu.po
new file mode 100644
index 0000000000..fdbad34471
--- /dev/null
+++ b/modules/sale_shipment_grouping/locale/hu.po
@@ -0,0 +1,56 @@
+#
+msgid ""
+msgstr "Content-Type: text/plain; charset=utf-8\n"
+
+msgctxt "field:party.party,sale_shipment_grouping_method:"
+msgid "Sale Shipment Grouping Method"
+msgstr "Szállítmányok csoportosítása"
+
+msgctxt "field:party.party,sale_shipment_grouping_methods:"
+msgid "Sale Shipment Grouping Methods"
+msgstr ""
+
+msgctxt "field:party.party.sale_shipment_grouping_method,party:"
+msgid "Party"
+msgstr "Ügyfél"
+
+msgctxt ""
+"field:party.party.sale_shipment_grouping_method,sale_shipment_grouping_method:"
+msgid "Sale Shipment Grouping Method"
+msgstr "Szállítmányok csoportosítása"
+
+msgctxt "field:sale.configuration,sale_shipment_grouping_method:"
+msgid "Sale Shipment Grouping Method"
+msgstr "Szállítmányok csoportosítása"
+
+msgctxt "field:sale.configuration.sale_method,sale_shipment_grouping_method:"
+msgid "Sale Shipment Grouping Method"
+msgstr "Szállítmányok csoportosítása"
+
+msgctxt "help:sale.configuration,sale_shipment_grouping_method:"
+msgid "The default shipment grouping method for new customers."
+msgstr ""
+"Új vevők létrehozásakor ezt a szállítmány csoportosítási módot adja meg "
+"automatikusan a rendszer."
+
+msgctxt "help:sale.configuration.sale_method,sale_shipment_grouping_method:"
+msgid "The default shipment grouping method for new customers."
+msgstr ""
+"Új vevők létrehozásakor ezt a szállítmány csoportosítási módot adja meg "
+"automatikusan a rendszer."
+
+msgctxt "model:party.party.sale_shipment_grouping_method,name:"
+msgid "Party Sale Shipment Grouping Method"
+msgstr ""
+
+msgctxt "selection:party.party,sale_shipment_grouping_method:"
+msgid "None"
+msgstr "nincs"
+
+msgctxt "selection:party.party,sale_shipment_grouping_method:"
+msgid "Standard"
+msgstr "alapértelmezett"
+
+msgctxt "view:party.party:"
+msgid "Shipments"
+msgstr "Szállítmányok"
diff --git a/modules/sale_shipment_grouping/locale/id.po b/modules/sale_shipment_grouping/locale/id.po
new file mode 100644
index 0000000000..0611a0e340
--- /dev/null
+++ b/modules/sale_shipment_grouping/locale/id.po
@@ -0,0 +1,52 @@
+#
+msgid ""
+msgstr "Content-Type: text/plain; charset=utf-8\n"
+
+msgctxt "field:party.party,sale_shipment_grouping_method:"
+msgid "Sale Shipment Grouping Method"
+msgstr ""
+
+msgctxt "field:party.party,sale_shipment_grouping_methods:"
+msgid "Sale Shipment Grouping Methods"
+msgstr ""
+
+msgctxt "field:party.party.sale_shipment_grouping_method,party:"
+msgid "Party"
+msgstr "Pihak"
+
+msgctxt ""
+"field:party.party.sale_shipment_grouping_method,sale_shipment_grouping_method:"
+msgid "Sale Shipment Grouping Method"
+msgstr ""
+
+msgctxt "field:sale.configuration,sale_shipment_grouping_method:"
+msgid "Sale Shipment Grouping Method"
+msgstr ""
+
+msgctxt "field:sale.configuration.sale_method,sale_shipment_grouping_method:"
+msgid "Sale Shipment Grouping Method"
+msgstr ""
+
+msgctxt "help:sale.configuration,sale_shipment_grouping_method:"
+msgid "The default shipment grouping method for new customers."
+msgstr ""
+
+msgctxt "help:sale.configuration.sale_method,sale_shipment_grouping_method:"
+msgid "The default shipment grouping method for new customers."
+msgstr ""
+
+msgctxt "model:party.party.sale_shipment_grouping_method,name:"
+msgid "Party Sale Shipment Grouping Method"
+msgstr ""
+
+msgctxt "selection:party.party,sale_shipment_grouping_method:"
+msgid "None"
+msgstr "Tidak ada"
+
+msgctxt "selection:party.party,sale_shipment_grouping_method:"
+msgid "Standard"
+msgstr "Standar"
+
+msgctxt "view:party.party:"
+msgid "Shipments"
+msgstr ""
diff --git a/modules/sale_shipment_grouping/locale/it.po b/modules/sale_shipment_grouping/locale/it.po
new file mode 100644
index 0000000000..cd4c7e0981
--- /dev/null
+++ b/modules/sale_shipment_grouping/locale/it.po
@@ -0,0 +1,57 @@
+#
+msgid ""
+msgstr "Content-Type: text/plain; charset=utf-8\n"
+
+msgctxt "field:party.party,sale_shipment_grouping_method:"
+msgid "Sale Shipment Grouping Method"
+msgstr "metodo di raggruppamento della spedizione"
+
+#, fuzzy
+msgctxt "field:party.party,sale_shipment_grouping_methods:"
+msgid "Sale Shipment Grouping Methods"
+msgstr "metodo di raggruppamento della spedizione "
+
+msgctxt "field:party.party.sale_shipment_grouping_method,party:"
+msgid "Party"
+msgstr ""
+
+#, fuzzy
+msgctxt ""
+"field:party.party.sale_shipment_grouping_method,sale_shipment_grouping_method:"
+msgid "Sale Shipment Grouping Method"
+msgstr "metodo di raggruppamento della spedizione "
+
+#, fuzzy
+msgctxt "field:sale.configuration,sale_shipment_grouping_method:"
+msgid "Sale Shipment Grouping Method"
+msgstr "metodo di raggruppamento della spedizione "
+
+#, fuzzy
+msgctxt "field:sale.configuration.sale_method,sale_shipment_grouping_method:"
+msgid "Sale Shipment Grouping Method"
+msgstr "metodo di raggruppamento della spedizione "
+
+msgctxt "help:sale.configuration,sale_shipment_grouping_method:"
+msgid "The default shipment grouping method for new customers."
+msgstr ""
+
+msgctxt "help:sale.configuration.sale_method,sale_shipment_grouping_method:"
+msgid "The default shipment grouping method for new customers."
+msgstr ""
+
+#, fuzzy
+msgctxt "model:party.party.sale_shipment_grouping_method,name:"
+msgid "Party Sale Shipment Grouping Method"
+msgstr "metodo di raggruppamento della spedizione "
+
+msgctxt "selection:party.party,sale_shipment_grouping_method:"
+msgid "None"
+msgstr "Nessuno"
+
+msgctxt "selection:party.party,sale_shipment_grouping_method:"
+msgid "Standard"
+msgstr "Standard"
+
+msgctxt "view:party.party:"
+msgid "Shipments"
+msgstr "Spedizioni"
diff --git a/modules/sale_shipment_grouping/locale/lo.po b/modules/sale_shipment_grouping/locale/lo.po
new file mode 100644
index 0000000000..97e794ce27
--- /dev/null
+++ b/modules/sale_shipment_grouping/locale/lo.po
@@ -0,0 +1,57 @@
+#
+msgid ""
+msgstr "Content-Type: text/plain; charset=utf-8\n"
+
+msgctxt "field:party.party,sale_shipment_grouping_method:"
+msgid "Sale Shipment Grouping Method"
+msgstr "ວິທີການໂຮມກຸ່ມການຂາຍ"
+
+#, fuzzy
+msgctxt "field:party.party,sale_shipment_grouping_methods:"
+msgid "Sale Shipment Grouping Methods"
+msgstr "ວິທີການໂຮມກຸ່ມການຂາຍ"
+
+msgctxt "field:party.party.sale_shipment_grouping_method,party:"
+msgid "Party"
+msgstr ""
+
+#, fuzzy
+msgctxt ""
+"field:party.party.sale_shipment_grouping_method,sale_shipment_grouping_method:"
+msgid "Sale Shipment Grouping Method"
+msgstr "ວິທີການໂຮມກຸ່ມການຂາຍ"
+
+#, fuzzy
+msgctxt "field:sale.configuration,sale_shipment_grouping_method:"
+msgid "Sale Shipment Grouping Method"
+msgstr "ວິທີການໂຮມກຸ່ມການຂາຍ"
+
+#, fuzzy
+msgctxt "field:sale.configuration.sale_method,sale_shipment_grouping_method:"
+msgid "Sale Shipment Grouping Method"
+msgstr "ວິທີການໂຮມກຸ່ມການຂາຍ"
+
+msgctxt "help:sale.configuration,sale_shipment_grouping_method:"
+msgid "The default shipment grouping method for new customers."
+msgstr ""
+
+msgctxt "help:sale.configuration.sale_method,sale_shipment_grouping_method:"
+msgid "The default shipment grouping method for new customers."
+msgstr ""
+
+#, fuzzy
+msgctxt "model:party.party.sale_shipment_grouping_method,name:"
+msgid "Party Sale Shipment Grouping Method"
+msgstr "ວິທີການໂຮມກຸ່ມການຂາຍ"
+
+msgctxt "selection:party.party,sale_shipment_grouping_method:"
+msgid "None"
+msgstr "ບໍ່ມີ"
+
+msgctxt "selection:party.party,sale_shipment_grouping_method:"
+msgid "Standard"
+msgstr "ມາດຕະຖານ"
+
+msgctxt "view:party.party:"
+msgid "Shipments"
+msgstr "ການຈັດສົ່ງ"
diff --git a/modules/sale_shipment_grouping/locale/lt.po b/modules/sale_shipment_grouping/locale/lt.po
new file mode 100644
index 0000000000..ce551ee519
--- /dev/null
+++ b/modules/sale_shipment_grouping/locale/lt.po
@@ -0,0 +1,52 @@
+#
+msgid ""
+msgstr "Content-Type: text/plain; charset=utf-8\n"
+
+msgctxt "field:party.party,sale_shipment_grouping_method:"
+msgid "Sale Shipment Grouping Method"
+msgstr ""
+
+msgctxt "field:party.party,sale_shipment_grouping_methods:"
+msgid "Sale Shipment Grouping Methods"
+msgstr ""
+
+msgctxt "field:party.party.sale_shipment_grouping_method,party:"
+msgid "Party"
+msgstr "Kontrahentas"
+
+msgctxt ""
+"field:party.party.sale_shipment_grouping_method,sale_shipment_grouping_method:"
+msgid "Sale Shipment Grouping Method"
+msgstr ""
+
+msgctxt "field:sale.configuration,sale_shipment_grouping_method:"
+msgid "Sale Shipment Grouping Method"
+msgstr ""
+
+msgctxt "field:sale.configuration.sale_method,sale_shipment_grouping_method:"
+msgid "Sale Shipment Grouping Method"
+msgstr ""
+
+msgctxt "help:sale.configuration,sale_shipment_grouping_method:"
+msgid "The default shipment grouping method for new customers."
+msgstr ""
+
+msgctxt "help:sale.configuration.sale_method,sale_shipment_grouping_method:"
+msgid "The default shipment grouping method for new customers."
+msgstr ""
+
+msgctxt "model:party.party.sale_shipment_grouping_method,name:"
+msgid "Party Sale Shipment Grouping Method"
+msgstr ""
+
+msgctxt "selection:party.party,sale_shipment_grouping_method:"
+msgid "None"
+msgstr ""
+
+msgctxt "selection:party.party,sale_shipment_grouping_method:"
+msgid "Standard"
+msgstr ""
+
+msgctxt "view:party.party:"
+msgid "Shipments"
+msgstr ""
diff --git a/modules/sale_shipment_grouping/locale/nl.po b/modules/sale_shipment_grouping/locale/nl.po
new file mode 100644
index 0000000000..ab06173c87
--- /dev/null
+++ b/modules/sale_shipment_grouping/locale/nl.po
@@ -0,0 +1,52 @@
+#
+msgid ""
+msgstr "Content-Type: text/plain; charset=utf-8\n"
+
+msgctxt "field:party.party,sale_shipment_grouping_method:"
+msgid "Sale Shipment Grouping Method"
+msgstr "Verkoopverzending Groeperingsmethode"
+
+msgctxt "field:party.party,sale_shipment_grouping_methods:"
+msgid "Sale Shipment Grouping Methods"
+msgstr "Verkoopverzending Groeperingsmethode"
+
+msgctxt "field:party.party.sale_shipment_grouping_method,party:"
+msgid "Party"
+msgstr "Relatie"
+
+msgctxt ""
+"field:party.party.sale_shipment_grouping_method,sale_shipment_grouping_method:"
+msgid "Sale Shipment Grouping Method"
+msgstr "Verkoopverzending Groeperingsmethode"
+
+msgctxt "field:sale.configuration,sale_shipment_grouping_method:"
+msgid "Sale Shipment Grouping Method"
+msgstr "Verkoopverzending Groeperingsmethode"
+
+msgctxt "field:sale.configuration.sale_method,sale_shipment_grouping_method:"
+msgid "Sale Shipment Grouping Method"
+msgstr "Verkoopverzending Groeperingsmethode"
+
+msgctxt "help:sale.configuration,sale_shipment_grouping_method:"
+msgid "The default shipment grouping method for new customers."
+msgstr "De standaard verzendgroeperingsmethode voor nieuwe klanten."
+
+msgctxt "help:sale.configuration.sale_method,sale_shipment_grouping_method:"
+msgid "The default shipment grouping method for new customers."
+msgstr "De standaard verzendgroeperingsmethode voor nieuwe klanten."
+
+msgctxt "model:party.party.sale_shipment_grouping_method,name:"
+msgid "Party Sale Shipment Grouping Method"
+msgstr "relatie Verkoopverzending Groeperingsmethode"
+
+msgctxt "selection:party.party,sale_shipment_grouping_method:"
+msgid "None"
+msgstr "Geen"
+
+msgctxt "selection:party.party,sale_shipment_grouping_method:"
+msgid "Standard"
+msgstr "Standaard"
+
+msgctxt "view:party.party:"
+msgid "Shipments"
+msgstr "Leveringen"
diff --git a/modules/sale_shipment_grouping/locale/pl.po b/modules/sale_shipment_grouping/locale/pl.po
new file mode 100644
index 0000000000..1acacf8580
--- /dev/null
+++ b/modules/sale_shipment_grouping/locale/pl.po
@@ -0,0 +1,52 @@
+#
+msgid ""
+msgstr "Content-Type: text/plain; charset=utf-8\n"
+
+msgctxt "field:party.party,sale_shipment_grouping_method:"
+msgid "Sale Shipment Grouping Method"
+msgstr ""
+
+msgctxt "field:party.party,sale_shipment_grouping_methods:"
+msgid "Sale Shipment Grouping Methods"
+msgstr ""
+
+msgctxt "field:party.party.sale_shipment_grouping_method,party:"
+msgid "Party"
+msgstr "Strona"
+
+msgctxt ""
+"field:party.party.sale_shipment_grouping_method,sale_shipment_grouping_method:"
+msgid "Sale Shipment Grouping Method"
+msgstr ""
+
+msgctxt "field:sale.configuration,sale_shipment_grouping_method:"
+msgid "Sale Shipment Grouping Method"
+msgstr ""
+
+msgctxt "field:sale.configuration.sale_method,sale_shipment_grouping_method:"
+msgid "Sale Shipment Grouping Method"
+msgstr ""
+
+msgctxt "help:sale.configuration,sale_shipment_grouping_method:"
+msgid "The default shipment grouping method for new customers."
+msgstr ""
+
+msgctxt "help:sale.configuration.sale_method,sale_shipment_grouping_method:"
+msgid "The default shipment grouping method for new customers."
+msgstr ""
+
+msgctxt "model:party.party.sale_shipment_grouping_method,name:"
+msgid "Party Sale Shipment Grouping Method"
+msgstr ""
+
+msgctxt "selection:party.party,sale_shipment_grouping_method:"
+msgid "None"
+msgstr "Brak"
+
+msgctxt "selection:party.party,sale_shipment_grouping_method:"
+msgid "Standard"
+msgstr "Standardowa"
+
+msgctxt "view:party.party:"
+msgid "Shipments"
+msgstr "Wysyłki"
diff --git a/modules/sale_shipment_grouping/locale/pt.po b/modules/sale_shipment_grouping/locale/pt.po
new file mode 100644
index 0000000000..3cee0c37a1
--- /dev/null
+++ b/modules/sale_shipment_grouping/locale/pt.po
@@ -0,0 +1,52 @@
+#
+msgid ""
+msgstr "Content-Type: text/plain; charset=utf-8\n"
+
+msgctxt "field:party.party,sale_shipment_grouping_method:"
+msgid "Sale Shipment Grouping Method"
+msgstr "Método de Agrupamento de Remessa de Venda"
+
+msgctxt "field:party.party,sale_shipment_grouping_methods:"
+msgid "Sale Shipment Grouping Methods"
+msgstr "Método de Agrupamento de Remessa de Venda"
+
+msgctxt "field:party.party.sale_shipment_grouping_method,party:"
+msgid "Party"
+msgstr "Pessoa"
+
+msgctxt ""
+"field:party.party.sale_shipment_grouping_method,sale_shipment_grouping_method:"
+msgid "Sale Shipment Grouping Method"
+msgstr "Método de Agrupamento de Remessa de Venda"
+
+msgctxt "field:sale.configuration,sale_shipment_grouping_method:"
+msgid "Sale Shipment Grouping Method"
+msgstr "Método de Agrupamento de Remessa de Venda"
+
+msgctxt "field:sale.configuration.sale_method,sale_shipment_grouping_method:"
+msgid "Sale Shipment Grouping Method"
+msgstr "Método de Agrupamento de Remessa de Venda"
+
+msgctxt "help:sale.configuration,sale_shipment_grouping_method:"
+msgid "The default shipment grouping method for new customers."
+msgstr "O método padrão de agrupamento de remessas para novos clientes."
+
+msgctxt "help:sale.configuration.sale_method,sale_shipment_grouping_method:"
+msgid "The default shipment grouping method for new customers."
+msgstr "O método padrão de agrupamento de remessas para novos clientes."
+
+msgctxt "model:party.party.sale_shipment_grouping_method,name:"
+msgid "Party Sale Shipment Grouping Method"
+msgstr "Método de Agrupamento de Remessa de Venda da Pessoa"
+
+msgctxt "selection:party.party,sale_shipment_grouping_method:"
+msgid "None"
+msgstr "Nenhum"
+
+msgctxt "selection:party.party,sale_shipment_grouping_method:"
+msgid "Standard"
+msgstr "Padrão"
+
+msgctxt "view:party.party:"
+msgid "Shipments"
+msgstr "Remessas"
diff --git a/modules/sale_shipment_grouping/locale/ro.po b/modules/sale_shipment_grouping/locale/ro.po
new file mode 100644
index 0000000000..45a6c45736
--- /dev/null
+++ b/modules/sale_shipment_grouping/locale/ro.po
@@ -0,0 +1,52 @@
+#
+msgid ""
+msgstr "Content-Type: text/plain; charset=utf-8\n"
+
+msgctxt "field:party.party,sale_shipment_grouping_method:"
+msgid "Sale Shipment Grouping Method"
+msgstr ""
+
+msgctxt "field:party.party,sale_shipment_grouping_methods:"
+msgid "Sale Shipment Grouping Methods"
+msgstr ""
+
+msgctxt "field:party.party.sale_shipment_grouping_method,party:"
+msgid "Party"
+msgstr "Parte"
+
+msgctxt ""
+"field:party.party.sale_shipment_grouping_method,sale_shipment_grouping_method:"
+msgid "Sale Shipment Grouping Method"
+msgstr ""
+
+msgctxt "field:sale.configuration,sale_shipment_grouping_method:"
+msgid "Sale Shipment Grouping Method"
+msgstr ""
+
+msgctxt "field:sale.configuration.sale_method,sale_shipment_grouping_method:"
+msgid "Sale Shipment Grouping Method"
+msgstr ""
+
+msgctxt "help:sale.configuration,sale_shipment_grouping_method:"
+msgid "The default shipment grouping method for new customers."
+msgstr ""
+
+msgctxt "help:sale.configuration.sale_method,sale_shipment_grouping_method:"
+msgid "The default shipment grouping method for new customers."
+msgstr ""
+
+msgctxt "model:party.party.sale_shipment_grouping_method,name:"
+msgid "Party Sale Shipment Grouping Method"
+msgstr ""
+
+msgctxt "selection:party.party,sale_shipment_grouping_method:"
+msgid "None"
+msgstr ""
+
+msgctxt "selection:party.party,sale_shipment_grouping_method:"
+msgid "Standard"
+msgstr ""
+
+msgctxt "view:party.party:"
+msgid "Shipments"
+msgstr ""
diff --git a/modules/sale_shipment_grouping/locale/ru.po b/modules/sale_shipment_grouping/locale/ru.po
new file mode 100644
index 0000000000..8118c22d56
--- /dev/null
+++ b/modules/sale_shipment_grouping/locale/ru.po
@@ -0,0 +1,55 @@
+#
+msgid ""
+msgstr "Content-Type: text/plain; charset=utf-8\n"
+
+msgctxt "field:party.party,sale_shipment_grouping_method:"
+msgid "Sale Shipment Grouping Method"
+msgstr ""
+
+msgctxt "field:party.party,sale_shipment_grouping_methods:"
+msgid "Sale Shipment Grouping Methods"
+msgstr ""
+
+msgctxt "field:party.party.sale_shipment_grouping_method,party:"
+msgid "Party"
+msgstr ""
+
+msgctxt ""
+"field:party.party.sale_shipment_grouping_method,sale_shipment_grouping_method:"
+msgid "Sale Shipment Grouping Method"
+msgstr ""
+
+msgctxt "field:sale.configuration,sale_shipment_grouping_method:"
+msgid "Sale Shipment Grouping Method"
+msgstr ""
+
+msgctxt "field:sale.configuration.sale_method,sale_shipment_grouping_method:"
+msgid "Sale Shipment Grouping Method"
+msgstr ""
+
+msgctxt "help:sale.configuration,sale_shipment_grouping_method:"
+msgid "The default shipment grouping method for new customers."
+msgstr ""
+
+msgctxt "help:sale.configuration.sale_method,sale_shipment_grouping_method:"
+msgid "The default shipment grouping method for new customers."
+msgstr ""
+
+msgctxt "model:party.party.sale_shipment_grouping_method,name:"
+msgid "Party Sale Shipment Grouping Method"
+msgstr ""
+
+#, fuzzy
+msgctxt "selection:party.party,sale_shipment_grouping_method:"
+msgid "None"
+msgstr "Отсутствует"
+
+#, fuzzy
+msgctxt "selection:party.party,sale_shipment_grouping_method:"
+msgid "Standard"
+msgstr "Стандартный"
+
+#, fuzzy
+msgctxt "view:party.party:"
+msgid "Shipments"
+msgstr "Доставка"
diff --git a/modules/sale_shipment_grouping/locale/sl.po b/modules/sale_shipment_grouping/locale/sl.po
new file mode 100644
index 0000000000..338946783e
--- /dev/null
+++ b/modules/sale_shipment_grouping/locale/sl.po
@@ -0,0 +1,54 @@
+#
+msgid ""
+msgstr "Content-Type: text/plain; charset=utf-8\n"
+
+msgctxt "field:party.party,sale_shipment_grouping_method:"
+msgid "Sale Shipment Grouping Method"
+msgstr "Način združevanja pošiljk"
+
+msgctxt "field:party.party,sale_shipment_grouping_methods:"
+msgid "Sale Shipment Grouping Methods"
+msgstr "Način združevanja pošiljk"
+
+msgctxt "field:party.party.sale_shipment_grouping_method,party:"
+msgid "Party"
+msgstr "Partner"
+
+msgctxt ""
+"field:party.party.sale_shipment_grouping_method,sale_shipment_grouping_method:"
+msgid "Sale Shipment Grouping Method"
+msgstr "Način združevanja pošiljk"
+
+#, fuzzy
+msgctxt "field:sale.configuration,sale_shipment_grouping_method:"
+msgid "Sale Shipment Grouping Method"
+msgstr "Način združevanja pošiljk"
+
+#, fuzzy
+msgctxt "field:sale.configuration.sale_method,sale_shipment_grouping_method:"
+msgid "Sale Shipment Grouping Method"
+msgstr "Način združevanja pošiljk"
+
+msgctxt "help:sale.configuration,sale_shipment_grouping_method:"
+msgid "The default shipment grouping method for new customers."
+msgstr ""
+
+msgctxt "help:sale.configuration.sale_method,sale_shipment_grouping_method:"
+msgid "The default shipment grouping method for new customers."
+msgstr ""
+
+msgctxt "model:party.party.sale_shipment_grouping_method,name:"
+msgid "Party Sale Shipment Grouping Method"
+msgstr "Način združevanja pošiljk partnerja"
+
+msgctxt "selection:party.party,sale_shipment_grouping_method:"
+msgid "None"
+msgstr "Brez"
+
+msgctxt "selection:party.party,sale_shipment_grouping_method:"
+msgid "Standard"
+msgstr "Standardno"
+
+msgctxt "view:party.party:"
+msgid "Shipments"
+msgstr "Pošiljke"
diff --git a/modules/sale_shipment_grouping/locale/tr.po b/modules/sale_shipment_grouping/locale/tr.po
new file mode 100644
index 0000000000..8c00f67902
--- /dev/null
+++ b/modules/sale_shipment_grouping/locale/tr.po
@@ -0,0 +1,52 @@
+#
+msgid ""
+msgstr "Content-Type: text/plain; charset=utf-8\n"
+
+msgctxt "field:party.party,sale_shipment_grouping_method:"
+msgid "Sale Shipment Grouping Method"
+msgstr ""
+
+msgctxt "field:party.party,sale_shipment_grouping_methods:"
+msgid "Sale Shipment Grouping Methods"
+msgstr ""
+
+msgctxt "field:party.party.sale_shipment_grouping_method,party:"
+msgid "Party"
+msgstr ""
+
+msgctxt ""
+"field:party.party.sale_shipment_grouping_method,sale_shipment_grouping_method:"
+msgid "Sale Shipment Grouping Method"
+msgstr ""
+
+msgctxt "field:sale.configuration,sale_shipment_grouping_method:"
+msgid "Sale Shipment Grouping Method"
+msgstr ""
+
+msgctxt "field:sale.configuration.sale_method,sale_shipment_grouping_method:"
+msgid "Sale Shipment Grouping Method"
+msgstr ""
+
+msgctxt "help:sale.configuration,sale_shipment_grouping_method:"
+msgid "The default shipment grouping method for new customers."
+msgstr ""
+
+msgctxt "help:sale.configuration.sale_method,sale_shipment_grouping_method:"
+msgid "The default shipment grouping method for new customers."
+msgstr ""
+
+msgctxt "model:party.party.sale_shipment_grouping_method,name:"
+msgid "Party Sale Shipment Grouping Method"
+msgstr ""
+
+msgctxt "selection:party.party,sale_shipment_grouping_method:"
+msgid "None"
+msgstr ""
+
+msgctxt "selection:party.party,sale_shipment_grouping_method:"
+msgid "Standard"
+msgstr ""
+
+msgctxt "view:party.party:"
+msgid "Shipments"
+msgstr ""
diff --git a/modules/sale_shipment_grouping/locale/zh_CN.po b/modules/sale_shipment_grouping/locale/zh_CN.po
new file mode 100644
index 0000000000..8c00f67902
--- /dev/null
+++ b/modules/sale_shipment_grouping/locale/zh_CN.po
@@ -0,0 +1,52 @@
+#
+msgid ""
+msgstr "Content-Type: text/plain; charset=utf-8\n"
+
+msgctxt "field:party.party,sale_shipment_grouping_method:"
+msgid "Sale Shipment Grouping Method"
+msgstr ""
+
+msgctxt "field:party.party,sale_shipment_grouping_methods:"
+msgid "Sale Shipment Grouping Methods"
+msgstr ""
+
+msgctxt "field:party.party.sale_shipment_grouping_method,party:"
+msgid "Party"
+msgstr ""
+
+msgctxt ""
+"field:party.party.sale_shipment_grouping_method,sale_shipment_grouping_method:"
+msgid "Sale Shipment Grouping Method"
+msgstr ""
+
+msgctxt "field:sale.configuration,sale_shipment_grouping_method:"
+msgid "Sale Shipment Grouping Method"
+msgstr ""
+
+msgctxt "field:sale.configuration.sale_method,sale_shipment_grouping_method:"
+msgid "Sale Shipment Grouping Method"
+msgstr ""
+
+msgctxt "help:sale.configuration,sale_shipment_grouping_method:"
+msgid "The default shipment grouping method for new customers."
+msgstr ""
+
+msgctxt "help:sale.configuration.sale_method,sale_shipment_grouping_method:"
+msgid "The default shipment grouping method for new customers."
+msgstr ""
+
+msgctxt "model:party.party.sale_shipment_grouping_method,name:"
+msgid "Party Sale Shipment Grouping Method"
+msgstr ""
+
+msgctxt "selection:party.party,sale_shipment_grouping_method:"
+msgid "None"
+msgstr ""
+
+msgctxt "selection:party.party,sale_shipment_grouping_method:"
+msgid "Standard"
+msgstr ""
+
+msgctxt "view:party.party:"
+msgid "Shipments"
+msgstr ""
diff --git a/modules/sale_shipment_grouping/party.py b/modules/sale_shipment_grouping/party.py
new file mode 100644
index 0000000000..2d22849167
--- /dev/null
+++ b/modules/sale_shipment_grouping/party.py
@@ -0,0 +1,59 @@
+# This file is part of Tryton. The COPYRIGHT file at the top level of this
+# repository contains the full copyright notices and license terms.
+from trytond import backend
+from trytond.model import ModelSQL, ValueMixin, fields
+from trytond.pool import PoolMeta, Pool
+from trytond.tools.multivalue import migrate_property
+
+
+class Party(metaclass=PoolMeta):
+ __name__ = 'party.party'
+
+ sale_shipment_grouping_method = fields.MultiValue(fields.Selection([
+ (None, 'None'),
+ ('standard', 'Standard'),
+ ],
+ 'Sale Shipment Grouping Method'))
+ sale_shipment_grouping_methods = fields.One2Many(
+ 'party.party.sale_shipment_grouping_method', 'party',
+ "Sale Shipment Grouping Methods")
+
+ @classmethod
+ def default_sale_shipment_grouping_method(cls, **pattern):
+ pool = Pool()
+ Configuration = pool.get('sale.configuration')
+ return Configuration(1).get_multivalue(
+ 'sale_shipment_grouping_method', **pattern)
+
+
+class PartySaleShipmentGroupingMethod(ModelSQL, ValueMixin):
+ "Party Sale Shipment Grouping Method"
+ __name__ = 'party.party.sale_shipment_grouping_method'
+ party = fields.Many2One(
+ 'party.party', "Party", ondelete='CASCADE', select=True)
+ sale_shipment_grouping_method = fields.Selection(
+ 'get_sale_shipment_grouping_methods', "Sale Shipment Grouping Method")
+
+ @classmethod
+ def __register__(cls, module_name):
+ exist = backend.TableHandler.table_exist(cls._table)
+
+ super(PartySaleShipmentGroupingMethod, cls).__register__(module_name)
+
+ if not exist:
+ cls._migrate_property([], [], [])
+
+ @classmethod
+ def _migrate_property(cls, field_names, value_names, fields):
+ field_names.append('sale_shipment_grouping_method')
+ value_names.append('sale_shipment_grouping_method')
+ migrate_property(
+ 'party.party', field_names, cls, value_names,
+ parent='party', fields=fields)
+
+ @classmethod
+ def get_sale_shipment_grouping_methods(cls):
+ pool = Pool()
+ Party = pool.get('party.party')
+ field_name = 'sale_shipment_grouping_method'
+ return Party.fields_get([field_name])[field_name]['selection']
diff --git a/modules/sale_shipment_grouping/party.xml b/modules/sale_shipment_grouping/party.xml
new file mode 100644
index 0000000000..e5c6732c93
--- /dev/null
+++ b/modules/sale_shipment_grouping/party.xml
@@ -0,0 +1,12 @@
+
+
+
+
+
+ party.party
+
+ party_form
+
+
+
diff --git a/modules/sale_shipment_grouping/sale.py b/modules/sale_shipment_grouping/sale.py
new file mode 100644
index 0000000000..a21243f9a3
--- /dev/null
+++ b/modules/sale_shipment_grouping/sale.py
@@ -0,0 +1,55 @@
+# This file is part of Tryton. The COPYRIGHT file at the top level of
+# this repository contains the full copyright notices and license terms.
+
+from trytond.pool import PoolMeta
+from trytond.transaction import Transaction
+
+
+class Sale(metaclass=PoolMeta):
+ __name__ = 'sale.sale'
+
+ @property
+ def shipment_grouping_method(self):
+ return self.party.sale_shipment_grouping_method
+
+ @property
+ def _shipment_grouping_fields(self):
+ return ('customer', 'delivery_address', 'company', 'warehouse')
+
+ def _get_grouped_shipment_planned_date(self, shipment):
+ return [('planned_date', '=', shipment.planned_date)]
+
+ def _get_grouped_shipment_order(self):
+ "Returns the order used to find shipments that should be grouped"
+ return None
+
+ def _get_grouped_shipment_domain(self, shipment):
+ "Returns a domain that will find shipments that should be grouped"
+ Shipment = shipment.__class__
+ shipment_domain = [
+ ('moves.origin', 'like', 'sale.line,%'),
+ ('state', 'in', ['draft', 'waiting']),
+ ]
+ shipment_domain += self._get_grouped_shipment_planned_date(shipment)
+ defaults = Shipment.default_get(self._shipment_grouping_fields,
+ with_rec_name=False)
+ for field in self._shipment_grouping_fields:
+ shipment_domain.append((field, '=',
+ getattr(shipment, field, defaults.get(field))))
+ return shipment_domain
+
+ def _get_shipment_sale(self, shipment_type, values):
+ transaction = Transaction()
+ context = transaction.context
+ shipment = super(Sale, self)._get_shipment_sale(shipment_type, values)
+ if (not context.get('skip_grouping', False)
+ and self.shipment_grouping_method):
+ with transaction.set_context(skip_grouping=True):
+ shipment = self._get_shipment_sale(shipment_type, values)
+ Shipment = shipment.__class__
+ domain = self._get_grouped_shipment_domain(shipment)
+ order = self._get_grouped_shipment_order()
+ grouped_shipments = Shipment.search(domain, order=order, limit=1)
+ if grouped_shipments:
+ shipment, = grouped_shipments
+ return shipment
diff --git a/modules/sale_shipment_grouping/setup.py b/modules/sale_shipment_grouping/setup.py
new file mode 100755
index 0000000000..f9b4d3e82e
--- /dev/null
+++ b/modules/sale_shipment_grouping/setup.py
@@ -0,0 +1,150 @@
+#!/usr/bin/env python3
+# This file is part of Tryton. The COPYRIGHT file at the top level of
+# this repository contains the full copyright notices and license terms.
+
+import io
+import os
+import re
+from configparser import ConfigParser
+from setuptools import setup, find_packages
+
+
+def read(fname):
+ return io.open(
+ os.path.join(os.path.dirname(__file__), fname),
+ 'r', encoding='utf-8').read()
+
+
+def get_require_version(name):
+ if minor_version % 2:
+ require = '%s >= %s.%s.dev0, < %s.%s'
+ else:
+ require = '%s >= %s.%s, < %s.%s'
+ require %= (name, major_version, minor_version,
+ major_version, minor_version + 1)
+ return require
+
+
+config = ConfigParser()
+config.read_file(open(os.path.join(os.path.dirname(__file__), 'tryton.cfg')))
+info = dict(config.items('tryton'))
+for key in ('depends', 'extras_depend', 'xml'):
+ if key in info:
+ info[key] = info[key].strip().splitlines()
+version = info.get('version', '0.0.1')
+major_version, minor_version, _ = version.split('.', 2)
+major_version = int(major_version)
+minor_version = int(minor_version)
+name = 'trytond_sale_shipment_grouping'
+
+download_url = 'http://dowloads.tryton.org/%s.%s/' % (
+ major_version, minor_version)
+if minor_version % 2:
+ version = '%s.%s.dev0' % (major_version, minor_version)
+ download_url = (
+ 'hg+http://hg.tryton.org/modules/%s#egg=%s-%s' % (
+ name[8:], name, version))
+local_version = []
+if os.environ.get('CI_JOB_ID'):
+ local_version.append(os.environ['CI_JOB_ID'])
+else:
+ for build in ['CI_BUILD_NUMBER', 'CI_JOB_NUMBER']:
+ if os.environ.get(build):
+ local_version.append(os.environ[build])
+ else:
+ local_version = []
+ break
+if local_version:
+ version += '+' + '.'.join(local_version)
+
+requires = []
+for dep in info.get('depends', []):
+ if not re.match(r'(ir|res)(\W|$)', dep):
+ requires.append(get_require_version('trytond_%s' % dep))
+requires.append(get_require_version('trytond'))
+
+tests_require = [get_require_version('proteus')]
+dependency_links = []
+if minor_version % 2:
+ dependency_links.append(
+ 'https://trydevpi.tryton.org/?local_version='
+ + '.'.join(local_version))
+
+setup(name=name,
+ version=version,
+ description='Tryton module to group sale stock moves',
+ long_description=read('README.rst'),
+ author='Tryton',
+ author_email='bugs@tryton.org',
+ url='http://www.tryton.org/',
+ download_url=download_url,
+ project_urls={
+ "Bug Tracker": 'https://bugs.tryton.org/',
+ "Documentation": 'https://docs.tryton.org/',
+ "Forum": 'https://www.tryton.org/forum',
+ "Source Code": 'https://hg.tryton.org/modules/sale_shipment_grouping',
+ },
+ keywords='tryton sale shipment grouping',
+ package_dir={'trytond.modules.sale_shipment_grouping': '.'},
+ packages=(
+ ['trytond.modules.sale_shipment_grouping']
+ + ['trytond.modules.sale_shipment_grouping.%s' % p
+ for p in find_packages()]
+ ),
+ package_data={
+ 'trytond.modules.sale_shipment_grouping': (info.get('xml', [])
+ + ['tryton.cfg', 'view/*.xml', 'locale/*.po', 'tests/*.rst']),
+ },
+ classifiers=[
+ 'Development Status :: 5 - Production/Stable',
+ 'Environment :: Plugins',
+ 'Framework :: Tryton',
+ 'Intended Audience :: Developers',
+ 'Intended Audience :: Financial and Insurance Industry',
+ 'Intended Audience :: Legal Industry',
+ 'License :: OSI Approved :: '
+ 'GNU General Public License v3 or later (GPLv3+)',
+ 'Natural Language :: Bulgarian',
+ 'Natural Language :: Catalan',
+ 'Natural Language :: Chinese (Simplified)',
+ 'Natural Language :: Czech',
+ 'Natural Language :: Dutch',
+ 'Natural Language :: English',
+ 'Natural Language :: Finnish',
+ 'Natural Language :: French',
+ 'Natural Language :: German',
+ 'Natural Language :: Hungarian',
+ 'Natural Language :: Indonesian',
+ 'Natural Language :: Italian',
+ 'Natural Language :: Persian',
+ 'Natural Language :: Polish',
+ 'Natural Language :: Portuguese (Brazilian)',
+ 'Natural Language :: Romanian',
+ 'Natural Language :: Russian',
+ 'Natural Language :: Slovenian',
+ 'Natural Language :: Spanish',
+ 'Natural Language :: Turkish',
+ 'Operating System :: OS Independent',
+ 'Programming Language :: Python :: 3',
+ 'Programming Language :: Python :: 3.6',
+ 'Programming Language :: Python :: 3.7',
+ 'Programming Language :: Python :: 3.8',
+ 'Programming Language :: Python :: 3.9',
+ 'Programming Language :: Python :: Implementation :: CPython',
+ 'Programming Language :: Python :: Implementation :: PyPy',
+ 'Topic :: Office/Business',
+ 'Topic :: Office/Business :: Financial :: Accounting',
+ ],
+ license='GPL-3',
+ python_requires='>=3.6',
+ install_requires=requires,
+ dependency_links=dependency_links,
+ zip_safe=False,
+ entry_points="""
+ [trytond.modules]
+ sale_shipment_grouping = trytond.modules.sale_shipment_grouping
+ """,
+ test_suite='tests',
+ test_loader='trytond.test_loader:Loader',
+ tests_require=tests_require,
+ )
diff --git a/modules/sale_shipment_grouping/tests/__init__.py b/modules/sale_shipment_grouping/tests/__init__.py
new file mode 100644
index 0000000000..7833f2a428
--- /dev/null
+++ b/modules/sale_shipment_grouping/tests/__init__.py
@@ -0,0 +1,9 @@
+# This file is part of Tryton. The COPYRIGHT file at the top level of
+# this repository contains the full copyright notices and license terms.
+
+try:
+ from trytond.modules.sale_shipment_grouping.tests.test_sale_shipment_grouping import suite # noqa: E501
+except ImportError:
+ from .test_sale_shipment_grouping import suite
+
+__all__ = ['suite']
diff --git a/modules/sale_shipment_grouping/tests/scenario_sale_shipment_grouping.rst b/modules/sale_shipment_grouping/tests/scenario_sale_shipment_grouping.rst
new file mode 100644
index 0000000000..9aa1888a94
--- /dev/null
+++ b/modules/sale_shipment_grouping/tests/scenario_sale_shipment_grouping.rst
@@ -0,0 +1,200 @@
+==============================
+Sale Invoice Grouping Scenario
+==============================
+
+Imports::
+
+ >>> import datetime
+ >>> from dateutil.relativedelta import relativedelta
+ >>> from decimal import Decimal
+ >>> from operator import attrgetter
+ >>> from proteus import Model, Wizard
+ >>> from trytond.tests.tools import activate_modules, set_user
+ >>> from trytond.modules.company.tests.tools import create_company, \
+ ... get_company
+ >>> from trytond.modules.account.tests.tools import create_fiscalyear, \
+ ... create_chart, get_accounts
+ >>> from trytond.modules.account_invoice.tests.tools import \
+ ... set_fiscalyear_invoice_sequences, create_payment_term
+ >>> today = datetime.date.today()
+
+Activate modules::
+
+ >>> config = activate_modules('sale_shipment_grouping')
+
+Create company::
+
+ >>> _ = create_company()
+ >>> company = get_company()
+
+Create sale user::
+
+ >>> User = Model.get('res.user')
+ >>> Group = Model.get('res.group')
+ >>> sale_user = User()
+ >>> sale_user.name = 'Sale'
+ >>> sale_user.login = 'sale'
+ >>> sale_group, = sale_user.groups.find([('name', '=', 'Sales')])
+ >>> sale_user.groups.append(sale_group)
+ >>> sale_user.save()
+
+Create stock user::
+
+ >>> stock_user = User()
+ >>> stock_user.name = 'Stock'
+ >>> stock_user.login = 'stock'
+ >>> stock_group, = Group.find([('name', '=', 'Stock')])
+ >>> stock_user.groups.append(stock_group)
+ >>> stock_user.save()
+
+Create fiscal year::
+
+ >>> fiscalyear = set_fiscalyear_invoice_sequences(
+ ... create_fiscalyear(company))
+ >>> fiscalyear.click('create_period')
+
+Create chart of accounts::
+
+ >>> _ = create_chart(company)
+ >>> accounts = get_accounts(company)
+ >>> revenue = accounts['revenue']
+ >>> expense = accounts['expense']
+
+Create parties::
+
+ >>> Party = Model.get('party.party')
+ >>> customer = Party(name='Customer')
+ >>> customer.save()
+ >>> customer_grouped = Party(name='Customer Grouped',
+ ... sale_shipment_grouping_method='standard')
+ >>> customer_grouped.save()
+
+Create account category::
+
+ >>> ProductCategory = Model.get('product.category')
+ >>> account_category = ProductCategory(name="Account Category")
+ >>> account_category.accounting = True
+ >>> account_category.account_expense = expense
+ >>> account_category.account_revenue = revenue
+ >>> account_category.save()
+
+Create product::
+
+ >>> ProductUom = Model.get('product.uom')
+ >>> unit, = ProductUom.find([('name', '=', 'Unit')])
+ >>> ProductTemplate = Model.get('product.template')
+
+ >>> template = ProductTemplate()
+ >>> template.name = 'product'
+ >>> template.default_uom = unit
+ >>> template.type = 'goods'
+ >>> template.salable = True
+ >>> template.list_price = Decimal('10')
+ >>> template.account_category = account_category
+ >>> template.save()
+ >>> product, = template.products
+
+Create payment term::
+
+ >>> payment_term = create_payment_term()
+ >>> payment_term.save()
+
+Create an inventory::
+
+ >>> set_user(stock_user)
+ >>> Inventory = Model.get('stock.inventory')
+ >>> InventoryLine = Model.get('stock.inventory.line')
+ >>> Location = Model.get('stock.location')
+ >>> storage, = Location.find([
+ ... ('code', '=', 'STO'),
+ ... ])
+ >>> inventory = Inventory()
+ >>> inventory.location = storage
+ >>> inventory_line = inventory.lines.new()
+ >>> inventory_line.product = product
+ >>> inventory_line.quantity = 100.0
+ >>> inventory_line.expected_quantity = 0.0
+ >>> inventory.click('confirm')
+ >>> inventory.state
+ 'done'
+
+Sell some products::
+
+ >>> set_user(sale_user)
+ >>> Sale = Model.get('sale.sale')
+ >>> sale = Sale()
+ >>> sale.party = customer
+ >>> sale.payment_term = payment_term
+ >>> sale.invoice_method = 'order'
+ >>> sale_line = sale.lines.new()
+ >>> sale_line.product = product
+ >>> sale_line.quantity = 2.0
+ >>> sale.click('quote')
+ >>> sale.click('confirm')
+ >>> sale.state
+ 'processing'
+
+Make another sale::
+
+ >>> sale, = Sale.duplicate([sale])
+ >>> sale.click('quote')
+ >>> sale.click('confirm')
+ >>> sale.state
+ 'processing'
+
+Check the shipments::
+
+ >>> set_user(stock_user)
+ >>> ShipmentOut = Model.get('stock.shipment.out')
+ >>> shipments = ShipmentOut.find([('customer', '=', customer.id)])
+ >>> len(shipments)
+ 2
+ >>> for shipment in shipments:
+ ... _ = shipment.click('assign_try')
+ ... shipment.click('pick')
+ ... shipment.click('pack')
+ ... shipment.click('done')
+
+Now we'll use the same scenario with the grouped customer::
+
+ >>> set_user(sale_user)
+ >>> sale = Sale()
+ >>> sale.party = customer_grouped
+ >>> sale.payment_term = payment_term
+ >>> sale.invoice_method = 'order'
+ >>> sale_line = sale.lines.new()
+ >>> sale_line.product = product
+ >>> sale_line.quantity = 1.0
+ >>> sale.click('quote')
+ >>> sale.click('confirm')
+ >>> sale.state
+ 'processing'
+
+Make another sale::
+
+ >>> sale = Sale()
+ >>> sale.party = customer_grouped
+ >>> sale.payment_term = payment_term
+ >>> sale.invoice_method = 'order'
+ >>> sale_line = sale.lines.new()
+ >>> sale_line.product = product
+ >>> sale_line.quantity = 2.0
+ >>> sale.click('quote')
+ >>> sale.click('confirm')
+ >>> sale.state
+ 'processing'
+
+Check the shipments::
+
+ >>> set_user(stock_user)
+ >>> shipments = ShipmentOut.find([
+ ... ('customer', '=', customer_grouped.id),
+ ... ('state', '=', 'waiting'),
+ ... ])
+ >>> len(shipments)
+ 1
+ >>> shipment, = shipments
+ >>> len(shipment.outgoing_moves)
+ 2
+ >>> sorted([m.quantity for m in shipment.outgoing_moves])
+ [1.0, 2.0]
diff --git a/modules/sale_shipment_grouping/tests/test_sale_shipment_grouping.py b/modules/sale_shipment_grouping/tests/test_sale_shipment_grouping.py
new file mode 100644
index 0000000000..30403cb847
--- /dev/null
+++ b/modules/sale_shipment_grouping/tests/test_sale_shipment_grouping.py
@@ -0,0 +1,24 @@
+# This file is part of Tryton. The COPYRIGHT file at the top level of
+# this repository contains the full copyright notices and license terms.
+import unittest
+import doctest
+import trytond.tests.test_tryton
+from trytond.tests.test_tryton import ModuleTestCase
+from trytond.tests.test_tryton import doctest_teardown
+from trytond.tests.test_tryton import doctest_checker
+
+
+class SaleShipmentGroupingTestCase(ModuleTestCase):
+ 'Test Sale module'
+ module = 'sale_shipment_grouping'
+
+
+def suite():
+ suite = trytond.tests.test_tryton.suite()
+ loader = unittest.TestLoader()
+ suite.addTests(loader.loadTestsFromTestCase(SaleShipmentGroupingTestCase))
+ suite.addTests(doctest.DocFileSuite('scenario_sale_shipment_grouping.rst',
+ tearDown=doctest_teardown, encoding='utf-8',
+ checker=doctest_checker,
+ optionflags=doctest.REPORT_ONLY_FIRST_FAILURE))
+ return suite
diff --git a/modules/sale_shipment_grouping/tox.ini b/modules/sale_shipment_grouping/tox.ini
new file mode 100644
index 0000000000..197496c0cb
--- /dev/null
+++ b/modules/sale_shipment_grouping/tox.ini
@@ -0,0 +1,15 @@
+[tox]
+envlist = {py36,py37,py38,py39}-{sqlite,postgresql},pypy3-{sqlite,postgresql}
+
+[testenv]
+commands = {envpython} setup.py test
+deps =
+ {py36,py37,py38,py39}-postgresql: psycopg2 >= 2.5
+ pypy3-postgresql: psycopg2cffi >= 2.5
+ py36-sqlite: sqlitebck
+setenv =
+ sqlite: TRYTOND_DATABASE_URI={env:SQLITE_URI:sqlite://}
+ postgresql: TRYTOND_DATABASE_URI={env:POSTGRESQL_URI:postgresql://}
+ sqlite: DB_NAME={env:SQLITE_NAME::memory:}
+ postgresql: DB_NAME={env:POSTGRESQL_NAME:test}
+install_command = pip install --pre --find-links https://trydevpi.tryton.org/?local_version={env:CI_JOB_ID:{env:CI_BUILD_NUMBER}.{env:CI_JOB_NUMBER}} {opts} {packages}
diff --git a/modules/sale_shipment_grouping/tryton.cfg b/modules/sale_shipment_grouping/tryton.cfg
new file mode 100644
index 0000000000..640497856c
--- /dev/null
+++ b/modules/sale_shipment_grouping/tryton.cfg
@@ -0,0 +1,11 @@
+[tryton]
+version=6.0.1
+depends:
+ ir
+ res
+ party
+ stock
+ sale
+xml:
+ party.xml
+ configuration.xml
diff --git a/modules/sale_shipment_grouping/view/configuration_form.xml b/modules/sale_shipment_grouping/view/configuration_form.xml
new file mode 100644
index 0000000000..90cac3a602
--- /dev/null
+++ b/modules/sale_shipment_grouping/view/configuration_form.xml
@@ -0,0 +1,9 @@
+
+
+
+
+
+
+
+
diff --git a/modules/sale_shipment_grouping/view/party_form.xml b/modules/sale_shipment_grouping/view/party_form.xml
new file mode 100644
index 0000000000..99d5f5aff6
--- /dev/null
+++ b/modules/sale_shipment_grouping/view/party_form.xml
@@ -0,0 +1,10 @@
+
+
+
+
+
+
+
+
+
diff --git a/modules/sale_shipment_tolerance/.drone.yml b/modules/sale_shipment_tolerance/.drone.yml
new file mode 100644
index 0000000000..2049d30a49
--- /dev/null
+++ b/modules/sale_shipment_tolerance/.drone.yml
@@ -0,0 +1,68 @@
+clone:
+ hg:
+ image: plugins/hg
+ environment:
+ - HG_SHARE_POOL=/root/.cache/hg
+ volumes:
+ - cache:/root/.cache
+
+pipeline:
+ tox:
+ image: ${IMAGE}
+ environment:
+ - CFLAGS=-O0
+ - DB_CACHE=/cache
+ - TOX_TESTENV_PASSENV=CFLAGS DB_CACHE CI_BUILD_NUMBER CI_JOB_NUMBER CI_JOB_ID
+ - POSTGRESQL_URI=postgresql://postgres@postgresql:5432/
+ commands:
+ - echo "[extensions]" >> /root/.hgrc
+ - echo "hgext.share =" >> /root/.hgrc
+ - echo "[share]" >> /root/.hgrc
+ - echo "pool = /root/.cache/hg" >> /root/.hgrc
+ - pip install tox
+ - tox -e "${TOXENV}-${DATABASE}"
+ volumes:
+ - cache:/root/.cache
+ check_dist:
+ image: ${IMAGE}
+ commands:
+ - pip install twine
+ - python setup.py sdist
+ - twine check dist/*
+
+services:
+ postgresql:
+ image: postgres
+ environment:
+ - POSTGRES_HOST_AUTH_METHOD=trust
+ command: "-c fsync=off -c synchronous_commit=off -c full_page_writes=off"
+ when:
+ matrix:
+ DATABASE: postgresql
+
+matrix:
+ include:
+ - IMAGE: python:3.6
+ TOXENV: py36
+ DATABASE: sqlite
+ - IMAGE: python:3.6
+ TOXENV: py36
+ DATABASE: postgresql
+ - IMAGE: python:3.7
+ TOXENV: py37
+ DATABASE: sqlite
+ - IMAGE: python:3.7
+ TOXENV: py37
+ DATABASE: postgresql
+ - IMAGE: python:3.8
+ TOXENV: py38
+ DATABASE: sqlite
+ - IMAGE: python:3.8
+ TOXENV: py38
+ DATABASE: postgresql
+ - IMAGE: python:3.9
+ TOXENV: py39
+ DATABASE: sqlite
+ - IMAGE: python:3.9
+ TOXENV: py39
+ DATABASE: postgresql
diff --git a/modules/sale_shipment_tolerance/.flake8 b/modules/sale_shipment_tolerance/.flake8
new file mode 100644
index 0000000000..fa6b4f66d1
--- /dev/null
+++ b/modules/sale_shipment_tolerance/.flake8
@@ -0,0 +1,2 @@
+[flake8]
+ignore=E123,E124,E126,E128,E741,W503
diff --git a/modules/sale_shipment_tolerance/CHANGELOG b/modules/sale_shipment_tolerance/CHANGELOG
new file mode 100644
index 0000000000..16ca60f18a
--- /dev/null
+++ b/modules/sale_shipment_tolerance/CHANGELOG
@@ -0,0 +1,25 @@
+Version 6.0.0 - 2021-05-03
+* Bug fixes (see mercurial logs for details)
+
+Version 5.8.0 - 2020-11-02
+* Bug fixes (see mercurial logs for details)
+* Remove support for Python 3.5
+
+Version 5.6.0 - 2020-05-04
+* Bug fixes (see mercurial logs for details)
+
+Version 5.4.0 - 2019-11-04
+* Bug fixes (see mercurial logs for details)
+
+Version 5.2.0 - 2019-05-06
+* Bug fixes (see mercurial logs for details)
+
+Version 5.0.0 - 2018-10-01
+* Bug fixes (see mercurial logs for details)
+* Remove support for Python 2.7
+
+Version 4.8.0 - 2018-04-23
+* Bug fixes (see mercurial logs for details)
+
+Version 4.6.0 - 2017-10-30
+* Initial release
diff --git a/modules/sale_shipment_tolerance/COPYRIGHT b/modules/sale_shipment_tolerance/COPYRIGHT
new file mode 100644
index 0000000000..d46f53f8f2
--- /dev/null
+++ b/modules/sale_shipment_tolerance/COPYRIGHT
@@ -0,0 +1,15 @@
+Copyright (C) 2017-2021 Cédric Krier
+Copyright (C) 2017-2021 B2CK
+
+This program is free software: you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation, either version 3 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program. If not, see .
diff --git a/modules/sale_shipment_tolerance/LICENSE b/modules/sale_shipment_tolerance/LICENSE
new file mode 100644
index 0000000000..94a9ed024d
--- /dev/null
+++ b/modules/sale_shipment_tolerance/LICENSE
@@ -0,0 +1,674 @@
+ GNU GENERAL PUBLIC LICENSE
+ Version 3, 29 June 2007
+
+ Copyright (C) 2007 Free Software Foundation, Inc.
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+ Preamble
+
+ The GNU General Public License is a free, copyleft license for
+software and other kinds of works.
+
+ The licenses for most software and other practical works are designed
+to take away your freedom to share and change the works. By contrast,
+the GNU General Public License is intended to guarantee your freedom to
+share and change all versions of a program--to make sure it remains free
+software for all its users. We, the Free Software Foundation, use the
+GNU General Public License for most of our software; it applies also to
+any other work released this way by its authors. You can apply it to
+your programs, too.
+
+ When we speak of free software, we are referring to freedom, not
+price. Our General Public Licenses are designed to make sure that you
+have the freedom to distribute copies of free software (and charge for
+them if you wish), that you receive source code or can get it if you
+want it, that you can change the software or use pieces of it in new
+free programs, and that you know you can do these things.
+
+ To protect your rights, we need to prevent others from denying you
+these rights or asking you to surrender the rights. Therefore, you have
+certain responsibilities if you distribute copies of the software, or if
+you modify it: responsibilities to respect the freedom of others.
+
+ For example, if you distribute copies of such a program, whether
+gratis or for a fee, you must pass on to the recipients the same
+freedoms that you received. You must make sure that they, too, receive
+or can get the source code. And you must show them these terms so they
+know their rights.
+
+ Developers that use the GNU GPL protect your rights with two steps:
+(1) assert copyright on the software, and (2) offer you this License
+giving you legal permission to copy, distribute and/or modify it.
+
+ For the developers' and authors' protection, the GPL clearly explains
+that there is no warranty for this free software. For both users' and
+authors' sake, the GPL requires that modified versions be marked as
+changed, so that their problems will not be attributed erroneously to
+authors of previous versions.
+
+ Some devices are designed to deny users access to install or run
+modified versions of the software inside them, although the manufacturer
+can do so. This is fundamentally incompatible with the aim of
+protecting users' freedom to change the software. The systematic
+pattern of such abuse occurs in the area of products for individuals to
+use, which is precisely where it is most unacceptable. Therefore, we
+have designed this version of the GPL to prohibit the practice for those
+products. If such problems arise substantially in other domains, we
+stand ready to extend this provision to those domains in future versions
+of the GPL, as needed to protect the freedom of users.
+
+ Finally, every program is threatened constantly by software patents.
+States should not allow patents to restrict development and use of
+software on general-purpose computers, but in those that do, we wish to
+avoid the special danger that patents applied to a free program could
+make it effectively proprietary. To prevent this, the GPL assures that
+patents cannot be used to render the program non-free.
+
+ The precise terms and conditions for copying, distribution and
+modification follow.
+
+ TERMS AND CONDITIONS
+
+ 0. Definitions.
+
+ "This License" refers to version 3 of the GNU General Public License.
+
+ "Copyright" also means copyright-like laws that apply to other kinds of
+works, such as semiconductor masks.
+
+ "The Program" refers to any copyrightable work licensed under this
+License. Each licensee is addressed as "you". "Licensees" and
+"recipients" may be individuals or organizations.
+
+ To "modify" a work means to copy from or adapt all or part of the work
+in a fashion requiring copyright permission, other than the making of an
+exact copy. The resulting work is called a "modified version" of the
+earlier work or a work "based on" the earlier work.
+
+ A "covered work" means either the unmodified Program or a work based
+on the Program.
+
+ To "propagate" a work means to do anything with it that, without
+permission, would make you directly or secondarily liable for
+infringement under applicable copyright law, except executing it on a
+computer or modifying a private copy. Propagation includes copying,
+distribution (with or without modification), making available to the
+public, and in some countries other activities as well.
+
+ To "convey" a work means any kind of propagation that enables other
+parties to make or receive copies. Mere interaction with a user through
+a computer network, with no transfer of a copy, is not conveying.
+
+ An interactive user interface displays "Appropriate Legal Notices"
+to the extent that it includes a convenient and prominently visible
+feature that (1) displays an appropriate copyright notice, and (2)
+tells the user that there is no warranty for the work (except to the
+extent that warranties are provided), that licensees may convey the
+work under this License, and how to view a copy of this License. If
+the interface presents a list of user commands or options, such as a
+menu, a prominent item in the list meets this criterion.
+
+ 1. Source Code.
+
+ The "source code" for a work means the preferred form of the work
+for making modifications to it. "Object code" means any non-source
+form of a work.
+
+ A "Standard Interface" means an interface that either is an official
+standard defined by a recognized standards body, or, in the case of
+interfaces specified for a particular programming language, one that
+is widely used among developers working in that language.
+
+ The "System Libraries" of an executable work include anything, other
+than the work as a whole, that (a) is included in the normal form of
+packaging a Major Component, but which is not part of that Major
+Component, and (b) serves only to enable use of the work with that
+Major Component, or to implement a Standard Interface for which an
+implementation is available to the public in source code form. A
+"Major Component", in this context, means a major essential component
+(kernel, window system, and so on) of the specific operating system
+(if any) on which the executable work runs, or a compiler used to
+produce the work, or an object code interpreter used to run it.
+
+ The "Corresponding Source" for a work in object code form means all
+the source code needed to generate, install, and (for an executable
+work) run the object code and to modify the work, including scripts to
+control those activities. However, it does not include the work's
+System Libraries, or general-purpose tools or generally available free
+programs which are used unmodified in performing those activities but
+which are not part of the work. For example, Corresponding Source
+includes interface definition files associated with source files for
+the work, and the source code for shared libraries and dynamically
+linked subprograms that the work is specifically designed to require,
+such as by intimate data communication or control flow between those
+subprograms and other parts of the work.
+
+ The Corresponding Source need not include anything that users
+can regenerate automatically from other parts of the Corresponding
+Source.
+
+ The Corresponding Source for a work in source code form is that
+same work.
+
+ 2. Basic Permissions.
+
+ All rights granted under this License are granted for the term of
+copyright on the Program, and are irrevocable provided the stated
+conditions are met. This License explicitly affirms your unlimited
+permission to run the unmodified Program. The output from running a
+covered work is covered by this License only if the output, given its
+content, constitutes a covered work. This License acknowledges your
+rights of fair use or other equivalent, as provided by copyright law.
+
+ You may make, run and propagate covered works that you do not
+convey, without conditions so long as your license otherwise remains
+in force. You may convey covered works to others for the sole purpose
+of having them make modifications exclusively for you, or provide you
+with facilities for running those works, provided that you comply with
+the terms of this License in conveying all material for which you do
+not control copyright. Those thus making or running the covered works
+for you must do so exclusively on your behalf, under your direction
+and control, on terms that prohibit them from making any copies of
+your copyrighted material outside their relationship with you.
+
+ Conveying under any other circumstances is permitted solely under
+the conditions stated below. Sublicensing is not allowed; section 10
+makes it unnecessary.
+
+ 3. Protecting Users' Legal Rights From Anti-Circumvention Law.
+
+ No covered work shall be deemed part of an effective technological
+measure under any applicable law fulfilling obligations under article
+11 of the WIPO copyright treaty adopted on 20 December 1996, or
+similar laws prohibiting or restricting circumvention of such
+measures.
+
+ When you convey a covered work, you waive any legal power to forbid
+circumvention of technological measures to the extent such circumvention
+is effected by exercising rights under this License with respect to
+the covered work, and you disclaim any intention to limit operation or
+modification of the work as a means of enforcing, against the work's
+users, your or third parties' legal rights to forbid circumvention of
+technological measures.
+
+ 4. Conveying Verbatim Copies.
+
+ You may convey verbatim copies of the Program's source code as you
+receive it, in any medium, provided that you conspicuously and
+appropriately publish on each copy an appropriate copyright notice;
+keep intact all notices stating that this License and any
+non-permissive terms added in accord with section 7 apply to the code;
+keep intact all notices of the absence of any warranty; and give all
+recipients a copy of this License along with the Program.
+
+ You may charge any price or no price for each copy that you convey,
+and you may offer support or warranty protection for a fee.
+
+ 5. Conveying Modified Source Versions.
+
+ You may convey a work based on the Program, or the modifications to
+produce it from the Program, in the form of source code under the
+terms of section 4, provided that you also meet all of these conditions:
+
+ a) The work must carry prominent notices stating that you modified
+ it, and giving a relevant date.
+
+ b) The work must carry prominent notices stating that it is
+ released under this License and any conditions added under section
+ 7. This requirement modifies the requirement in section 4 to
+ "keep intact all notices".
+
+ c) You must license the entire work, as a whole, under this
+ License to anyone who comes into possession of a copy. This
+ License will therefore apply, along with any applicable section 7
+ additional terms, to the whole of the work, and all its parts,
+ regardless of how they are packaged. This License gives no
+ permission to license the work in any other way, but it does not
+ invalidate such permission if you have separately received it.
+
+ d) If the work has interactive user interfaces, each must display
+ Appropriate Legal Notices; however, if the Program has interactive
+ interfaces that do not display Appropriate Legal Notices, your
+ work need not make them do so.
+
+ A compilation of a covered work with other separate and independent
+works, which are not by their nature extensions of the covered work,
+and which are not combined with it such as to form a larger program,
+in or on a volume of a storage or distribution medium, is called an
+"aggregate" if the compilation and its resulting copyright are not
+used to limit the access or legal rights of the compilation's users
+beyond what the individual works permit. Inclusion of a covered work
+in an aggregate does not cause this License to apply to the other
+parts of the aggregate.
+
+ 6. Conveying Non-Source Forms.
+
+ You may convey a covered work in object code form under the terms
+of sections 4 and 5, provided that you also convey the
+machine-readable Corresponding Source under the terms of this License,
+in one of these ways:
+
+ a) Convey the object code in, or embodied in, a physical product
+ (including a physical distribution medium), accompanied by the
+ Corresponding Source fixed on a durable physical medium
+ customarily used for software interchange.
+
+ b) Convey the object code in, or embodied in, a physical product
+ (including a physical distribution medium), accompanied by a
+ written offer, valid for at least three years and valid for as
+ long as you offer spare parts or customer support for that product
+ model, to give anyone who possesses the object code either (1) a
+ copy of the Corresponding Source for all the software in the
+ product that is covered by this License, on a durable physical
+ medium customarily used for software interchange, for a price no
+ more than your reasonable cost of physically performing this
+ conveying of source, or (2) access to copy the
+ Corresponding Source from a network server at no charge.
+
+ c) Convey individual copies of the object code with a copy of the
+ written offer to provide the Corresponding Source. This
+ alternative is allowed only occasionally and noncommercially, and
+ only if you received the object code with such an offer, in accord
+ with subsection 6b.
+
+ d) Convey the object code by offering access from a designated
+ place (gratis or for a charge), and offer equivalent access to the
+ Corresponding Source in the same way through the same place at no
+ further charge. You need not require recipients to copy the
+ Corresponding Source along with the object code. If the place to
+ copy the object code is a network server, the Corresponding Source
+ may be on a different server (operated by you or a third party)
+ that supports equivalent copying facilities, provided you maintain
+ clear directions next to the object code saying where to find the
+ Corresponding Source. Regardless of what server hosts the
+ Corresponding Source, you remain obligated to ensure that it is
+ available for as long as needed to satisfy these requirements.
+
+ e) Convey the object code using peer-to-peer transmission, provided
+ you inform other peers where the object code and Corresponding
+ Source of the work are being offered to the general public at no
+ charge under subsection 6d.
+
+ A separable portion of the object code, whose source code is excluded
+from the Corresponding Source as a System Library, need not be
+included in conveying the object code work.
+
+ A "User Product" is either (1) a "consumer product", which means any
+tangible personal property which is normally used for personal, family,
+or household purposes, or (2) anything designed or sold for incorporation
+into a dwelling. In determining whether a product is a consumer product,
+doubtful cases shall be resolved in favor of coverage. For a particular
+product received by a particular user, "normally used" refers to a
+typical or common use of that class of product, regardless of the status
+of the particular user or of the way in which the particular user
+actually uses, or expects or is expected to use, the product. A product
+is a consumer product regardless of whether the product has substantial
+commercial, industrial or non-consumer uses, unless such uses represent
+the only significant mode of use of the product.
+
+ "Installation Information" for a User Product means any methods,
+procedures, authorization keys, or other information required to install
+and execute modified versions of a covered work in that User Product from
+a modified version of its Corresponding Source. The information must
+suffice to ensure that the continued functioning of the modified object
+code is in no case prevented or interfered with solely because
+modification has been made.
+
+ If you convey an object code work under this section in, or with, or
+specifically for use in, a User Product, and the conveying occurs as
+part of a transaction in which the right of possession and use of the
+User Product is transferred to the recipient in perpetuity or for a
+fixed term (regardless of how the transaction is characterized), the
+Corresponding Source conveyed under this section must be accompanied
+by the Installation Information. But this requirement does not apply
+if neither you nor any third party retains the ability to install
+modified object code on the User Product (for example, the work has
+been installed in ROM).
+
+ The requirement to provide Installation Information does not include a
+requirement to continue to provide support service, warranty, or updates
+for a work that has been modified or installed by the recipient, or for
+the User Product in which it has been modified or installed. Access to a
+network may be denied when the modification itself materially and
+adversely affects the operation of the network or violates the rules and
+protocols for communication across the network.
+
+ Corresponding Source conveyed, and Installation Information provided,
+in accord with this section must be in a format that is publicly
+documented (and with an implementation available to the public in
+source code form), and must require no special password or key for
+unpacking, reading or copying.
+
+ 7. Additional Terms.
+
+ "Additional permissions" are terms that supplement the terms of this
+License by making exceptions from one or more of its conditions.
+Additional permissions that are applicable to the entire Program shall
+be treated as though they were included in this License, to the extent
+that they are valid under applicable law. If additional permissions
+apply only to part of the Program, that part may be used separately
+under those permissions, but the entire Program remains governed by
+this License without regard to the additional permissions.
+
+ When you convey a copy of a covered work, you may at your option
+remove any additional permissions from that copy, or from any part of
+it. (Additional permissions may be written to require their own
+removal in certain cases when you modify the work.) You may place
+additional permissions on material, added by you to a covered work,
+for which you have or can give appropriate copyright permission.
+
+ Notwithstanding any other provision of this License, for material you
+add to a covered work, you may (if authorized by the copyright holders of
+that material) supplement the terms of this License with terms:
+
+ a) Disclaiming warranty or limiting liability differently from the
+ terms of sections 15 and 16 of this License; or
+
+ b) Requiring preservation of specified reasonable legal notices or
+ author attributions in that material or in the Appropriate Legal
+ Notices displayed by works containing it; or
+
+ c) Prohibiting misrepresentation of the origin of that material, or
+ requiring that modified versions of such material be marked in
+ reasonable ways as different from the original version; or
+
+ d) Limiting the use for publicity purposes of names of licensors or
+ authors of the material; or
+
+ e) Declining to grant rights under trademark law for use of some
+ trade names, trademarks, or service marks; or
+
+ f) Requiring indemnification of licensors and authors of that
+ material by anyone who conveys the material (or modified versions of
+ it) with contractual assumptions of liability to the recipient, for
+ any liability that these contractual assumptions directly impose on
+ those licensors and authors.
+
+ All other non-permissive additional terms are considered "further
+restrictions" within the meaning of section 10. If the Program as you
+received it, or any part of it, contains a notice stating that it is
+governed by this License along with a term that is a further
+restriction, you may remove that term. If a license document contains
+a further restriction but permits relicensing or conveying under this
+License, you may add to a covered work material governed by the terms
+of that license document, provided that the further restriction does
+not survive such relicensing or conveying.
+
+ If you add terms to a covered work in accord with this section, you
+must place, in the relevant source files, a statement of the
+additional terms that apply to those files, or a notice indicating
+where to find the applicable terms.
+
+ Additional terms, permissive or non-permissive, may be stated in the
+form of a separately written license, or stated as exceptions;
+the above requirements apply either way.
+
+ 8. Termination.
+
+ You may not propagate or modify a covered work except as expressly
+provided under this License. Any attempt otherwise to propagate or
+modify it is void, and will automatically terminate your rights under
+this License (including any patent licenses granted under the third
+paragraph of section 11).
+
+ However, if you cease all violation of this License, then your
+license from a particular copyright holder is reinstated (a)
+provisionally, unless and until the copyright holder explicitly and
+finally terminates your license, and (b) permanently, if the copyright
+holder fails to notify you of the violation by some reasonable means
+prior to 60 days after the cessation.
+
+ Moreover, your license from a particular copyright holder is
+reinstated permanently if the copyright holder notifies you of the
+violation by some reasonable means, this is the first time you have
+received notice of violation of this License (for any work) from that
+copyright holder, and you cure the violation prior to 30 days after
+your receipt of the notice.
+
+ Termination of your rights under this section does not terminate the
+licenses of parties who have received copies or rights from you under
+this License. If your rights have been terminated and not permanently
+reinstated, you do not qualify to receive new licenses for the same
+material under section 10.
+
+ 9. Acceptance Not Required for Having Copies.
+
+ You are not required to accept this License in order to receive or
+run a copy of the Program. Ancillary propagation of a covered work
+occurring solely as a consequence of using peer-to-peer transmission
+to receive a copy likewise does not require acceptance. However,
+nothing other than this License grants you permission to propagate or
+modify any covered work. These actions infringe copyright if you do
+not accept this License. Therefore, by modifying or propagating a
+covered work, you indicate your acceptance of this License to do so.
+
+ 10. Automatic Licensing of Downstream Recipients.
+
+ Each time you convey a covered work, the recipient automatically
+receives a license from the original licensors, to run, modify and
+propagate that work, subject to this License. You are not responsible
+for enforcing compliance by third parties with this License.
+
+ An "entity transaction" is a transaction transferring control of an
+organization, or substantially all assets of one, or subdividing an
+organization, or merging organizations. If propagation of a covered
+work results from an entity transaction, each party to that
+transaction who receives a copy of the work also receives whatever
+licenses to the work the party's predecessor in interest had or could
+give under the previous paragraph, plus a right to possession of the
+Corresponding Source of the work from the predecessor in interest, if
+the predecessor has it or can get it with reasonable efforts.
+
+ You may not impose any further restrictions on the exercise of the
+rights granted or affirmed under this License. For example, you may
+not impose a license fee, royalty, or other charge for exercise of
+rights granted under this License, and you may not initiate litigation
+(including a cross-claim or counterclaim in a lawsuit) alleging that
+any patent claim is infringed by making, using, selling, offering for
+sale, or importing the Program or any portion of it.
+
+ 11. Patents.
+
+ A "contributor" is a copyright holder who authorizes use under this
+License of the Program or a work on which the Program is based. The
+work thus licensed is called the contributor's "contributor version".
+
+ A contributor's "essential patent claims" are all patent claims
+owned or controlled by the contributor, whether already acquired or
+hereafter acquired, that would be infringed by some manner, permitted
+by this License, of making, using, or selling its contributor version,
+but do not include claims that would be infringed only as a
+consequence of further modification of the contributor version. For
+purposes of this definition, "control" includes the right to grant
+patent sublicenses in a manner consistent with the requirements of
+this License.
+
+ Each contributor grants you a non-exclusive, worldwide, royalty-free
+patent license under the contributor's essential patent claims, to
+make, use, sell, offer for sale, import and otherwise run, modify and
+propagate the contents of its contributor version.
+
+ In the following three paragraphs, a "patent license" is any express
+agreement or commitment, however denominated, not to enforce a patent
+(such as an express permission to practice a patent or covenant not to
+sue for patent infringement). To "grant" such a patent license to a
+party means to make such an agreement or commitment not to enforce a
+patent against the party.
+
+ If you convey a covered work, knowingly relying on a patent license,
+and the Corresponding Source of the work is not available for anyone
+to copy, free of charge and under the terms of this License, through a
+publicly available network server or other readily accessible means,
+then you must either (1) cause the Corresponding Source to be so
+available, or (2) arrange to deprive yourself of the benefit of the
+patent license for this particular work, or (3) arrange, in a manner
+consistent with the requirements of this License, to extend the patent
+license to downstream recipients. "Knowingly relying" means you have
+actual knowledge that, but for the patent license, your conveying the
+covered work in a country, or your recipient's use of the covered work
+in a country, would infringe one or more identifiable patents in that
+country that you have reason to believe are valid.
+
+ If, pursuant to or in connection with a single transaction or
+arrangement, you convey, or propagate by procuring conveyance of, a
+covered work, and grant a patent license to some of the parties
+receiving the covered work authorizing them to use, propagate, modify
+or convey a specific copy of the covered work, then the patent license
+you grant is automatically extended to all recipients of the covered
+work and works based on it.
+
+ A patent license is "discriminatory" if it does not include within
+the scope of its coverage, prohibits the exercise of, or is
+conditioned on the non-exercise of one or more of the rights that are
+specifically granted under this License. You may not convey a covered
+work if you are a party to an arrangement with a third party that is
+in the business of distributing software, under which you make payment
+to the third party based on the extent of your activity of conveying
+the work, and under which the third party grants, to any of the
+parties who would receive the covered work from you, a discriminatory
+patent license (a) in connection with copies of the covered work
+conveyed by you (or copies made from those copies), or (b) primarily
+for and in connection with specific products or compilations that
+contain the covered work, unless you entered into that arrangement,
+or that patent license was granted, prior to 28 March 2007.
+
+ Nothing in this License shall be construed as excluding or limiting
+any implied license or other defenses to infringement that may
+otherwise be available to you under applicable patent law.
+
+ 12. No Surrender of Others' Freedom.
+
+ If conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License. If you cannot convey a
+covered work so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you may
+not convey it at all. For example, if you agree to terms that obligate you
+to collect a royalty for further conveying from those to whom you convey
+the Program, the only way you could satisfy both those terms and this
+License would be to refrain entirely from conveying the Program.
+
+ 13. Use with the GNU Affero General Public License.
+
+ Notwithstanding any other provision of this License, you have
+permission to link or combine any covered work with a work licensed
+under version 3 of the GNU Affero General Public License into a single
+combined work, and to convey the resulting work. The terms of this
+License will continue to apply to the part which is the covered work,
+but the special requirements of the GNU Affero General Public License,
+section 13, concerning interaction through a network will apply to the
+combination as such.
+
+ 14. Revised Versions of this License.
+
+ The Free Software Foundation may publish revised and/or new versions of
+the GNU General Public License from time to time. Such new versions will
+be similar in spirit to the present version, but may differ in detail to
+address new problems or concerns.
+
+ Each version is given a distinguishing version number. If the
+Program specifies that a certain numbered version of the GNU General
+Public License "or any later version" applies to it, you have the
+option of following the terms and conditions either of that numbered
+version or of any later version published by the Free Software
+Foundation. If the Program does not specify a version number of the
+GNU General Public License, you may choose any version ever published
+by the Free Software Foundation.
+
+ If the Program specifies that a proxy can decide which future
+versions of the GNU General Public License can be used, that proxy's
+public statement of acceptance of a version permanently authorizes you
+to choose that version for the Program.
+
+ Later license versions may give you additional or different
+permissions. However, no additional obligations are imposed on any
+author or copyright holder as a result of your choosing to follow a
+later version.
+
+ 15. Disclaimer of Warranty.
+
+ THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY
+APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT
+HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY
+OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO,
+THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM
+IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF
+ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
+
+ 16. Limitation of Liability.
+
+ IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS
+THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY
+GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE
+USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF
+DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD
+PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS),
+EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF
+SUCH DAMAGES.
+
+ 17. Interpretation of Sections 15 and 16.
+
+ If the disclaimer of warranty and limitation of liability provided
+above cannot be given local legal effect according to their terms,
+reviewing courts shall apply local law that most closely approximates
+an absolute waiver of all civil liability in connection with the
+Program, unless a warranty or assumption of liability accompanies a
+copy of the Program in return for a fee.
+
+ END OF TERMS AND CONDITIONS
+
+ How to Apply These Terms to Your New Programs
+
+ If you develop a new program, and you want it to be of the greatest
+possible use to the public, the best way to achieve this is to make it
+free software which everyone can redistribute and change under these terms.
+
+ To do so, attach the following notices to the program. It is safest
+to attach them to the start of each source file to most effectively
+state the exclusion of warranty; and each file should have at least
+the "copyright" line and a pointer to where the full notice is found.
+
+
+ Copyright (C)
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see .
+
+Also add information on how to contact you by electronic and paper mail.
+
+ If the program does terminal interaction, make it output a short
+notice like this when it starts in an interactive mode:
+
+ Copyright (C)
+ This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
+ This is free software, and you are welcome to redistribute it
+ under certain conditions; type `show c' for details.
+
+The hypothetical commands `show w' and `show c' should show the appropriate
+parts of the General Public License. Of course, your program's commands
+might be different; for a GUI interface, you would use an "about box".
+
+ You should also get your employer (if you work as a programmer) or school,
+if any, to sign a "copyright disclaimer" for the program, if necessary.
+For more information on this, and how to apply and follow the GNU GPL, see
+.
+
+ The GNU General Public License does not permit incorporating your program
+into proprietary programs. If your program is a subroutine library, you
+may consider it more useful to permit linking proprietary applications with
+the library. If this is what you want to do, use the GNU Lesser General
+Public License instead of this License. But first, please read
+.
diff --git a/modules/sale_shipment_tolerance/MANIFEST.in b/modules/sale_shipment_tolerance/MANIFEST.in
new file mode 100644
index 0000000000..e88b2348a3
--- /dev/null
+++ b/modules/sale_shipment_tolerance/MANIFEST.in
@@ -0,0 +1,5 @@
+include CHANGELOG
+include COPYRIGHT
+include LICENSE
+include README.rst
+include doc/*
diff --git a/modules/sale_shipment_tolerance/README.rst b/modules/sale_shipment_tolerance/README.rst
new file mode 120000
index 0000000000..176d9c2695
--- /dev/null
+++ b/modules/sale_shipment_tolerance/README.rst
@@ -0,0 +1 @@
+doc/index.rst
\ No newline at end of file
diff --git a/modules/sale_shipment_tolerance/__init__.py b/modules/sale_shipment_tolerance/__init__.py
new file mode 100644
index 0000000000..7560e2b0f2
--- /dev/null
+++ b/modules/sale_shipment_tolerance/__init__.py
@@ -0,0 +1,18 @@
+# This file is part of Tryton. The COPYRIGHT file at the top level of
+# this repository contains the full copyright notices and license terms.
+
+from trytond.pool import Pool
+from . import configuration
+from . import sale
+from . import stock
+
+__all__ = ['register']
+
+
+def register():
+ Pool.register(
+ configuration.Configuration,
+ configuration.ConfigurationShipmentTolerance,
+ sale.Line,
+ stock.Move,
+ module='sale_shipment_tolerance', type_='model')
diff --git a/modules/sale_shipment_tolerance/configuration.py b/modules/sale_shipment_tolerance/configuration.py
new file mode 100644
index 0000000000..e0fb40250e
--- /dev/null
+++ b/modules/sale_shipment_tolerance/configuration.py
@@ -0,0 +1,75 @@
+# This file is part of Tryton. The COPYRIGHT file at the top level of
+# this repository contains the full copyright notices and license terms.
+from trytond.model import ModelSQL, ValueMixin, fields
+from trytond.pool import PoolMeta, Pool
+
+
+sale_under_shipment_tolerance = fields.Float(
+ "Sale Under Shipment Tolerance",
+ help="The lower quantity accepted in percentage.")
+sale_over_shipment_tolerance = fields.Float(
+ "Sale Over Shipment Tolerance",
+ help="The upper quantity accepted in percentage.")
+
+
+def default_func(field_name):
+ @classmethod
+ def default(cls, **pattern):
+ return getattr(
+ cls.multivalue_model(field_name),
+ 'default_%s' % field_name, lambda: None)()
+ return default
+
+
+class Configuration(metaclass=PoolMeta):
+ __name__ = 'sale.configuration'
+
+ sale_under_shipment_tolerance = fields.MultiValue(
+ sale_under_shipment_tolerance)
+ sale_over_shipment_tolerance = fields.MultiValue(
+ sale_over_shipment_tolerance)
+
+ @classmethod
+ def multivalue_model(cls, field):
+ pool = Pool()
+ if field in {
+ 'sale_under_shipment_tolerance',
+ 'sale_over_shipment_tolerance'}:
+ return pool.get('sale.configuration.shipment_tolerance')
+ return super(Configuration, cls).multivalue_model(field)
+
+ default_sale_under_shipment_tolerance = default_func(
+ 'sale_under_shipment_tolerance')
+ default_sale_over_shipment_tolerance = default_func(
+ 'sale_over_shipment_tolerance')
+
+
+class ConfigurationShipmentTolerance(ModelSQL, ValueMixin):
+ "Sale Configuration Shipment Tolerance"
+ __name__ = 'sale.configuration.shipment_tolerance'
+ sale_under_shipment_tolerance = sale_under_shipment_tolerance
+ sale_over_shipment_tolerance = sale_over_shipment_tolerance
+
+ @classmethod
+ def __setup__(cls):
+ super(ConfigurationShipmentTolerance, cls).__setup__()
+ cls.sale_under_shipment_tolerance.domain = [
+ 'OR',
+ ('sale_under_shipment_tolerance', '=', None),
+ [
+ ('sale_under_shipment_tolerance', '>=', 0),
+ ('sale_under_shipment_tolerance', '<=', 1),
+ ]]
+ cls.sale_over_shipment_tolerance.domain = [
+ 'OR',
+ ('sale_over_shipment_tolerance', '=', None),
+ ('sale_over_shipment_tolerance', '>=', 1),
+ ]
+
+ @classmethod
+ def default_sale_under_shipment_tolerance(cls):
+ return 1
+
+ @classmethod
+ def default_sale_over_shipment_tolerance(cls):
+ return None
diff --git a/modules/sale_shipment_tolerance/configuration.xml b/modules/sale_shipment_tolerance/configuration.xml
new file mode 100644
index 0000000000..1be072a305
--- /dev/null
+++ b/modules/sale_shipment_tolerance/configuration.xml
@@ -0,0 +1,12 @@
+
+
+
+
+
+ sale.configuration
+
+ configuration_form
+
+
+
diff --git a/modules/sale_shipment_tolerance/doc/index.rst b/modules/sale_shipment_tolerance/doc/index.rst
new file mode 100644
index 0000000000..8b8d3ce9ab
--- /dev/null
+++ b/modules/sale_shipment_tolerance/doc/index.rst
@@ -0,0 +1,10 @@
+Sale Shipment Tolerance Module
+##############################
+
+The sale_shipment_tolerance modules adds under and over shipment tolerance on
+the sale.
+If the quantity of a sale line is under shipped but inside the tolerance
+percentage, then the line will be considered as fully shipped and no back-order
+will be created.
+If the quantity of a sale line is over shipped more than the tolerance
+percentage, then a warning is raised.
diff --git a/modules/sale_shipment_tolerance/exceptions.py b/modules/sale_shipment_tolerance/exceptions.py
new file mode 100644
index 0000000000..2b011caa45
--- /dev/null
+++ b/modules/sale_shipment_tolerance/exceptions.py
@@ -0,0 +1,8 @@
+# This file is part of Tryton. The COPYRIGHT file at the top level of
+# this repository contains the full copyright notices and license terms.
+
+from trytond.exceptions import UserWarning
+
+
+class OverShipmentWarning(UserWarning):
+ pass
diff --git a/modules/sale_shipment_tolerance/locale/bg.po b/modules/sale_shipment_tolerance/locale/bg.po
new file mode 100644
index 0000000000..eee28e36a4
--- /dev/null
+++ b/modules/sale_shipment_tolerance/locale/bg.po
@@ -0,0 +1,58 @@
+#
+msgid ""
+msgstr "Content-Type: text/plain; charset=utf-8\n"
+
+msgctxt "field:sale.configuration,sale_over_shipment_tolerance:"
+msgid "Sale Over Shipment Tolerance"
+msgstr ""
+
+msgctxt "field:sale.configuration,sale_under_shipment_tolerance:"
+msgid "Sale Under Shipment Tolerance"
+msgstr ""
+
+msgctxt ""
+"field:sale.configuration.shipment_tolerance,sale_over_shipment_tolerance:"
+msgid "Sale Over Shipment Tolerance"
+msgstr ""
+
+msgctxt ""
+"field:sale.configuration.shipment_tolerance,sale_under_shipment_tolerance:"
+msgid "Sale Under Shipment Tolerance"
+msgstr ""
+
+msgctxt "help:sale.configuration,sale_over_shipment_tolerance:"
+msgid "The upper quantity accepted in percentage."
+msgstr ""
+
+msgctxt "help:sale.configuration,sale_under_shipment_tolerance:"
+msgid "The lower quantity accepted in percentage."
+msgstr ""
+
+msgctxt ""
+"help:sale.configuration.shipment_tolerance,sale_over_shipment_tolerance:"
+msgid "The upper quantity accepted in percentage."
+msgstr ""
+
+msgctxt ""
+"help:sale.configuration.shipment_tolerance,sale_under_shipment_tolerance:"
+msgid "The lower quantity accepted in percentage."
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_over_shipment"
+msgid ""
+"The sale line \"%(line)s\" exceeds the over shipment tolerance (%(shipped)s "
+"shipped > %(maximal)s )."
+msgstr ""
+
+msgctxt "model:sale.configuration.shipment_tolerance,name:"
+msgid "Sale Configuration Shipment Tolerance"
+msgstr ""
+
+#, fuzzy
+msgctxt "view:sale.configuration:"
+msgid "%"
+msgstr "%"
+
+msgctxt "view:sale.configuration:"
+msgid "Sale Shipment Tolerance"
+msgstr ""
diff --git a/modules/sale_shipment_tolerance/locale/ca.po b/modules/sale_shipment_tolerance/locale/ca.po
new file mode 100644
index 0000000000..9d54ee5925
--- /dev/null
+++ b/modules/sale_shipment_tolerance/locale/ca.po
@@ -0,0 +1,59 @@
+#
+msgid ""
+msgstr "Content-Type: text/plain; charset=utf-8\n"
+
+msgctxt "field:sale.configuration,sale_over_shipment_tolerance:"
+msgid "Sale Over Shipment Tolerance"
+msgstr "Tolerància d'enviament excessiu de venda"
+
+msgctxt "field:sale.configuration,sale_under_shipment_tolerance:"
+msgid "Sale Under Shipment Tolerance"
+msgstr "Tolerància de falta d'enviament de venda"
+
+msgctxt ""
+"field:sale.configuration.shipment_tolerance,sale_over_shipment_tolerance:"
+msgid "Sale Over Shipment Tolerance"
+msgstr "Tolerància d'enviament excessiu de venda"
+
+msgctxt ""
+"field:sale.configuration.shipment_tolerance,sale_under_shipment_tolerance:"
+msgid "Sale Under Shipment Tolerance"
+msgstr "Tolerància de falta d'enviament de venda"
+
+msgctxt "help:sale.configuration,sale_over_shipment_tolerance:"
+msgid "The upper quantity accepted in percentage."
+msgstr "El percentatge de quantitat en excés que s'accepta."
+
+msgctxt "help:sale.configuration,sale_under_shipment_tolerance:"
+msgid "The lower quantity accepted in percentage."
+msgstr "El percentatge de quantitat mínim a acceptar com a enviat."
+
+msgctxt ""
+"help:sale.configuration.shipment_tolerance,sale_over_shipment_tolerance:"
+msgid "The upper quantity accepted in percentage."
+msgstr "El percentatge de quantitat en excés que s'accepta."
+
+msgctxt ""
+"help:sale.configuration.shipment_tolerance,sale_under_shipment_tolerance:"
+msgid "The lower quantity accepted in percentage."
+msgstr "El percentatge de quantitat mínim a acceptar com a enviat."
+
+msgctxt "model:ir.message,text:msg_over_shipment"
+msgid ""
+"The sale line \"%(line)s\" exceeds the over shipment tolerance (%(shipped)s "
+"shipped > %(maximal)s )."
+msgstr ""
+"La línia de venda \"%s\" sobrepassa la tolerància d'enviament excessiu "
+"(%(shipped)s enviat > %(maximal)s )."
+
+msgctxt "model:sale.configuration.shipment_tolerance,name:"
+msgid "Sale Configuration Shipment Tolerance"
+msgstr "Configuració de la tolerància d'enviament de venda"
+
+msgctxt "view:sale.configuration:"
+msgid "%"
+msgstr "%"
+
+msgctxt "view:sale.configuration:"
+msgid "Sale Shipment Tolerance"
+msgstr "Tolerancia d'enviament de venda"
diff --git a/modules/sale_shipment_tolerance/locale/cs.po b/modules/sale_shipment_tolerance/locale/cs.po
new file mode 100644
index 0000000000..eee28e36a4
--- /dev/null
+++ b/modules/sale_shipment_tolerance/locale/cs.po
@@ -0,0 +1,58 @@
+#
+msgid ""
+msgstr "Content-Type: text/plain; charset=utf-8\n"
+
+msgctxt "field:sale.configuration,sale_over_shipment_tolerance:"
+msgid "Sale Over Shipment Tolerance"
+msgstr ""
+
+msgctxt "field:sale.configuration,sale_under_shipment_tolerance:"
+msgid "Sale Under Shipment Tolerance"
+msgstr ""
+
+msgctxt ""
+"field:sale.configuration.shipment_tolerance,sale_over_shipment_tolerance:"
+msgid "Sale Over Shipment Tolerance"
+msgstr ""
+
+msgctxt ""
+"field:sale.configuration.shipment_tolerance,sale_under_shipment_tolerance:"
+msgid "Sale Under Shipment Tolerance"
+msgstr ""
+
+msgctxt "help:sale.configuration,sale_over_shipment_tolerance:"
+msgid "The upper quantity accepted in percentage."
+msgstr ""
+
+msgctxt "help:sale.configuration,sale_under_shipment_tolerance:"
+msgid "The lower quantity accepted in percentage."
+msgstr ""
+
+msgctxt ""
+"help:sale.configuration.shipment_tolerance,sale_over_shipment_tolerance:"
+msgid "The upper quantity accepted in percentage."
+msgstr ""
+
+msgctxt ""
+"help:sale.configuration.shipment_tolerance,sale_under_shipment_tolerance:"
+msgid "The lower quantity accepted in percentage."
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_over_shipment"
+msgid ""
+"The sale line \"%(line)s\" exceeds the over shipment tolerance (%(shipped)s "
+"shipped > %(maximal)s )."
+msgstr ""
+
+msgctxt "model:sale.configuration.shipment_tolerance,name:"
+msgid "Sale Configuration Shipment Tolerance"
+msgstr ""
+
+#, fuzzy
+msgctxt "view:sale.configuration:"
+msgid "%"
+msgstr "%"
+
+msgctxt "view:sale.configuration:"
+msgid "Sale Shipment Tolerance"
+msgstr ""
diff --git a/modules/sale_shipment_tolerance/locale/de.po b/modules/sale_shipment_tolerance/locale/de.po
new file mode 100644
index 0000000000..90e766f1de
--- /dev/null
+++ b/modules/sale_shipment_tolerance/locale/de.po
@@ -0,0 +1,59 @@
+#
+msgid ""
+msgstr "Content-Type: text/plain; charset=utf-8\n"
+
+msgctxt "field:sale.configuration,sale_over_shipment_tolerance:"
+msgid "Sale Over Shipment Tolerance"
+msgstr "Obere Liefertoleranz im Verkauf"
+
+msgctxt "field:sale.configuration,sale_under_shipment_tolerance:"
+msgid "Sale Under Shipment Tolerance"
+msgstr "Untere Liefertoleranz im Verkauf"
+
+msgctxt ""
+"field:sale.configuration.shipment_tolerance,sale_over_shipment_tolerance:"
+msgid "Sale Over Shipment Tolerance"
+msgstr "Obere Liefertoleranz im Verkauf"
+
+msgctxt ""
+"field:sale.configuration.shipment_tolerance,sale_under_shipment_tolerance:"
+msgid "Sale Under Shipment Tolerance"
+msgstr "Untere Liefertoleranz im Verkauf"
+
+msgctxt "help:sale.configuration,sale_over_shipment_tolerance:"
+msgid "The upper quantity accepted in percentage."
+msgstr "Die Obergrenze der akzeptierten Menge in Prozent."
+
+msgctxt "help:sale.configuration,sale_under_shipment_tolerance:"
+msgid "The lower quantity accepted in percentage."
+msgstr "Die Untergrenze der akzeptierten Menge in Prozent."
+
+msgctxt ""
+"help:sale.configuration.shipment_tolerance,sale_over_shipment_tolerance:"
+msgid "The upper quantity accepted in percentage."
+msgstr "Die Obergrenze der akzeptierten Menge in Prozent."
+
+msgctxt ""
+"help:sale.configuration.shipment_tolerance,sale_under_shipment_tolerance:"
+msgid "The lower quantity accepted in percentage."
+msgstr "Die Untergrenze der akzeptierten Menge in Prozent."
+
+msgctxt "model:ir.message,text:msg_over_shipment"
+msgid ""
+"The sale line \"%(line)s\" exceeds the over shipment tolerance (%(shipped)s "
+"shipped > %(maximal)s )."
+msgstr ""
+"Die Verkaufsposition \"%(line)s\" überschreitet die Überlieferungstoleranz "
+"(%(shipped)s shipped > %(maximal)s )."
+
+msgctxt "model:sale.configuration.shipment_tolerance,name:"
+msgid "Sale Configuration Shipment Tolerance"
+msgstr "Einstellungen Liefertoleranzen im Verkauf"
+
+msgctxt "view:sale.configuration:"
+msgid "%"
+msgstr "%"
+
+msgctxt "view:sale.configuration:"
+msgid "Sale Shipment Tolerance"
+msgstr "Liefertoleranz im Verkauf"
diff --git a/modules/sale_shipment_tolerance/locale/es.po b/modules/sale_shipment_tolerance/locale/es.po
new file mode 100644
index 0000000000..ce53d78621
--- /dev/null
+++ b/modules/sale_shipment_tolerance/locale/es.po
@@ -0,0 +1,59 @@
+#
+msgid ""
+msgstr "Content-Type: text/plain; charset=utf-8\n"
+
+msgctxt "field:sale.configuration,sale_over_shipment_tolerance:"
+msgid "Sale Over Shipment Tolerance"
+msgstr "Tolerancia de envío excesivo de venta"
+
+msgctxt "field:sale.configuration,sale_under_shipment_tolerance:"
+msgid "Sale Under Shipment Tolerance"
+msgstr "Tolerancia de falta de envío de venta"
+
+msgctxt ""
+"field:sale.configuration.shipment_tolerance,sale_over_shipment_tolerance:"
+msgid "Sale Over Shipment Tolerance"
+msgstr "Tolerancia de envío excesivo de venta"
+
+msgctxt ""
+"field:sale.configuration.shipment_tolerance,sale_under_shipment_tolerance:"
+msgid "Sale Under Shipment Tolerance"
+msgstr "Tolerancia de falta de envío de venta"
+
+msgctxt "help:sale.configuration,sale_over_shipment_tolerance:"
+msgid "The upper quantity accepted in percentage."
+msgstr "El porcentaje de cantidad excesiva que se acepta."
+
+msgctxt "help:sale.configuration,sale_under_shipment_tolerance:"
+msgid "The lower quantity accepted in percentage."
+msgstr "El porcentaje de cantidad mínima a aceptar como enviado."
+
+msgctxt ""
+"help:sale.configuration.shipment_tolerance,sale_over_shipment_tolerance:"
+msgid "The upper quantity accepted in percentage."
+msgstr "El porcentaje de cantidad excesiva que se acepta."
+
+msgctxt ""
+"help:sale.configuration.shipment_tolerance,sale_under_shipment_tolerance:"
+msgid "The lower quantity accepted in percentage."
+msgstr "El porcentaje de cantidad mínima a aceptar como enviado."
+
+msgctxt "model:ir.message,text:msg_over_shipment"
+msgid ""
+"The sale line \"%(line)s\" exceeds the over shipment tolerance (%(shipped)s "
+"shipped > %(maximal)s )."
+msgstr ""
+"La línea de venta \"%(line)s\" excede la tolerancia de envío (%(shipped)s "
+"enviado > %(maximal)s )."
+
+msgctxt "model:sale.configuration.shipment_tolerance,name:"
+msgid "Sale Configuration Shipment Tolerance"
+msgstr "Configuración de la tolerancia de envío de venta"
+
+msgctxt "view:sale.configuration:"
+msgid "%"
+msgstr "%"
+
+msgctxt "view:sale.configuration:"
+msgid "Sale Shipment Tolerance"
+msgstr "Tolerancia de envío de venta"
diff --git a/modules/sale_shipment_tolerance/locale/es_419.po b/modules/sale_shipment_tolerance/locale/es_419.po
new file mode 100644
index 0000000000..74a4603300
--- /dev/null
+++ b/modules/sale_shipment_tolerance/locale/es_419.po
@@ -0,0 +1,57 @@
+#
+msgid ""
+msgstr "Content-Type: text/plain; charset=utf-8\n"
+
+msgctxt "field:sale.configuration,sale_over_shipment_tolerance:"
+msgid "Sale Over Shipment Tolerance"
+msgstr ""
+
+msgctxt "field:sale.configuration,sale_under_shipment_tolerance:"
+msgid "Sale Under Shipment Tolerance"
+msgstr ""
+
+msgctxt ""
+"field:sale.configuration.shipment_tolerance,sale_over_shipment_tolerance:"
+msgid "Sale Over Shipment Tolerance"
+msgstr ""
+
+msgctxt ""
+"field:sale.configuration.shipment_tolerance,sale_under_shipment_tolerance:"
+msgid "Sale Under Shipment Tolerance"
+msgstr ""
+
+msgctxt "help:sale.configuration,sale_over_shipment_tolerance:"
+msgid "The upper quantity accepted in percentage."
+msgstr ""
+
+msgctxt "help:sale.configuration,sale_under_shipment_tolerance:"
+msgid "The lower quantity accepted in percentage."
+msgstr ""
+
+msgctxt ""
+"help:sale.configuration.shipment_tolerance,sale_over_shipment_tolerance:"
+msgid "The upper quantity accepted in percentage."
+msgstr ""
+
+msgctxt ""
+"help:sale.configuration.shipment_tolerance,sale_under_shipment_tolerance:"
+msgid "The lower quantity accepted in percentage."
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_over_shipment"
+msgid ""
+"The sale line \"%(line)s\" exceeds the over shipment tolerance (%(shipped)s "
+"shipped > %(maximal)s )."
+msgstr ""
+
+msgctxt "model:sale.configuration.shipment_tolerance,name:"
+msgid "Sale Configuration Shipment Tolerance"
+msgstr ""
+
+msgctxt "view:sale.configuration:"
+msgid "%"
+msgstr ""
+
+msgctxt "view:sale.configuration:"
+msgid "Sale Shipment Tolerance"
+msgstr ""
diff --git a/modules/sale_shipment_tolerance/locale/et.po b/modules/sale_shipment_tolerance/locale/et.po
new file mode 100644
index 0000000000..0d5149cb6d
--- /dev/null
+++ b/modules/sale_shipment_tolerance/locale/et.po
@@ -0,0 +1,57 @@
+#
+msgid ""
+msgstr "Content-Type: text/plain; charset=utf-8\n"
+
+msgctxt "field:sale.configuration,sale_over_shipment_tolerance:"
+msgid "Sale Over Shipment Tolerance"
+msgstr ""
+
+msgctxt "field:sale.configuration,sale_under_shipment_tolerance:"
+msgid "Sale Under Shipment Tolerance"
+msgstr ""
+
+msgctxt ""
+"field:sale.configuration.shipment_tolerance,sale_over_shipment_tolerance:"
+msgid "Sale Over Shipment Tolerance"
+msgstr ""
+
+msgctxt ""
+"field:sale.configuration.shipment_tolerance,sale_under_shipment_tolerance:"
+msgid "Sale Under Shipment Tolerance"
+msgstr ""
+
+msgctxt "help:sale.configuration,sale_over_shipment_tolerance:"
+msgid "The upper quantity accepted in percentage."
+msgstr ""
+
+msgctxt "help:sale.configuration,sale_under_shipment_tolerance:"
+msgid "The lower quantity accepted in percentage."
+msgstr ""
+
+msgctxt ""
+"help:sale.configuration.shipment_tolerance,sale_over_shipment_tolerance:"
+msgid "The upper quantity accepted in percentage."
+msgstr ""
+
+msgctxt ""
+"help:sale.configuration.shipment_tolerance,sale_under_shipment_tolerance:"
+msgid "The lower quantity accepted in percentage."
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_over_shipment"
+msgid ""
+"The sale line \"%(line)s\" exceeds the over shipment tolerance (%(shipped)s "
+"shipped > %(maximal)s )."
+msgstr ""
+
+msgctxt "model:sale.configuration.shipment_tolerance,name:"
+msgid "Sale Configuration Shipment Tolerance"
+msgstr ""
+
+msgctxt "view:sale.configuration:"
+msgid "%"
+msgstr "%"
+
+msgctxt "view:sale.configuration:"
+msgid "Sale Shipment Tolerance"
+msgstr ""
diff --git a/modules/sale_shipment_tolerance/locale/fa.po b/modules/sale_shipment_tolerance/locale/fa.po
new file mode 100644
index 0000000000..af6eaad5d0
--- /dev/null
+++ b/modules/sale_shipment_tolerance/locale/fa.po
@@ -0,0 +1,58 @@
+#
+msgid ""
+msgstr "Content-Type: text/plain; charset=utf-8\n"
+
+msgctxt "field:sale.configuration,sale_over_shipment_tolerance:"
+msgid "Sale Over Shipment Tolerance"
+msgstr "فروش بیشتر از ظرفیت حمل و نقل میباشد"
+
+msgctxt "field:sale.configuration,sale_under_shipment_tolerance:"
+msgid "Sale Under Shipment Tolerance"
+msgstr "فروش کمتر از ظرفیت حمل و نقل میباشد"
+
+msgctxt ""
+"field:sale.configuration.shipment_tolerance,sale_over_shipment_tolerance:"
+msgid "Sale Over Shipment Tolerance"
+msgstr "فروش بیشتر از ظرفیت حمل و نقل میباشد"
+
+msgctxt ""
+"field:sale.configuration.shipment_tolerance,sale_under_shipment_tolerance:"
+msgid "Sale Under Shipment Tolerance"
+msgstr "فروش کمتر از ظرفیت حمل و نقل میباشد"
+
+msgctxt "help:sale.configuration,sale_over_shipment_tolerance:"
+msgid "The upper quantity accepted in percentage."
+msgstr "درصد بالاترین مقدار پذیرفته شده."
+
+msgctxt "help:sale.configuration,sale_under_shipment_tolerance:"
+msgid "The lower quantity accepted in percentage."
+msgstr "درصد پایین ترین مقدار پذیرفته شده."
+
+msgctxt ""
+"help:sale.configuration.shipment_tolerance,sale_over_shipment_tolerance:"
+msgid "The upper quantity accepted in percentage."
+msgstr "درصد بالاترین مقدار پذیرفته شده."
+
+msgctxt ""
+"help:sale.configuration.shipment_tolerance,sale_under_shipment_tolerance:"
+msgid "The lower quantity accepted in percentage."
+msgstr "درصد پایین ترین مقدار پذیرفته شده."
+
+#, fuzzy
+msgctxt "model:ir.message,text:msg_over_shipment"
+msgid ""
+"The sale line \"%(line)s\" exceeds the over shipment tolerance (%(shipped)s "
+"shipped > %(maximal)s )."
+msgstr "سطر فروش : \"%s\" بیشتر از ظرفیت حمل و نقل میباشد."
+
+msgctxt "model:sale.configuration.shipment_tolerance,name:"
+msgid "Sale Configuration Shipment Tolerance"
+msgstr "پیکربندی فروش ؛ ظرفیت حمل تحمل"
+
+msgctxt "view:sale.configuration:"
+msgid "%"
+msgstr "%"
+
+msgctxt "view:sale.configuration:"
+msgid "Sale Shipment Tolerance"
+msgstr "ظرفیت حمل و نقل فروش"
diff --git a/modules/sale_shipment_tolerance/locale/fi.po b/modules/sale_shipment_tolerance/locale/fi.po
new file mode 100644
index 0000000000..eee28e36a4
--- /dev/null
+++ b/modules/sale_shipment_tolerance/locale/fi.po
@@ -0,0 +1,58 @@
+#
+msgid ""
+msgstr "Content-Type: text/plain; charset=utf-8\n"
+
+msgctxt "field:sale.configuration,sale_over_shipment_tolerance:"
+msgid "Sale Over Shipment Tolerance"
+msgstr ""
+
+msgctxt "field:sale.configuration,sale_under_shipment_tolerance:"
+msgid "Sale Under Shipment Tolerance"
+msgstr ""
+
+msgctxt ""
+"field:sale.configuration.shipment_tolerance,sale_over_shipment_tolerance:"
+msgid "Sale Over Shipment Tolerance"
+msgstr ""
+
+msgctxt ""
+"field:sale.configuration.shipment_tolerance,sale_under_shipment_tolerance:"
+msgid "Sale Under Shipment Tolerance"
+msgstr ""
+
+msgctxt "help:sale.configuration,sale_over_shipment_tolerance:"
+msgid "The upper quantity accepted in percentage."
+msgstr ""
+
+msgctxt "help:sale.configuration,sale_under_shipment_tolerance:"
+msgid "The lower quantity accepted in percentage."
+msgstr ""
+
+msgctxt ""
+"help:sale.configuration.shipment_tolerance,sale_over_shipment_tolerance:"
+msgid "The upper quantity accepted in percentage."
+msgstr ""
+
+msgctxt ""
+"help:sale.configuration.shipment_tolerance,sale_under_shipment_tolerance:"
+msgid "The lower quantity accepted in percentage."
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_over_shipment"
+msgid ""
+"The sale line \"%(line)s\" exceeds the over shipment tolerance (%(shipped)s "
+"shipped > %(maximal)s )."
+msgstr ""
+
+msgctxt "model:sale.configuration.shipment_tolerance,name:"
+msgid "Sale Configuration Shipment Tolerance"
+msgstr ""
+
+#, fuzzy
+msgctxt "view:sale.configuration:"
+msgid "%"
+msgstr "%"
+
+msgctxt "view:sale.configuration:"
+msgid "Sale Shipment Tolerance"
+msgstr ""
diff --git a/modules/sale_shipment_tolerance/locale/fr.po b/modules/sale_shipment_tolerance/locale/fr.po
new file mode 100644
index 0000000000..3bb06cecfe
--- /dev/null
+++ b/modules/sale_shipment_tolerance/locale/fr.po
@@ -0,0 +1,59 @@
+#
+msgid ""
+msgstr "Content-Type: text/plain; charset=utf-8\n"
+
+msgctxt "field:sale.configuration,sale_over_shipment_tolerance:"
+msgid "Sale Over Shipment Tolerance"
+msgstr "Tolérance de sur-expédition de vente"
+
+msgctxt "field:sale.configuration,sale_under_shipment_tolerance:"
+msgid "Sale Under Shipment Tolerance"
+msgstr "Tolérance de sous-expédition de vente"
+
+msgctxt ""
+"field:sale.configuration.shipment_tolerance,sale_over_shipment_tolerance:"
+msgid "Sale Over Shipment Tolerance"
+msgstr "Tolérance de sur-expédition de vente"
+
+msgctxt ""
+"field:sale.configuration.shipment_tolerance,sale_under_shipment_tolerance:"
+msgid "Sale Under Shipment Tolerance"
+msgstr "Tolérance de sous-expédition de vente"
+
+msgctxt "help:sale.configuration,sale_over_shipment_tolerance:"
+msgid "The upper quantity accepted in percentage."
+msgstr "La quantité supérieure acceptée en pourcentage."
+
+msgctxt "help:sale.configuration,sale_under_shipment_tolerance:"
+msgid "The lower quantity accepted in percentage."
+msgstr "La quantité inférieure acceptée en pourcentage."
+
+msgctxt ""
+"help:sale.configuration.shipment_tolerance,sale_over_shipment_tolerance:"
+msgid "The upper quantity accepted in percentage."
+msgstr "La quantité supérieure acceptée en pourcentage."
+
+msgctxt ""
+"help:sale.configuration.shipment_tolerance,sale_under_shipment_tolerance:"
+msgid "The lower quantity accepted in percentage."
+msgstr "La quantité inférieure acceptée en pourcentage."
+
+msgctxt "model:ir.message,text:msg_over_shipment"
+msgid ""
+"The sale line \"%(line)s\" exceeds the over shipment tolerance (%(shipped)s "
+"shipped > %(maximal)s )."
+msgstr ""
+"La ligne de vente « %(line)s » dépasse la tolérance de sur-expédition "
+"(%(shipped)s expédiés > %(maximal)s)."
+
+msgctxt "model:sale.configuration.shipment_tolerance,name:"
+msgid "Sale Configuration Shipment Tolerance"
+msgstr "Configuration de tolérance d'expédition de vente"
+
+msgctxt "view:sale.configuration:"
+msgid "%"
+msgstr "%"
+
+msgctxt "view:sale.configuration:"
+msgid "Sale Shipment Tolerance"
+msgstr "Tolérance d'expédition de vente"
diff --git a/modules/sale_shipment_tolerance/locale/hu.po b/modules/sale_shipment_tolerance/locale/hu.po
new file mode 100644
index 0000000000..eee28e36a4
--- /dev/null
+++ b/modules/sale_shipment_tolerance/locale/hu.po
@@ -0,0 +1,58 @@
+#
+msgid ""
+msgstr "Content-Type: text/plain; charset=utf-8\n"
+
+msgctxt "field:sale.configuration,sale_over_shipment_tolerance:"
+msgid "Sale Over Shipment Tolerance"
+msgstr ""
+
+msgctxt "field:sale.configuration,sale_under_shipment_tolerance:"
+msgid "Sale Under Shipment Tolerance"
+msgstr ""
+
+msgctxt ""
+"field:sale.configuration.shipment_tolerance,sale_over_shipment_tolerance:"
+msgid "Sale Over Shipment Tolerance"
+msgstr ""
+
+msgctxt ""
+"field:sale.configuration.shipment_tolerance,sale_under_shipment_tolerance:"
+msgid "Sale Under Shipment Tolerance"
+msgstr ""
+
+msgctxt "help:sale.configuration,sale_over_shipment_tolerance:"
+msgid "The upper quantity accepted in percentage."
+msgstr ""
+
+msgctxt "help:sale.configuration,sale_under_shipment_tolerance:"
+msgid "The lower quantity accepted in percentage."
+msgstr ""
+
+msgctxt ""
+"help:sale.configuration.shipment_tolerance,sale_over_shipment_tolerance:"
+msgid "The upper quantity accepted in percentage."
+msgstr ""
+
+msgctxt ""
+"help:sale.configuration.shipment_tolerance,sale_under_shipment_tolerance:"
+msgid "The lower quantity accepted in percentage."
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_over_shipment"
+msgid ""
+"The sale line \"%(line)s\" exceeds the over shipment tolerance (%(shipped)s "
+"shipped > %(maximal)s )."
+msgstr ""
+
+msgctxt "model:sale.configuration.shipment_tolerance,name:"
+msgid "Sale Configuration Shipment Tolerance"
+msgstr ""
+
+#, fuzzy
+msgctxt "view:sale.configuration:"
+msgid "%"
+msgstr "%"
+
+msgctxt "view:sale.configuration:"
+msgid "Sale Shipment Tolerance"
+msgstr ""
diff --git a/modules/sale_shipment_tolerance/locale/id.po b/modules/sale_shipment_tolerance/locale/id.po
new file mode 100644
index 0000000000..0d5149cb6d
--- /dev/null
+++ b/modules/sale_shipment_tolerance/locale/id.po
@@ -0,0 +1,57 @@
+#
+msgid ""
+msgstr "Content-Type: text/plain; charset=utf-8\n"
+
+msgctxt "field:sale.configuration,sale_over_shipment_tolerance:"
+msgid "Sale Over Shipment Tolerance"
+msgstr ""
+
+msgctxt "field:sale.configuration,sale_under_shipment_tolerance:"
+msgid "Sale Under Shipment Tolerance"
+msgstr ""
+
+msgctxt ""
+"field:sale.configuration.shipment_tolerance,sale_over_shipment_tolerance:"
+msgid "Sale Over Shipment Tolerance"
+msgstr ""
+
+msgctxt ""
+"field:sale.configuration.shipment_tolerance,sale_under_shipment_tolerance:"
+msgid "Sale Under Shipment Tolerance"
+msgstr ""
+
+msgctxt "help:sale.configuration,sale_over_shipment_tolerance:"
+msgid "The upper quantity accepted in percentage."
+msgstr ""
+
+msgctxt "help:sale.configuration,sale_under_shipment_tolerance:"
+msgid "The lower quantity accepted in percentage."
+msgstr ""
+
+msgctxt ""
+"help:sale.configuration.shipment_tolerance,sale_over_shipment_tolerance:"
+msgid "The upper quantity accepted in percentage."
+msgstr ""
+
+msgctxt ""
+"help:sale.configuration.shipment_tolerance,sale_under_shipment_tolerance:"
+msgid "The lower quantity accepted in percentage."
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_over_shipment"
+msgid ""
+"The sale line \"%(line)s\" exceeds the over shipment tolerance (%(shipped)s "
+"shipped > %(maximal)s )."
+msgstr ""
+
+msgctxt "model:sale.configuration.shipment_tolerance,name:"
+msgid "Sale Configuration Shipment Tolerance"
+msgstr ""
+
+msgctxt "view:sale.configuration:"
+msgid "%"
+msgstr "%"
+
+msgctxt "view:sale.configuration:"
+msgid "Sale Shipment Tolerance"
+msgstr ""
diff --git a/modules/sale_shipment_tolerance/locale/it.po b/modules/sale_shipment_tolerance/locale/it.po
new file mode 100644
index 0000000000..eee28e36a4
--- /dev/null
+++ b/modules/sale_shipment_tolerance/locale/it.po
@@ -0,0 +1,58 @@
+#
+msgid ""
+msgstr "Content-Type: text/plain; charset=utf-8\n"
+
+msgctxt "field:sale.configuration,sale_over_shipment_tolerance:"
+msgid "Sale Over Shipment Tolerance"
+msgstr ""
+
+msgctxt "field:sale.configuration,sale_under_shipment_tolerance:"
+msgid "Sale Under Shipment Tolerance"
+msgstr ""
+
+msgctxt ""
+"field:sale.configuration.shipment_tolerance,sale_over_shipment_tolerance:"
+msgid "Sale Over Shipment Tolerance"
+msgstr ""
+
+msgctxt ""
+"field:sale.configuration.shipment_tolerance,sale_under_shipment_tolerance:"
+msgid "Sale Under Shipment Tolerance"
+msgstr ""
+
+msgctxt "help:sale.configuration,sale_over_shipment_tolerance:"
+msgid "The upper quantity accepted in percentage."
+msgstr ""
+
+msgctxt "help:sale.configuration,sale_under_shipment_tolerance:"
+msgid "The lower quantity accepted in percentage."
+msgstr ""
+
+msgctxt ""
+"help:sale.configuration.shipment_tolerance,sale_over_shipment_tolerance:"
+msgid "The upper quantity accepted in percentage."
+msgstr ""
+
+msgctxt ""
+"help:sale.configuration.shipment_tolerance,sale_under_shipment_tolerance:"
+msgid "The lower quantity accepted in percentage."
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_over_shipment"
+msgid ""
+"The sale line \"%(line)s\" exceeds the over shipment tolerance (%(shipped)s "
+"shipped > %(maximal)s )."
+msgstr ""
+
+msgctxt "model:sale.configuration.shipment_tolerance,name:"
+msgid "Sale Configuration Shipment Tolerance"
+msgstr ""
+
+#, fuzzy
+msgctxt "view:sale.configuration:"
+msgid "%"
+msgstr "%"
+
+msgctxt "view:sale.configuration:"
+msgid "Sale Shipment Tolerance"
+msgstr ""
diff --git a/modules/sale_shipment_tolerance/locale/lo.po b/modules/sale_shipment_tolerance/locale/lo.po
new file mode 100644
index 0000000000..eee28e36a4
--- /dev/null
+++ b/modules/sale_shipment_tolerance/locale/lo.po
@@ -0,0 +1,58 @@
+#
+msgid ""
+msgstr "Content-Type: text/plain; charset=utf-8\n"
+
+msgctxt "field:sale.configuration,sale_over_shipment_tolerance:"
+msgid "Sale Over Shipment Tolerance"
+msgstr ""
+
+msgctxt "field:sale.configuration,sale_under_shipment_tolerance:"
+msgid "Sale Under Shipment Tolerance"
+msgstr ""
+
+msgctxt ""
+"field:sale.configuration.shipment_tolerance,sale_over_shipment_tolerance:"
+msgid "Sale Over Shipment Tolerance"
+msgstr ""
+
+msgctxt ""
+"field:sale.configuration.shipment_tolerance,sale_under_shipment_tolerance:"
+msgid "Sale Under Shipment Tolerance"
+msgstr ""
+
+msgctxt "help:sale.configuration,sale_over_shipment_tolerance:"
+msgid "The upper quantity accepted in percentage."
+msgstr ""
+
+msgctxt "help:sale.configuration,sale_under_shipment_tolerance:"
+msgid "The lower quantity accepted in percentage."
+msgstr ""
+
+msgctxt ""
+"help:sale.configuration.shipment_tolerance,sale_over_shipment_tolerance:"
+msgid "The upper quantity accepted in percentage."
+msgstr ""
+
+msgctxt ""
+"help:sale.configuration.shipment_tolerance,sale_under_shipment_tolerance:"
+msgid "The lower quantity accepted in percentage."
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_over_shipment"
+msgid ""
+"The sale line \"%(line)s\" exceeds the over shipment tolerance (%(shipped)s "
+"shipped > %(maximal)s )."
+msgstr ""
+
+msgctxt "model:sale.configuration.shipment_tolerance,name:"
+msgid "Sale Configuration Shipment Tolerance"
+msgstr ""
+
+#, fuzzy
+msgctxt "view:sale.configuration:"
+msgid "%"
+msgstr "%"
+
+msgctxt "view:sale.configuration:"
+msgid "Sale Shipment Tolerance"
+msgstr ""
diff --git a/modules/sale_shipment_tolerance/locale/lt.po b/modules/sale_shipment_tolerance/locale/lt.po
new file mode 100644
index 0000000000..eee28e36a4
--- /dev/null
+++ b/modules/sale_shipment_tolerance/locale/lt.po
@@ -0,0 +1,58 @@
+#
+msgid ""
+msgstr "Content-Type: text/plain; charset=utf-8\n"
+
+msgctxt "field:sale.configuration,sale_over_shipment_tolerance:"
+msgid "Sale Over Shipment Tolerance"
+msgstr ""
+
+msgctxt "field:sale.configuration,sale_under_shipment_tolerance:"
+msgid "Sale Under Shipment Tolerance"
+msgstr ""
+
+msgctxt ""
+"field:sale.configuration.shipment_tolerance,sale_over_shipment_tolerance:"
+msgid "Sale Over Shipment Tolerance"
+msgstr ""
+
+msgctxt ""
+"field:sale.configuration.shipment_tolerance,sale_under_shipment_tolerance:"
+msgid "Sale Under Shipment Tolerance"
+msgstr ""
+
+msgctxt "help:sale.configuration,sale_over_shipment_tolerance:"
+msgid "The upper quantity accepted in percentage."
+msgstr ""
+
+msgctxt "help:sale.configuration,sale_under_shipment_tolerance:"
+msgid "The lower quantity accepted in percentage."
+msgstr ""
+
+msgctxt ""
+"help:sale.configuration.shipment_tolerance,sale_over_shipment_tolerance:"
+msgid "The upper quantity accepted in percentage."
+msgstr ""
+
+msgctxt ""
+"help:sale.configuration.shipment_tolerance,sale_under_shipment_tolerance:"
+msgid "The lower quantity accepted in percentage."
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_over_shipment"
+msgid ""
+"The sale line \"%(line)s\" exceeds the over shipment tolerance (%(shipped)s "
+"shipped > %(maximal)s )."
+msgstr ""
+
+msgctxt "model:sale.configuration.shipment_tolerance,name:"
+msgid "Sale Configuration Shipment Tolerance"
+msgstr ""
+
+#, fuzzy
+msgctxt "view:sale.configuration:"
+msgid "%"
+msgstr "%"
+
+msgctxt "view:sale.configuration:"
+msgid "Sale Shipment Tolerance"
+msgstr ""
diff --git a/modules/sale_shipment_tolerance/locale/nl.po b/modules/sale_shipment_tolerance/locale/nl.po
new file mode 100644
index 0000000000..e014f48332
--- /dev/null
+++ b/modules/sale_shipment_tolerance/locale/nl.po
@@ -0,0 +1,59 @@
+#
+msgid ""
+msgstr "Content-Type: text/plain; charset=utf-8\n"
+
+msgctxt "field:sale.configuration,sale_over_shipment_tolerance:"
+msgid "Sale Over Shipment Tolerance"
+msgstr "verkoop boven verzendingstolerantie"
+
+msgctxt "field:sale.configuration,sale_under_shipment_tolerance:"
+msgid "Sale Under Shipment Tolerance"
+msgstr "Verkoop onder verzendtolerantie"
+
+msgctxt ""
+"field:sale.configuration.shipment_tolerance,sale_over_shipment_tolerance:"
+msgid "Sale Over Shipment Tolerance"
+msgstr "verkoop boven verzendingstolerantie"
+
+msgctxt ""
+"field:sale.configuration.shipment_tolerance,sale_under_shipment_tolerance:"
+msgid "Sale Under Shipment Tolerance"
+msgstr "Verkoop onder verzendtolerantie"
+
+msgctxt "help:sale.configuration,sale_over_shipment_tolerance:"
+msgid "The upper quantity accepted in percentage."
+msgstr "De maximaal geaccepteerde hoeveelheid in procent."
+
+msgctxt "help:sale.configuration,sale_under_shipment_tolerance:"
+msgid "The lower quantity accepted in percentage."
+msgstr "De minimaal geaccepteerde hoeveelheid in procent."
+
+msgctxt ""
+"help:sale.configuration.shipment_tolerance,sale_over_shipment_tolerance:"
+msgid "The upper quantity accepted in percentage."
+msgstr "De maximaal geaccepteerde hoeveelheid in procent."
+
+msgctxt ""
+"help:sale.configuration.shipment_tolerance,sale_under_shipment_tolerance:"
+msgid "The lower quantity accepted in percentage."
+msgstr "De minimaal geaccepteerde hoeveelheid in procent."
+
+msgctxt "model:ir.message,text:msg_over_shipment"
+msgid ""
+"The sale line \"%(line)s\" exceeds the over shipment tolerance (%(shipped)s "
+"shipped > %(maximal)s )."
+msgstr ""
+"De verkoopregel \"%(line)s\" overschrijdt de tolerantiegrens voor verzending"
+" (%(shipped)s shipped > %(maximal)s ).."
+
+msgctxt "model:sale.configuration.shipment_tolerance,name:"
+msgid "Sale Configuration Shipment Tolerance"
+msgstr "Verkoopconfiguratie Verzendtolerantie"
+
+msgctxt "view:sale.configuration:"
+msgid "%"
+msgstr "%"
+
+msgctxt "view:sale.configuration:"
+msgid "Sale Shipment Tolerance"
+msgstr "verkoop Verzendtolerantie"
diff --git a/modules/sale_shipment_tolerance/locale/pl.po b/modules/sale_shipment_tolerance/locale/pl.po
new file mode 100644
index 0000000000..0d5149cb6d
--- /dev/null
+++ b/modules/sale_shipment_tolerance/locale/pl.po
@@ -0,0 +1,57 @@
+#
+msgid ""
+msgstr "Content-Type: text/plain; charset=utf-8\n"
+
+msgctxt "field:sale.configuration,sale_over_shipment_tolerance:"
+msgid "Sale Over Shipment Tolerance"
+msgstr ""
+
+msgctxt "field:sale.configuration,sale_under_shipment_tolerance:"
+msgid "Sale Under Shipment Tolerance"
+msgstr ""
+
+msgctxt ""
+"field:sale.configuration.shipment_tolerance,sale_over_shipment_tolerance:"
+msgid "Sale Over Shipment Tolerance"
+msgstr ""
+
+msgctxt ""
+"field:sale.configuration.shipment_tolerance,sale_under_shipment_tolerance:"
+msgid "Sale Under Shipment Tolerance"
+msgstr ""
+
+msgctxt "help:sale.configuration,sale_over_shipment_tolerance:"
+msgid "The upper quantity accepted in percentage."
+msgstr ""
+
+msgctxt "help:sale.configuration,sale_under_shipment_tolerance:"
+msgid "The lower quantity accepted in percentage."
+msgstr ""
+
+msgctxt ""
+"help:sale.configuration.shipment_tolerance,sale_over_shipment_tolerance:"
+msgid "The upper quantity accepted in percentage."
+msgstr ""
+
+msgctxt ""
+"help:sale.configuration.shipment_tolerance,sale_under_shipment_tolerance:"
+msgid "The lower quantity accepted in percentage."
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_over_shipment"
+msgid ""
+"The sale line \"%(line)s\" exceeds the over shipment tolerance (%(shipped)s "
+"shipped > %(maximal)s )."
+msgstr ""
+
+msgctxt "model:sale.configuration.shipment_tolerance,name:"
+msgid "Sale Configuration Shipment Tolerance"
+msgstr ""
+
+msgctxt "view:sale.configuration:"
+msgid "%"
+msgstr "%"
+
+msgctxt "view:sale.configuration:"
+msgid "Sale Shipment Tolerance"
+msgstr ""
diff --git a/modules/sale_shipment_tolerance/locale/pt.po b/modules/sale_shipment_tolerance/locale/pt.po
new file mode 100644
index 0000000000..02fb3b5440
--- /dev/null
+++ b/modules/sale_shipment_tolerance/locale/pt.po
@@ -0,0 +1,58 @@
+#
+msgid ""
+msgstr "Content-Type: text/plain; charset=utf-8\n"
+
+msgctxt "field:sale.configuration,sale_over_shipment_tolerance:"
+msgid "Sale Over Shipment Tolerance"
+msgstr "Tolerância de Carregamento da Remessa de Venda"
+
+msgctxt "field:sale.configuration,sale_under_shipment_tolerance:"
+msgid "Sale Under Shipment Tolerance"
+msgstr "Tolerância de Falta de Carregamento de Venda"
+
+msgctxt ""
+"field:sale.configuration.shipment_tolerance,sale_over_shipment_tolerance:"
+msgid "Sale Over Shipment Tolerance"
+msgstr "Tolerância de Carregamento da Remessa de Venda"
+
+msgctxt ""
+"field:sale.configuration.shipment_tolerance,sale_under_shipment_tolerance:"
+msgid "Sale Under Shipment Tolerance"
+msgstr "Tolerância de Falta de Carregamento de Venda"
+
+msgctxt "help:sale.configuration,sale_over_shipment_tolerance:"
+msgid "The upper quantity accepted in percentage."
+msgstr "A porcentagem de quantidade excedente aceita."
+
+msgctxt "help:sale.configuration,sale_under_shipment_tolerance:"
+msgid "The lower quantity accepted in percentage."
+msgstr "A porcentagem mínima a aceitar como enviado."
+
+msgctxt ""
+"help:sale.configuration.shipment_tolerance,sale_over_shipment_tolerance:"
+msgid "The upper quantity accepted in percentage."
+msgstr "A porcentagem da quantidade excessiva a ser aceita."
+
+msgctxt ""
+"help:sale.configuration.shipment_tolerance,sale_under_shipment_tolerance:"
+msgid "The lower quantity accepted in percentage."
+msgstr "A porcentagem da quantidade mínima a ser aceita como enviado."
+
+#, fuzzy
+msgctxt "model:ir.message,text:msg_over_shipment"
+msgid ""
+"The sale line \"%(line)s\" exceeds the over shipment tolerance (%(shipped)s "
+"shipped > %(maximal)s )."
+msgstr "A Linha de Venda \"%s\" excedeu a tolerância de carregamento da remessa."
+
+msgctxt "model:sale.configuration.shipment_tolerance,name:"
+msgid "Sale Configuration Shipment Tolerance"
+msgstr "Configuração da tolerância de remessa de venda"
+
+msgctxt "view:sale.configuration:"
+msgid "%"
+msgstr "%"
+
+msgctxt "view:sale.configuration:"
+msgid "Sale Shipment Tolerance"
+msgstr "Tolerância de Remessa de Venda"
diff --git a/modules/sale_shipment_tolerance/locale/ro.po b/modules/sale_shipment_tolerance/locale/ro.po
new file mode 100644
index 0000000000..74a4603300
--- /dev/null
+++ b/modules/sale_shipment_tolerance/locale/ro.po
@@ -0,0 +1,57 @@
+#
+msgid ""
+msgstr "Content-Type: text/plain; charset=utf-8\n"
+
+msgctxt "field:sale.configuration,sale_over_shipment_tolerance:"
+msgid "Sale Over Shipment Tolerance"
+msgstr ""
+
+msgctxt "field:sale.configuration,sale_under_shipment_tolerance:"
+msgid "Sale Under Shipment Tolerance"
+msgstr ""
+
+msgctxt ""
+"field:sale.configuration.shipment_tolerance,sale_over_shipment_tolerance:"
+msgid "Sale Over Shipment Tolerance"
+msgstr ""
+
+msgctxt ""
+"field:sale.configuration.shipment_tolerance,sale_under_shipment_tolerance:"
+msgid "Sale Under Shipment Tolerance"
+msgstr ""
+
+msgctxt "help:sale.configuration,sale_over_shipment_tolerance:"
+msgid "The upper quantity accepted in percentage."
+msgstr ""
+
+msgctxt "help:sale.configuration,sale_under_shipment_tolerance:"
+msgid "The lower quantity accepted in percentage."
+msgstr ""
+
+msgctxt ""
+"help:sale.configuration.shipment_tolerance,sale_over_shipment_tolerance:"
+msgid "The upper quantity accepted in percentage."
+msgstr ""
+
+msgctxt ""
+"help:sale.configuration.shipment_tolerance,sale_under_shipment_tolerance:"
+msgid "The lower quantity accepted in percentage."
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_over_shipment"
+msgid ""
+"The sale line \"%(line)s\" exceeds the over shipment tolerance (%(shipped)s "
+"shipped > %(maximal)s )."
+msgstr ""
+
+msgctxt "model:sale.configuration.shipment_tolerance,name:"
+msgid "Sale Configuration Shipment Tolerance"
+msgstr ""
+
+msgctxt "view:sale.configuration:"
+msgid "%"
+msgstr ""
+
+msgctxt "view:sale.configuration:"
+msgid "Sale Shipment Tolerance"
+msgstr ""
diff --git a/modules/sale_shipment_tolerance/locale/ru.po b/modules/sale_shipment_tolerance/locale/ru.po
new file mode 100644
index 0000000000..eee28e36a4
--- /dev/null
+++ b/modules/sale_shipment_tolerance/locale/ru.po
@@ -0,0 +1,58 @@
+#
+msgid ""
+msgstr "Content-Type: text/plain; charset=utf-8\n"
+
+msgctxt "field:sale.configuration,sale_over_shipment_tolerance:"
+msgid "Sale Over Shipment Tolerance"
+msgstr ""
+
+msgctxt "field:sale.configuration,sale_under_shipment_tolerance:"
+msgid "Sale Under Shipment Tolerance"
+msgstr ""
+
+msgctxt ""
+"field:sale.configuration.shipment_tolerance,sale_over_shipment_tolerance:"
+msgid "Sale Over Shipment Tolerance"
+msgstr ""
+
+msgctxt ""
+"field:sale.configuration.shipment_tolerance,sale_under_shipment_tolerance:"
+msgid "Sale Under Shipment Tolerance"
+msgstr ""
+
+msgctxt "help:sale.configuration,sale_over_shipment_tolerance:"
+msgid "The upper quantity accepted in percentage."
+msgstr ""
+
+msgctxt "help:sale.configuration,sale_under_shipment_tolerance:"
+msgid "The lower quantity accepted in percentage."
+msgstr ""
+
+msgctxt ""
+"help:sale.configuration.shipment_tolerance,sale_over_shipment_tolerance:"
+msgid "The upper quantity accepted in percentage."
+msgstr ""
+
+msgctxt ""
+"help:sale.configuration.shipment_tolerance,sale_under_shipment_tolerance:"
+msgid "The lower quantity accepted in percentage."
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_over_shipment"
+msgid ""
+"The sale line \"%(line)s\" exceeds the over shipment tolerance (%(shipped)s "
+"shipped > %(maximal)s )."
+msgstr ""
+
+msgctxt "model:sale.configuration.shipment_tolerance,name:"
+msgid "Sale Configuration Shipment Tolerance"
+msgstr ""
+
+#, fuzzy
+msgctxt "view:sale.configuration:"
+msgid "%"
+msgstr "%"
+
+msgctxt "view:sale.configuration:"
+msgid "Sale Shipment Tolerance"
+msgstr ""
diff --git a/modules/sale_shipment_tolerance/locale/sl.po b/modules/sale_shipment_tolerance/locale/sl.po
new file mode 100644
index 0000000000..eee28e36a4
--- /dev/null
+++ b/modules/sale_shipment_tolerance/locale/sl.po
@@ -0,0 +1,58 @@
+#
+msgid ""
+msgstr "Content-Type: text/plain; charset=utf-8\n"
+
+msgctxt "field:sale.configuration,sale_over_shipment_tolerance:"
+msgid "Sale Over Shipment Tolerance"
+msgstr ""
+
+msgctxt "field:sale.configuration,sale_under_shipment_tolerance:"
+msgid "Sale Under Shipment Tolerance"
+msgstr ""
+
+msgctxt ""
+"field:sale.configuration.shipment_tolerance,sale_over_shipment_tolerance:"
+msgid "Sale Over Shipment Tolerance"
+msgstr ""
+
+msgctxt ""
+"field:sale.configuration.shipment_tolerance,sale_under_shipment_tolerance:"
+msgid "Sale Under Shipment Tolerance"
+msgstr ""
+
+msgctxt "help:sale.configuration,sale_over_shipment_tolerance:"
+msgid "The upper quantity accepted in percentage."
+msgstr ""
+
+msgctxt "help:sale.configuration,sale_under_shipment_tolerance:"
+msgid "The lower quantity accepted in percentage."
+msgstr ""
+
+msgctxt ""
+"help:sale.configuration.shipment_tolerance,sale_over_shipment_tolerance:"
+msgid "The upper quantity accepted in percentage."
+msgstr ""
+
+msgctxt ""
+"help:sale.configuration.shipment_tolerance,sale_under_shipment_tolerance:"
+msgid "The lower quantity accepted in percentage."
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_over_shipment"
+msgid ""
+"The sale line \"%(line)s\" exceeds the over shipment tolerance (%(shipped)s "
+"shipped > %(maximal)s )."
+msgstr ""
+
+msgctxt "model:sale.configuration.shipment_tolerance,name:"
+msgid "Sale Configuration Shipment Tolerance"
+msgstr ""
+
+#, fuzzy
+msgctxt "view:sale.configuration:"
+msgid "%"
+msgstr "%"
+
+msgctxt "view:sale.configuration:"
+msgid "Sale Shipment Tolerance"
+msgstr ""
diff --git a/modules/sale_shipment_tolerance/locale/tr.po b/modules/sale_shipment_tolerance/locale/tr.po
new file mode 100644
index 0000000000..0d5149cb6d
--- /dev/null
+++ b/modules/sale_shipment_tolerance/locale/tr.po
@@ -0,0 +1,57 @@
+#
+msgid ""
+msgstr "Content-Type: text/plain; charset=utf-8\n"
+
+msgctxt "field:sale.configuration,sale_over_shipment_tolerance:"
+msgid "Sale Over Shipment Tolerance"
+msgstr ""
+
+msgctxt "field:sale.configuration,sale_under_shipment_tolerance:"
+msgid "Sale Under Shipment Tolerance"
+msgstr ""
+
+msgctxt ""
+"field:sale.configuration.shipment_tolerance,sale_over_shipment_tolerance:"
+msgid "Sale Over Shipment Tolerance"
+msgstr ""
+
+msgctxt ""
+"field:sale.configuration.shipment_tolerance,sale_under_shipment_tolerance:"
+msgid "Sale Under Shipment Tolerance"
+msgstr ""
+
+msgctxt "help:sale.configuration,sale_over_shipment_tolerance:"
+msgid "The upper quantity accepted in percentage."
+msgstr ""
+
+msgctxt "help:sale.configuration,sale_under_shipment_tolerance:"
+msgid "The lower quantity accepted in percentage."
+msgstr ""
+
+msgctxt ""
+"help:sale.configuration.shipment_tolerance,sale_over_shipment_tolerance:"
+msgid "The upper quantity accepted in percentage."
+msgstr ""
+
+msgctxt ""
+"help:sale.configuration.shipment_tolerance,sale_under_shipment_tolerance:"
+msgid "The lower quantity accepted in percentage."
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_over_shipment"
+msgid ""
+"The sale line \"%(line)s\" exceeds the over shipment tolerance (%(shipped)s "
+"shipped > %(maximal)s )."
+msgstr ""
+
+msgctxt "model:sale.configuration.shipment_tolerance,name:"
+msgid "Sale Configuration Shipment Tolerance"
+msgstr ""
+
+msgctxt "view:sale.configuration:"
+msgid "%"
+msgstr "%"
+
+msgctxt "view:sale.configuration:"
+msgid "Sale Shipment Tolerance"
+msgstr ""
diff --git a/modules/sale_shipment_tolerance/locale/zh_CN.po b/modules/sale_shipment_tolerance/locale/zh_CN.po
new file mode 100644
index 0000000000..eee28e36a4
--- /dev/null
+++ b/modules/sale_shipment_tolerance/locale/zh_CN.po
@@ -0,0 +1,58 @@
+#
+msgid ""
+msgstr "Content-Type: text/plain; charset=utf-8\n"
+
+msgctxt "field:sale.configuration,sale_over_shipment_tolerance:"
+msgid "Sale Over Shipment Tolerance"
+msgstr ""
+
+msgctxt "field:sale.configuration,sale_under_shipment_tolerance:"
+msgid "Sale Under Shipment Tolerance"
+msgstr ""
+
+msgctxt ""
+"field:sale.configuration.shipment_tolerance,sale_over_shipment_tolerance:"
+msgid "Sale Over Shipment Tolerance"
+msgstr ""
+
+msgctxt ""
+"field:sale.configuration.shipment_tolerance,sale_under_shipment_tolerance:"
+msgid "Sale Under Shipment Tolerance"
+msgstr ""
+
+msgctxt "help:sale.configuration,sale_over_shipment_tolerance:"
+msgid "The upper quantity accepted in percentage."
+msgstr ""
+
+msgctxt "help:sale.configuration,sale_under_shipment_tolerance:"
+msgid "The lower quantity accepted in percentage."
+msgstr ""
+
+msgctxt ""
+"help:sale.configuration.shipment_tolerance,sale_over_shipment_tolerance:"
+msgid "The upper quantity accepted in percentage."
+msgstr ""
+
+msgctxt ""
+"help:sale.configuration.shipment_tolerance,sale_under_shipment_tolerance:"
+msgid "The lower quantity accepted in percentage."
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_over_shipment"
+msgid ""
+"The sale line \"%(line)s\" exceeds the over shipment tolerance (%(shipped)s "
+"shipped > %(maximal)s )."
+msgstr ""
+
+msgctxt "model:sale.configuration.shipment_tolerance,name:"
+msgid "Sale Configuration Shipment Tolerance"
+msgstr ""
+
+#, fuzzy
+msgctxt "view:sale.configuration:"
+msgid "%"
+msgstr "%"
+
+msgctxt "view:sale.configuration:"
+msgid "Sale Shipment Tolerance"
+msgstr ""
diff --git a/modules/sale_shipment_tolerance/message.xml b/modules/sale_shipment_tolerance/message.xml
new file mode 100644
index 0000000000..31d4ba5639
--- /dev/null
+++ b/modules/sale_shipment_tolerance/message.xml
@@ -0,0 +1,10 @@
+
+
+
+
+
+ The sale line "%(line)s" exceeds the over shipment tolerance (%(shipped)s shipped > %(maximal)s ).
+
+
+
diff --git a/modules/sale_shipment_tolerance/sale.py b/modules/sale_shipment_tolerance/sale.py
new file mode 100644
index 0000000000..a2beba65a9
--- /dev/null
+++ b/modules/sale_shipment_tolerance/sale.py
@@ -0,0 +1,72 @@
+# This file is part of Tryton. The COPYRIGHT file at the top level of
+# this repository contains the full copyright notices and license terms.
+from trytond.i18n import gettext
+from trytond.pool import PoolMeta, Pool
+
+from .exceptions import OverShipmentWarning
+
+
+class Line(metaclass=PoolMeta):
+ __name__ = 'sale.line'
+
+ def _test_under_shipment_tolerance(self, quantity):
+ pool = Pool()
+ Configuration = pool.get('sale.configuration')
+ if quantity:
+ config = Configuration(1)
+ tolerance = config.get_multivalue(
+ 'sale_under_shipment_tolerance', company=self.company.id)
+ if tolerance is not None:
+ minimal_quantity = abs(self.quantity * (1 - tolerance))
+ minimal_quantity = self.unit.round(minimal_quantity)
+ quantity = self.unit.round(quantity)
+ return quantity <= minimal_quantity < abs(self.quantity)
+ return False
+
+ @property
+ def _move_remaining_quantity(self):
+ quantity = super()._move_remaining_quantity
+ if self._test_under_shipment_tolerance(quantity):
+ return 0
+ return quantity
+
+ def get_move(self, shipment_type):
+ pool = Pool()
+ Uom = pool.get('product.uom')
+ move = super().get_move(shipment_type)
+ # Compute tolerance only if there is already at least one move.
+ if move and set(self.moves) - set(self.moves_recreated):
+ quantity = Uom.compute_qty(
+ move.uom, move.quantity, self.unit, round=False)
+ if self._test_under_shipment_tolerance(quantity):
+ move = None
+ return move
+
+ def check_over_shipment(self):
+ pool = Pool()
+ Configuration = pool.get('sale.configuration')
+ Warning = pool.get('res.user.warning')
+ Lang = pool.get('ir.lang')
+ config = Configuration(1)
+ lang = Lang.get()
+
+ if self.quantity >= 0:
+ shipment_type = 'out'
+ else:
+ shipment_type = 'in'
+ shipped_quantity = self._get_shipped_quantity(shipment_type)
+ tolerance = config.get_multivalue(
+ 'sale_over_shipment_tolerance', company=self.company.id)
+ if tolerance is not None:
+ maximal_quantity = abs(self.quantity * tolerance)
+ if shipped_quantity > maximal_quantity:
+ name = 'over_shipment_sale_line_%d' % self.id
+ if Warning.check(name):
+ raise OverShipmentWarning(
+ name,
+ gettext('sale_shipment_tolerance.msg_over_shipment',
+ line=self.rec_name,
+ shipped=lang.format(
+ '%.*f', (self.unit.digits, shipped_quantity)),
+ maximal=lang.format(
+ '%.*f', (self.unit.digits, maximal_quantity))))
diff --git a/modules/sale_shipment_tolerance/setup.py b/modules/sale_shipment_tolerance/setup.py
new file mode 100755
index 0000000000..f62055ed4e
--- /dev/null
+++ b/modules/sale_shipment_tolerance/setup.py
@@ -0,0 +1,148 @@
+#!/usr/bin/env python3
+# This file is part of Tryton. The COPYRIGHT file at the top level of
+# this repository contains the full copyright notices and license terms.
+
+import io
+import os
+import re
+from configparser import ConfigParser
+from setuptools import setup, find_packages
+
+
+def read(fname):
+ return io.open(
+ os.path.join(os.path.dirname(__file__), fname),
+ 'r', encoding='utf-8').read()
+
+
+def get_require_version(name):
+ if minor_version % 2:
+ require = '%s >= %s.%s.dev0, < %s.%s'
+ else:
+ require = '%s >= %s.%s, < %s.%s'
+ require %= (name, major_version, minor_version,
+ major_version, minor_version + 1)
+ return require
+
+
+config = ConfigParser()
+config.read_file(open(os.path.join(os.path.dirname(__file__), 'tryton.cfg')))
+info = dict(config.items('tryton'))
+for key in ('depends', 'extras_depend', 'xml'):
+ if key in info:
+ info[key] = info[key].strip().splitlines()
+version = info.get('version', '0.0.1')
+major_version, minor_version, _ = version.split('.', 2)
+major_version = int(major_version)
+minor_version = int(minor_version)
+name = 'trytond_sale_shipment_tolerance'
+
+download_url = 'http://downloads.tryton.org/%s.%s/' % (
+ major_version, minor_version)
+if minor_version % 2:
+ version = '%s.%s.dev0' % (major_version, minor_version)
+ download_url = (
+ 'hg+http://hg.tryton.org/modules/%s#egg=%s-%s' % (
+ name[8:], name, version))
+local_version = []
+if os.environ.get('CI_JOB_ID'):
+ local_version.append(os.environ['CI_JOB_ID'])
+else:
+ for build in ['CI_BUILD_NUMBER', 'CI_JOB_NUMBER']:
+ if os.environ.get(build):
+ local_version.append(os.environ[build])
+ else:
+ local_version = []
+ break
+if local_version:
+ version += '+' + '.'.join(local_version)
+
+requires = []
+for dep in info.get('depends', []):
+ if not re.match(r'(ir|res)(\W|$)', dep):
+ requires.append(get_require_version('trytond_%s' % dep))
+requires.append(get_require_version('trytond'))
+
+tests_require = [get_require_version('proteus')]
+dependency_links = []
+if minor_version % 2:
+ dependency_links.append(
+ 'https://trydevpi.tryton.org/?local_version='
+ + '.'.join(local_version))
+
+setup(name=name,
+ version=version,
+ description='Tryton module to define tolerance for sale shipment',
+ long_description=read('README.rst'),
+ author='Tryton',
+ author_email='bugs@tryton.org',
+ url='http://www.tryton.org/',
+ download_url=download_url,
+ project_urls={
+ "Bug Tracker": 'https://bugs.tryton.org/',
+ "Documentation": 'https://docs.tryton.org/',
+ "Forum": 'https://www.tryton.org/forum',
+ "Source Code": 'https://hg.tryton.org/modules/sale_shipment_tolerance',
+ },
+ keywords='tryton sale shipment tolerance back-order',
+ package_dir={'trytond.modules.sale_shipment_tolerance': '.'},
+ packages=(
+ ['trytond.modules.sale_shipment_tolerance']
+ + ['trytond.modules.sale_shipment_tolerance.%s' % p
+ for p in find_packages()]
+ ),
+ package_data={
+ 'trytond.modules.sale_shipment_tolerance': (info.get('xml', [])
+ + ['tryton.cfg', 'view/*.xml', 'locale/*.po', '*.odt',
+ 'icons/*.svg', 'tests/*.rst']),
+ },
+ classifiers=[
+ 'Development Status :: 5 - Production/Stable',
+ 'Environment :: Plugins',
+ 'Framework :: Tryton',
+ 'Intended Audience :: Developers',
+ 'Intended Audience :: Financial and Insurance Industry',
+ 'Intended Audience :: Legal Industry',
+ 'License :: OSI Approved :: '
+ 'GNU General Public License v3 or later (GPLv3+)',
+ 'Natural Language :: Bulgarian',
+ 'Natural Language :: Catalan',
+ 'Natural Language :: Czech',
+ 'Natural Language :: Dutch',
+ 'Natural Language :: English',
+ 'Natural Language :: Finnish',
+ 'Natural Language :: French',
+ 'Natural Language :: German',
+ 'Natural Language :: Hungarian',
+ 'Natural Language :: Indonesian',
+ 'Natural Language :: Italian',
+ 'Natural Language :: Persian',
+ 'Natural Language :: Portuguese (Brazilian)',
+ 'Natural Language :: Romanian',
+ 'Natural Language :: Russian',
+ 'Natural Language :: Slovenian',
+ 'Natural Language :: Spanish',
+ 'Natural Language :: Turkish',
+ 'Operating System :: OS Independent',
+ 'Programming Language :: Python :: 3',
+ 'Programming Language :: Python :: 3.6',
+ 'Programming Language :: Python :: 3.7',
+ 'Programming Language :: Python :: 3.8',
+ 'Programming Language :: Python :: 3.9',
+ 'Programming Language :: Python :: Implementation :: CPython',
+ 'Programming Language :: Python :: Implementation :: PyPy',
+ 'Topic :: Office/Business',
+ ],
+ license='GPL-3',
+ python_requires='>=3.6',
+ install_requires=requires,
+ dependency_links=dependency_links,
+ zip_safe=False,
+ entry_points="""
+ [trytond.modules]
+ sale_shipment_tolerance = trytond.modules.sale_shipment_tolerance
+ """,
+ test_suite='tests',
+ test_loader='trytond.test_loader:Loader',
+ tests_require=tests_require,
+ )
diff --git a/modules/sale_shipment_tolerance/stock.py b/modules/sale_shipment_tolerance/stock.py
new file mode 100644
index 0000000000..7fa35deade
--- /dev/null
+++ b/modules/sale_shipment_tolerance/stock.py
@@ -0,0 +1,30 @@
+# This file is part of Tryton. The COPYRIGHT file at the top level of
+# this repository contains the full copyright notices and license terms.
+from trytond.model import ModelView, Workflow
+from trytond.pool import PoolMeta, Pool
+
+
+class Move(metaclass=PoolMeta):
+ __name__ = 'stock.move'
+
+ @classmethod
+ def check_over_shipment(cls, moves):
+ pool = Pool()
+ SaleLine = pool.get('sale.line')
+ for move in moves:
+ if isinstance(move.origin, SaleLine):
+ move.origin.check_over_shipment()
+
+ @classmethod
+ @ModelView.button
+ @Workflow.transition('done')
+ def do(cls, moves):
+ super(Move, cls).do(moves)
+ cls.check_over_shipment(moves)
+
+ @classmethod
+ @ModelView.button
+ @Workflow.transition('assigned')
+ def assign(cls, moves):
+ super(Move, cls).assign(moves)
+ cls.check_over_shipment(moves)
diff --git a/modules/sale_shipment_tolerance/tests/__init__.py b/modules/sale_shipment_tolerance/tests/__init__.py
new file mode 100644
index 0000000000..b747b53213
--- /dev/null
+++ b/modules/sale_shipment_tolerance/tests/__init__.py
@@ -0,0 +1,9 @@
+# This file is part of Tryton. The COPYRIGHT file at the top level of
+# this repository contains the full copyright notices and license terms.
+
+try:
+ from trytond.modules.sale_shipment_tolerance.tests.test_sale_shipment_tolerance import suite # noqa: E501
+except ImportError:
+ from .test_sale_shipment_tolerance import suite
+
+__all__ = ['suite']
diff --git a/modules/sale_shipment_tolerance/tests/scenario_sale_over_shipment_tolerance.rst b/modules/sale_shipment_tolerance/tests/scenario_sale_over_shipment_tolerance.rst
new file mode 100644
index 0000000000..106d10d9cd
--- /dev/null
+++ b/modules/sale_shipment_tolerance/tests/scenario_sale_over_shipment_tolerance.rst
@@ -0,0 +1,108 @@
+=====================================
+Sale Over Shipment Tolerance Scenario
+=====================================
+
+Imports::
+
+ >>> from decimal import Decimal
+ >>> from proteus import Model, Wizard
+ >>> from trytond.tests.tools import activate_modules
+ >>> from trytond.modules.company.tests.tools import create_company, \
+ ... get_company
+ >>> from trytond.modules.account.tests.tools import create_chart, \
+ ... get_accounts
+
+Activate modules::
+
+ >>> config = activate_modules('sale_shipment_tolerance')
+
+Create company::
+
+ >>> _ = create_company()
+ >>> company = get_company()
+
+Create chart of accounts::
+
+ >>> _ = create_chart(company)
+ >>> accounts = get_accounts(company)
+ >>> revenue = accounts['revenue']
+
+Create parties::
+
+ >>> Party = Model.get('party.party')
+ >>> customer = Party(name='Customer')
+ >>> customer.save()
+
+Create account category::
+
+ >>> ProductCategory = Model.get('product.category')
+ >>> account_category = ProductCategory(name="Account Category")
+ >>> account_category.accounting = True
+ >>> account_category.account_revenue = revenue
+ >>> account_category.save()
+
+Create product::
+
+ >>> ProductUom = Model.get('product.uom')
+ >>> unit, = ProductUom.find([('name', '=', 'Unit')])
+ >>> ProductTemplate = Model.get('product.template')
+ >>> template = ProductTemplate()
+ >>> template.name = 'product'
+ >>> template.default_uom = unit
+ >>> template.type = 'goods'
+ >>> template.salable = True
+ >>> template.list_price = Decimal('10')
+ >>> template.account_category = account_category
+ >>> template.save()
+ >>> product, = template.products
+
+Set tolerance::
+
+ >>> Configuration = Model.get('sale.configuration')
+ >>> config = Configuration(1)
+ >>> config.sale_over_shipment_tolerance = 1.2
+ >>> config.save()
+
+Sale 10 products::
+
+ >>> Sale = Model.get('sale.sale')
+ >>> sale = Sale()
+ >>> sale.party = customer
+ >>> sale_line = sale.lines.new()
+ >>> sale_line.product = product
+ >>> sale_line.quantity = 10
+ >>> sale.click('quote')
+ >>> sale.click('confirm')
+ >>> sale.click('process')
+
+Prevent over ship 13 products::
+
+ >>> shipment, = sale.shipments
+ >>> shipment.click('draft')
+ >>> move, = shipment.outgoing_moves
+ >>> move.quantity = 13
+ >>> shipment.click('wait')
+ >>> shipment.click('assign_force')
+ >>> shipment.click('pick')
+ >>> shipment.click('pack') # doctest: +IGNORE_EXCEPTION_DETAIL
+ Traceback (most recent call last):
+ ...
+ OverShipmentWarning: ...
+
+Over ship 12 products::
+
+ >>> shipment.click('wait')
+ >>> shipment.click('draft')
+ >>> move, = shipment.outgoing_moves
+ >>> move.quantity = 12
+ >>> shipment.click('wait')
+ >>> shipment.click('assign_force')
+ >>> shipment.click('pick')
+ >>> shipment.click('pack')
+ >>> shipment.click('done')
+
+No new shipment as shipped inside tolerance::
+
+ >>> sale.reload()
+ >>> len(sale.shipments)
+ 1
diff --git a/modules/sale_shipment_tolerance/tests/scenario_sale_under_shipment_tolerance.rst b/modules/sale_shipment_tolerance/tests/scenario_sale_under_shipment_tolerance.rst
new file mode 100644
index 0000000000..83caf4642b
--- /dev/null
+++ b/modules/sale_shipment_tolerance/tests/scenario_sale_under_shipment_tolerance.rst
@@ -0,0 +1,105 @@
+======================================
+Sale Under Shipment Tolerance Scenario
+======================================
+
+Imports::
+
+ >>> from decimal import Decimal
+ >>> from proteus import Model, Wizard
+ >>> from trytond.tests.tools import activate_modules
+ >>> from trytond.modules.company.tests.tools import create_company, \
+ ... get_company
+ >>> from trytond.modules.account.tests.tools import create_chart, \
+ ... get_accounts
+
+Activate modules::
+
+ >>> config = activate_modules('sale_shipment_tolerance')
+
+Create company::
+
+ >>> _ = create_company()
+ >>> company = get_company()
+
+Create chart of accounts::
+
+ >>> _ = create_chart(company)
+ >>> accounts = get_accounts(company)
+ >>> revenue = accounts['revenue']
+
+Create parties::
+
+ >>> Party = Model.get('party.party')
+ >>> customer = Party(name='Customer')
+ >>> customer.save()
+
+Create account category::
+
+ >>> ProductCategory = Model.get('product.category')
+ >>> account_category = ProductCategory(name="Account Category")
+ >>> account_category.accounting = True
+ >>> account_category.account_revenue = revenue
+ >>> account_category.save()
+
+Create product::
+
+ >>> ProductUom = Model.get('product.uom')
+ >>> unit, = ProductUom.find([('name', '=', 'Unit')])
+ >>> ProductTemplate = Model.get('product.template')
+ >>> template = ProductTemplate()
+ >>> template.name = 'product'
+ >>> template.default_uom = unit
+ >>> template.type = 'goods'
+ >>> template.salable = True
+ >>> template.list_price = Decimal('10')
+ >>> template.account_category = account_category
+ >>> template.save()
+ >>> product, = template.products
+
+Set tolerance::
+
+ >>> Configuration = Model.get('sale.configuration')
+ >>> config = Configuration(1)
+ >>> config.sale_under_shipment_tolerance = 0.9
+ >>> config.save()
+
+Sale 10 products::
+
+ >>> Sale = Model.get('sale.sale')
+ >>> sale = Sale()
+ >>> sale.party = customer
+ >>> sale_line = sale.lines.new()
+ >>> sale_line.product = product
+ >>> sale_line.quantity = 10
+ >>> sale.click('quote')
+ >>> sale.click('confirm')
+ >>> sale.click('process')
+
+Under ship 5 products::
+
+ >>> shipment, = sale.shipments
+ >>> move, = shipment.inventory_moves
+ >>> move.quantity = 5
+ >>> shipment.click('assign_force')
+ >>> shipment.click('pick')
+ >>> shipment.click('pack')
+ >>> shipment.click('done')
+
+Under ship 4 products::
+
+ >>> sale.reload()
+ >>> _, shipment = sale.shipments
+ >>> move, = shipment.inventory_moves
+ >>> move.quantity = 4
+ >>> shipment.click('assign_force')
+ >>> shipment.click('pick')
+ >>> shipment.click('pack')
+ >>> shipment.click('done')
+
+No new shipment as shipped inside tolerance::
+
+ >>> sale.reload()
+ >>> len(sale.shipments)
+ 2
+ >>> sale.shipment_state
+ 'sent'
diff --git a/modules/sale_shipment_tolerance/tests/test_sale_shipment_tolerance.py b/modules/sale_shipment_tolerance/tests/test_sale_shipment_tolerance.py
new file mode 100644
index 0000000000..ff02ae010f
--- /dev/null
+++ b/modules/sale_shipment_tolerance/tests/test_sale_shipment_tolerance.py
@@ -0,0 +1,33 @@
+# This file is part of Tryton. The COPYRIGHT file at the top level of
+# this repository contains the full copyright notices and license terms.
+
+import unittest
+
+import doctest
+
+from trytond.tests.test_tryton import ModuleTestCase
+from trytond.tests.test_tryton import suite as test_suite
+from trytond.tests.test_tryton import doctest_teardown
+from trytond.tests.test_tryton import doctest_checker
+
+
+class SaleShipmentToleranceTestCase(ModuleTestCase):
+ 'Test Sale Shipment Tolerance module'
+ module = 'sale_shipment_tolerance'
+
+
+def suite():
+ suite = test_suite()
+ suite.addTests(unittest.TestLoader().loadTestsFromTestCase(
+ SaleShipmentToleranceTestCase))
+ suite.addTests(doctest.DocFileSuite(
+ 'scenario_sale_under_shipment_tolerance.rst',
+ tearDown=doctest_teardown, encoding='utf-8',
+ checker=doctest_checker,
+ optionflags=doctest.REPORT_ONLY_FIRST_FAILURE))
+ suite.addTests(doctest.DocFileSuite(
+ 'scenario_sale_over_shipment_tolerance.rst',
+ tearDown=doctest_teardown, encoding='utf-8',
+ checker=doctest_checker,
+ optionflags=doctest.REPORT_ONLY_FIRST_FAILURE))
+ return suite
diff --git a/modules/sale_shipment_tolerance/tox.ini b/modules/sale_shipment_tolerance/tox.ini
new file mode 100644
index 0000000000..197496c0cb
--- /dev/null
+++ b/modules/sale_shipment_tolerance/tox.ini
@@ -0,0 +1,15 @@
+[tox]
+envlist = {py36,py37,py38,py39}-{sqlite,postgresql},pypy3-{sqlite,postgresql}
+
+[testenv]
+commands = {envpython} setup.py test
+deps =
+ {py36,py37,py38,py39}-postgresql: psycopg2 >= 2.5
+ pypy3-postgresql: psycopg2cffi >= 2.5
+ py36-sqlite: sqlitebck
+setenv =
+ sqlite: TRYTOND_DATABASE_URI={env:SQLITE_URI:sqlite://}
+ postgresql: TRYTOND_DATABASE_URI={env:POSTGRESQL_URI:postgresql://}
+ sqlite: DB_NAME={env:SQLITE_NAME::memory:}
+ postgresql: DB_NAME={env:POSTGRESQL_NAME:test}
+install_command = pip install --pre --find-links https://trydevpi.tryton.org/?local_version={env:CI_JOB_ID:{env:CI_BUILD_NUMBER}.{env:CI_JOB_NUMBER}} {opts} {packages}
diff --git a/modules/sale_shipment_tolerance/tryton.cfg b/modules/sale_shipment_tolerance/tryton.cfg
new file mode 100644
index 0000000000..839e58e479
--- /dev/null
+++ b/modules/sale_shipment_tolerance/tryton.cfg
@@ -0,0 +1,9 @@
+[tryton]
+version=6.0.1
+depends:
+ ir
+ sale
+ stock
+xml:
+ configuration.xml
+ message.xml
diff --git a/modules/sale_shipment_tolerance/view/configuration_form.xml b/modules/sale_shipment_tolerance/view/configuration_form.xml
new file mode 100644
index 0000000000..38f0b3baa0
--- /dev/null
+++ b/modules/sale_shipment_tolerance/view/configuration_form.xml
@@ -0,0 +1,23 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/modules/sale_stock_quantity/.drone.yml b/modules/sale_stock_quantity/.drone.yml
new file mode 100644
index 0000000000..2049d30a49
--- /dev/null
+++ b/modules/sale_stock_quantity/.drone.yml
@@ -0,0 +1,68 @@
+clone:
+ hg:
+ image: plugins/hg
+ environment:
+ - HG_SHARE_POOL=/root/.cache/hg
+ volumes:
+ - cache:/root/.cache
+
+pipeline:
+ tox:
+ image: ${IMAGE}
+ environment:
+ - CFLAGS=-O0
+ - DB_CACHE=/cache
+ - TOX_TESTENV_PASSENV=CFLAGS DB_CACHE CI_BUILD_NUMBER CI_JOB_NUMBER CI_JOB_ID
+ - POSTGRESQL_URI=postgresql://postgres@postgresql:5432/
+ commands:
+ - echo "[extensions]" >> /root/.hgrc
+ - echo "hgext.share =" >> /root/.hgrc
+ - echo "[share]" >> /root/.hgrc
+ - echo "pool = /root/.cache/hg" >> /root/.hgrc
+ - pip install tox
+ - tox -e "${TOXENV}-${DATABASE}"
+ volumes:
+ - cache:/root/.cache
+ check_dist:
+ image: ${IMAGE}
+ commands:
+ - pip install twine
+ - python setup.py sdist
+ - twine check dist/*
+
+services:
+ postgresql:
+ image: postgres
+ environment:
+ - POSTGRES_HOST_AUTH_METHOD=trust
+ command: "-c fsync=off -c synchronous_commit=off -c full_page_writes=off"
+ when:
+ matrix:
+ DATABASE: postgresql
+
+matrix:
+ include:
+ - IMAGE: python:3.6
+ TOXENV: py36
+ DATABASE: sqlite
+ - IMAGE: python:3.6
+ TOXENV: py36
+ DATABASE: postgresql
+ - IMAGE: python:3.7
+ TOXENV: py37
+ DATABASE: sqlite
+ - IMAGE: python:3.7
+ TOXENV: py37
+ DATABASE: postgresql
+ - IMAGE: python:3.8
+ TOXENV: py38
+ DATABASE: sqlite
+ - IMAGE: python:3.8
+ TOXENV: py38
+ DATABASE: postgresql
+ - IMAGE: python:3.9
+ TOXENV: py39
+ DATABASE: sqlite
+ - IMAGE: python:3.9
+ TOXENV: py39
+ DATABASE: postgresql
diff --git a/modules/sale_stock_quantity/.flake8 b/modules/sale_stock_quantity/.flake8
new file mode 100644
index 0000000000..fa6b4f66d1
--- /dev/null
+++ b/modules/sale_stock_quantity/.flake8
@@ -0,0 +1,2 @@
+[flake8]
+ignore=E123,E124,E126,E128,E741,W503
diff --git a/modules/sale_stock_quantity/CHANGELOG b/modules/sale_stock_quantity/CHANGELOG
new file mode 100644
index 0000000000..c553ade26e
--- /dev/null
+++ b/modules/sale_stock_quantity/CHANGELOG
@@ -0,0 +1,43 @@
+Version 6.0.1 - 2022-11-05
+--------------------------
+* Bug fixes (see mercurial logs for details)
+
+Version 6.0.0 - 2021-05-03
+* Bug fixes (see mercurial logs for details)
+
+Version 5.8.0 - 2020-11-02
+* Bug fixes (see mercurial logs for details)
+* Remove support for Python 3.5
+
+Version 5.6.0 - 2020-05-04
+* Bug fixes (see mercurial logs for details)
+
+Version 5.4.0 - 2019-11-04
+* Bug fixes (see mercurial logs for details)
+
+Version 5.2.0 - 2019-05-06
+* Bug fixes (see mercurial logs for details)
+
+Version 5.0.0 - 2018-10-01
+* Bug fixes (see mercurial logs for details)
+* Remove support for Python 2.7
+
+Version 4.8.0 - 2018-04-23
+* Bug fixes (see mercurial logs for details)
+
+Version 4.6.0 - 2017-10-30
+* Bug fixes (see mercurial logs for details)
+* Do not check consumable
+
+Version 4.4.0 - 2017-05-01
+* Bug fixes (see mercurial logs for details)
+
+Version 4.2.0 - 2016-11-28
+* Bug fixes (see mercurial logs for details)
+
+Version 4.0.0 - 2016-05-02
+* Bug fixes (see mercurial logs for details)
+* Add Python3 support
+
+Version 3.8.0 - 2015-11-02
+* Initial release
diff --git a/modules/sale_stock_quantity/COPYRIGHT b/modules/sale_stock_quantity/COPYRIGHT
new file mode 100644
index 0000000000..b97a61c3dd
--- /dev/null
+++ b/modules/sale_stock_quantity/COPYRIGHT
@@ -0,0 +1,15 @@
+Copyright (C) 2015-2022 Cédric Krier.
+Copyright (C) 2015-2022 B2CK SPRL.
+
+This program is free software: you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation, either version 3 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program. If not, see .
diff --git a/modules/sale_stock_quantity/LICENSE b/modules/sale_stock_quantity/LICENSE
new file mode 100644
index 0000000000..94a9ed024d
--- /dev/null
+++ b/modules/sale_stock_quantity/LICENSE
@@ -0,0 +1,674 @@
+ GNU GENERAL PUBLIC LICENSE
+ Version 3, 29 June 2007
+
+ Copyright (C) 2007 Free Software Foundation, Inc.
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+ Preamble
+
+ The GNU General Public License is a free, copyleft license for
+software and other kinds of works.
+
+ The licenses for most software and other practical works are designed
+to take away your freedom to share and change the works. By contrast,
+the GNU General Public License is intended to guarantee your freedom to
+share and change all versions of a program--to make sure it remains free
+software for all its users. We, the Free Software Foundation, use the
+GNU General Public License for most of our software; it applies also to
+any other work released this way by its authors. You can apply it to
+your programs, too.
+
+ When we speak of free software, we are referring to freedom, not
+price. Our General Public Licenses are designed to make sure that you
+have the freedom to distribute copies of free software (and charge for
+them if you wish), that you receive source code or can get it if you
+want it, that you can change the software or use pieces of it in new
+free programs, and that you know you can do these things.
+
+ To protect your rights, we need to prevent others from denying you
+these rights or asking you to surrender the rights. Therefore, you have
+certain responsibilities if you distribute copies of the software, or if
+you modify it: responsibilities to respect the freedom of others.
+
+ For example, if you distribute copies of such a program, whether
+gratis or for a fee, you must pass on to the recipients the same
+freedoms that you received. You must make sure that they, too, receive
+or can get the source code. And you must show them these terms so they
+know their rights.
+
+ Developers that use the GNU GPL protect your rights with two steps:
+(1) assert copyright on the software, and (2) offer you this License
+giving you legal permission to copy, distribute and/or modify it.
+
+ For the developers' and authors' protection, the GPL clearly explains
+that there is no warranty for this free software. For both users' and
+authors' sake, the GPL requires that modified versions be marked as
+changed, so that their problems will not be attributed erroneously to
+authors of previous versions.
+
+ Some devices are designed to deny users access to install or run
+modified versions of the software inside them, although the manufacturer
+can do so. This is fundamentally incompatible with the aim of
+protecting users' freedom to change the software. The systematic
+pattern of such abuse occurs in the area of products for individuals to
+use, which is precisely where it is most unacceptable. Therefore, we
+have designed this version of the GPL to prohibit the practice for those
+products. If such problems arise substantially in other domains, we
+stand ready to extend this provision to those domains in future versions
+of the GPL, as needed to protect the freedom of users.
+
+ Finally, every program is threatened constantly by software patents.
+States should not allow patents to restrict development and use of
+software on general-purpose computers, but in those that do, we wish to
+avoid the special danger that patents applied to a free program could
+make it effectively proprietary. To prevent this, the GPL assures that
+patents cannot be used to render the program non-free.
+
+ The precise terms and conditions for copying, distribution and
+modification follow.
+
+ TERMS AND CONDITIONS
+
+ 0. Definitions.
+
+ "This License" refers to version 3 of the GNU General Public License.
+
+ "Copyright" also means copyright-like laws that apply to other kinds of
+works, such as semiconductor masks.
+
+ "The Program" refers to any copyrightable work licensed under this
+License. Each licensee is addressed as "you". "Licensees" and
+"recipients" may be individuals or organizations.
+
+ To "modify" a work means to copy from or adapt all or part of the work
+in a fashion requiring copyright permission, other than the making of an
+exact copy. The resulting work is called a "modified version" of the
+earlier work or a work "based on" the earlier work.
+
+ A "covered work" means either the unmodified Program or a work based
+on the Program.
+
+ To "propagate" a work means to do anything with it that, without
+permission, would make you directly or secondarily liable for
+infringement under applicable copyright law, except executing it on a
+computer or modifying a private copy. Propagation includes copying,
+distribution (with or without modification), making available to the
+public, and in some countries other activities as well.
+
+ To "convey" a work means any kind of propagation that enables other
+parties to make or receive copies. Mere interaction with a user through
+a computer network, with no transfer of a copy, is not conveying.
+
+ An interactive user interface displays "Appropriate Legal Notices"
+to the extent that it includes a convenient and prominently visible
+feature that (1) displays an appropriate copyright notice, and (2)
+tells the user that there is no warranty for the work (except to the
+extent that warranties are provided), that licensees may convey the
+work under this License, and how to view a copy of this License. If
+the interface presents a list of user commands or options, such as a
+menu, a prominent item in the list meets this criterion.
+
+ 1. Source Code.
+
+ The "source code" for a work means the preferred form of the work
+for making modifications to it. "Object code" means any non-source
+form of a work.
+
+ A "Standard Interface" means an interface that either is an official
+standard defined by a recognized standards body, or, in the case of
+interfaces specified for a particular programming language, one that
+is widely used among developers working in that language.
+
+ The "System Libraries" of an executable work include anything, other
+than the work as a whole, that (a) is included in the normal form of
+packaging a Major Component, but which is not part of that Major
+Component, and (b) serves only to enable use of the work with that
+Major Component, or to implement a Standard Interface for which an
+implementation is available to the public in source code form. A
+"Major Component", in this context, means a major essential component
+(kernel, window system, and so on) of the specific operating system
+(if any) on which the executable work runs, or a compiler used to
+produce the work, or an object code interpreter used to run it.
+
+ The "Corresponding Source" for a work in object code form means all
+the source code needed to generate, install, and (for an executable
+work) run the object code and to modify the work, including scripts to
+control those activities. However, it does not include the work's
+System Libraries, or general-purpose tools or generally available free
+programs which are used unmodified in performing those activities but
+which are not part of the work. For example, Corresponding Source
+includes interface definition files associated with source files for
+the work, and the source code for shared libraries and dynamically
+linked subprograms that the work is specifically designed to require,
+such as by intimate data communication or control flow between those
+subprograms and other parts of the work.
+
+ The Corresponding Source need not include anything that users
+can regenerate automatically from other parts of the Corresponding
+Source.
+
+ The Corresponding Source for a work in source code form is that
+same work.
+
+ 2. Basic Permissions.
+
+ All rights granted under this License are granted for the term of
+copyright on the Program, and are irrevocable provided the stated
+conditions are met. This License explicitly affirms your unlimited
+permission to run the unmodified Program. The output from running a
+covered work is covered by this License only if the output, given its
+content, constitutes a covered work. This License acknowledges your
+rights of fair use or other equivalent, as provided by copyright law.
+
+ You may make, run and propagate covered works that you do not
+convey, without conditions so long as your license otherwise remains
+in force. You may convey covered works to others for the sole purpose
+of having them make modifications exclusively for you, or provide you
+with facilities for running those works, provided that you comply with
+the terms of this License in conveying all material for which you do
+not control copyright. Those thus making or running the covered works
+for you must do so exclusively on your behalf, under your direction
+and control, on terms that prohibit them from making any copies of
+your copyrighted material outside their relationship with you.
+
+ Conveying under any other circumstances is permitted solely under
+the conditions stated below. Sublicensing is not allowed; section 10
+makes it unnecessary.
+
+ 3. Protecting Users' Legal Rights From Anti-Circumvention Law.
+
+ No covered work shall be deemed part of an effective technological
+measure under any applicable law fulfilling obligations under article
+11 of the WIPO copyright treaty adopted on 20 December 1996, or
+similar laws prohibiting or restricting circumvention of such
+measures.
+
+ When you convey a covered work, you waive any legal power to forbid
+circumvention of technological measures to the extent such circumvention
+is effected by exercising rights under this License with respect to
+the covered work, and you disclaim any intention to limit operation or
+modification of the work as a means of enforcing, against the work's
+users, your or third parties' legal rights to forbid circumvention of
+technological measures.
+
+ 4. Conveying Verbatim Copies.
+
+ You may convey verbatim copies of the Program's source code as you
+receive it, in any medium, provided that you conspicuously and
+appropriately publish on each copy an appropriate copyright notice;
+keep intact all notices stating that this License and any
+non-permissive terms added in accord with section 7 apply to the code;
+keep intact all notices of the absence of any warranty; and give all
+recipients a copy of this License along with the Program.
+
+ You may charge any price or no price for each copy that you convey,
+and you may offer support or warranty protection for a fee.
+
+ 5. Conveying Modified Source Versions.
+
+ You may convey a work based on the Program, or the modifications to
+produce it from the Program, in the form of source code under the
+terms of section 4, provided that you also meet all of these conditions:
+
+ a) The work must carry prominent notices stating that you modified
+ it, and giving a relevant date.
+
+ b) The work must carry prominent notices stating that it is
+ released under this License and any conditions added under section
+ 7. This requirement modifies the requirement in section 4 to
+ "keep intact all notices".
+
+ c) You must license the entire work, as a whole, under this
+ License to anyone who comes into possession of a copy. This
+ License will therefore apply, along with any applicable section 7
+ additional terms, to the whole of the work, and all its parts,
+ regardless of how they are packaged. This License gives no
+ permission to license the work in any other way, but it does not
+ invalidate such permission if you have separately received it.
+
+ d) If the work has interactive user interfaces, each must display
+ Appropriate Legal Notices; however, if the Program has interactive
+ interfaces that do not display Appropriate Legal Notices, your
+ work need not make them do so.
+
+ A compilation of a covered work with other separate and independent
+works, which are not by their nature extensions of the covered work,
+and which are not combined with it such as to form a larger program,
+in or on a volume of a storage or distribution medium, is called an
+"aggregate" if the compilation and its resulting copyright are not
+used to limit the access or legal rights of the compilation's users
+beyond what the individual works permit. Inclusion of a covered work
+in an aggregate does not cause this License to apply to the other
+parts of the aggregate.
+
+ 6. Conveying Non-Source Forms.
+
+ You may convey a covered work in object code form under the terms
+of sections 4 and 5, provided that you also convey the
+machine-readable Corresponding Source under the terms of this License,
+in one of these ways:
+
+ a) Convey the object code in, or embodied in, a physical product
+ (including a physical distribution medium), accompanied by the
+ Corresponding Source fixed on a durable physical medium
+ customarily used for software interchange.
+
+ b) Convey the object code in, or embodied in, a physical product
+ (including a physical distribution medium), accompanied by a
+ written offer, valid for at least three years and valid for as
+ long as you offer spare parts or customer support for that product
+ model, to give anyone who possesses the object code either (1) a
+ copy of the Corresponding Source for all the software in the
+ product that is covered by this License, on a durable physical
+ medium customarily used for software interchange, for a price no
+ more than your reasonable cost of physically performing this
+ conveying of source, or (2) access to copy the
+ Corresponding Source from a network server at no charge.
+
+ c) Convey individual copies of the object code with a copy of the
+ written offer to provide the Corresponding Source. This
+ alternative is allowed only occasionally and noncommercially, and
+ only if you received the object code with such an offer, in accord
+ with subsection 6b.
+
+ d) Convey the object code by offering access from a designated
+ place (gratis or for a charge), and offer equivalent access to the
+ Corresponding Source in the same way through the same place at no
+ further charge. You need not require recipients to copy the
+ Corresponding Source along with the object code. If the place to
+ copy the object code is a network server, the Corresponding Source
+ may be on a different server (operated by you or a third party)
+ that supports equivalent copying facilities, provided you maintain
+ clear directions next to the object code saying where to find the
+ Corresponding Source. Regardless of what server hosts the
+ Corresponding Source, you remain obligated to ensure that it is
+ available for as long as needed to satisfy these requirements.
+
+ e) Convey the object code using peer-to-peer transmission, provided
+ you inform other peers where the object code and Corresponding
+ Source of the work are being offered to the general public at no
+ charge under subsection 6d.
+
+ A separable portion of the object code, whose source code is excluded
+from the Corresponding Source as a System Library, need not be
+included in conveying the object code work.
+
+ A "User Product" is either (1) a "consumer product", which means any
+tangible personal property which is normally used for personal, family,
+or household purposes, or (2) anything designed or sold for incorporation
+into a dwelling. In determining whether a product is a consumer product,
+doubtful cases shall be resolved in favor of coverage. For a particular
+product received by a particular user, "normally used" refers to a
+typical or common use of that class of product, regardless of the status
+of the particular user or of the way in which the particular user
+actually uses, or expects or is expected to use, the product. A product
+is a consumer product regardless of whether the product has substantial
+commercial, industrial or non-consumer uses, unless such uses represent
+the only significant mode of use of the product.
+
+ "Installation Information" for a User Product means any methods,
+procedures, authorization keys, or other information required to install
+and execute modified versions of a covered work in that User Product from
+a modified version of its Corresponding Source. The information must
+suffice to ensure that the continued functioning of the modified object
+code is in no case prevented or interfered with solely because
+modification has been made.
+
+ If you convey an object code work under this section in, or with, or
+specifically for use in, a User Product, and the conveying occurs as
+part of a transaction in which the right of possession and use of the
+User Product is transferred to the recipient in perpetuity or for a
+fixed term (regardless of how the transaction is characterized), the
+Corresponding Source conveyed under this section must be accompanied
+by the Installation Information. But this requirement does not apply
+if neither you nor any third party retains the ability to install
+modified object code on the User Product (for example, the work has
+been installed in ROM).
+
+ The requirement to provide Installation Information does not include a
+requirement to continue to provide support service, warranty, or updates
+for a work that has been modified or installed by the recipient, or for
+the User Product in which it has been modified or installed. Access to a
+network may be denied when the modification itself materially and
+adversely affects the operation of the network or violates the rules and
+protocols for communication across the network.
+
+ Corresponding Source conveyed, and Installation Information provided,
+in accord with this section must be in a format that is publicly
+documented (and with an implementation available to the public in
+source code form), and must require no special password or key for
+unpacking, reading or copying.
+
+ 7. Additional Terms.
+
+ "Additional permissions" are terms that supplement the terms of this
+License by making exceptions from one or more of its conditions.
+Additional permissions that are applicable to the entire Program shall
+be treated as though they were included in this License, to the extent
+that they are valid under applicable law. If additional permissions
+apply only to part of the Program, that part may be used separately
+under those permissions, but the entire Program remains governed by
+this License without regard to the additional permissions.
+
+ When you convey a copy of a covered work, you may at your option
+remove any additional permissions from that copy, or from any part of
+it. (Additional permissions may be written to require their own
+removal in certain cases when you modify the work.) You may place
+additional permissions on material, added by you to a covered work,
+for which you have or can give appropriate copyright permission.
+
+ Notwithstanding any other provision of this License, for material you
+add to a covered work, you may (if authorized by the copyright holders of
+that material) supplement the terms of this License with terms:
+
+ a) Disclaiming warranty or limiting liability differently from the
+ terms of sections 15 and 16 of this License; or
+
+ b) Requiring preservation of specified reasonable legal notices or
+ author attributions in that material or in the Appropriate Legal
+ Notices displayed by works containing it; or
+
+ c) Prohibiting misrepresentation of the origin of that material, or
+ requiring that modified versions of such material be marked in
+ reasonable ways as different from the original version; or
+
+ d) Limiting the use for publicity purposes of names of licensors or
+ authors of the material; or
+
+ e) Declining to grant rights under trademark law for use of some
+ trade names, trademarks, or service marks; or
+
+ f) Requiring indemnification of licensors and authors of that
+ material by anyone who conveys the material (or modified versions of
+ it) with contractual assumptions of liability to the recipient, for
+ any liability that these contractual assumptions directly impose on
+ those licensors and authors.
+
+ All other non-permissive additional terms are considered "further
+restrictions" within the meaning of section 10. If the Program as you
+received it, or any part of it, contains a notice stating that it is
+governed by this License along with a term that is a further
+restriction, you may remove that term. If a license document contains
+a further restriction but permits relicensing or conveying under this
+License, you may add to a covered work material governed by the terms
+of that license document, provided that the further restriction does
+not survive such relicensing or conveying.
+
+ If you add terms to a covered work in accord with this section, you
+must place, in the relevant source files, a statement of the
+additional terms that apply to those files, or a notice indicating
+where to find the applicable terms.
+
+ Additional terms, permissive or non-permissive, may be stated in the
+form of a separately written license, or stated as exceptions;
+the above requirements apply either way.
+
+ 8. Termination.
+
+ You may not propagate or modify a covered work except as expressly
+provided under this License. Any attempt otherwise to propagate or
+modify it is void, and will automatically terminate your rights under
+this License (including any patent licenses granted under the third
+paragraph of section 11).
+
+ However, if you cease all violation of this License, then your
+license from a particular copyright holder is reinstated (a)
+provisionally, unless and until the copyright holder explicitly and
+finally terminates your license, and (b) permanently, if the copyright
+holder fails to notify you of the violation by some reasonable means
+prior to 60 days after the cessation.
+
+ Moreover, your license from a particular copyright holder is
+reinstated permanently if the copyright holder notifies you of the
+violation by some reasonable means, this is the first time you have
+received notice of violation of this License (for any work) from that
+copyright holder, and you cure the violation prior to 30 days after
+your receipt of the notice.
+
+ Termination of your rights under this section does not terminate the
+licenses of parties who have received copies or rights from you under
+this License. If your rights have been terminated and not permanently
+reinstated, you do not qualify to receive new licenses for the same
+material under section 10.
+
+ 9. Acceptance Not Required for Having Copies.
+
+ You are not required to accept this License in order to receive or
+run a copy of the Program. Ancillary propagation of a covered work
+occurring solely as a consequence of using peer-to-peer transmission
+to receive a copy likewise does not require acceptance. However,
+nothing other than this License grants you permission to propagate or
+modify any covered work. These actions infringe copyright if you do
+not accept this License. Therefore, by modifying or propagating a
+covered work, you indicate your acceptance of this License to do so.
+
+ 10. Automatic Licensing of Downstream Recipients.
+
+ Each time you convey a covered work, the recipient automatically
+receives a license from the original licensors, to run, modify and
+propagate that work, subject to this License. You are not responsible
+for enforcing compliance by third parties with this License.
+
+ An "entity transaction" is a transaction transferring control of an
+organization, or substantially all assets of one, or subdividing an
+organization, or merging organizations. If propagation of a covered
+work results from an entity transaction, each party to that
+transaction who receives a copy of the work also receives whatever
+licenses to the work the party's predecessor in interest had or could
+give under the previous paragraph, plus a right to possession of the
+Corresponding Source of the work from the predecessor in interest, if
+the predecessor has it or can get it with reasonable efforts.
+
+ You may not impose any further restrictions on the exercise of the
+rights granted or affirmed under this License. For example, you may
+not impose a license fee, royalty, or other charge for exercise of
+rights granted under this License, and you may not initiate litigation
+(including a cross-claim or counterclaim in a lawsuit) alleging that
+any patent claim is infringed by making, using, selling, offering for
+sale, or importing the Program or any portion of it.
+
+ 11. Patents.
+
+ A "contributor" is a copyright holder who authorizes use under this
+License of the Program or a work on which the Program is based. The
+work thus licensed is called the contributor's "contributor version".
+
+ A contributor's "essential patent claims" are all patent claims
+owned or controlled by the contributor, whether already acquired or
+hereafter acquired, that would be infringed by some manner, permitted
+by this License, of making, using, or selling its contributor version,
+but do not include claims that would be infringed only as a
+consequence of further modification of the contributor version. For
+purposes of this definition, "control" includes the right to grant
+patent sublicenses in a manner consistent with the requirements of
+this License.
+
+ Each contributor grants you a non-exclusive, worldwide, royalty-free
+patent license under the contributor's essential patent claims, to
+make, use, sell, offer for sale, import and otherwise run, modify and
+propagate the contents of its contributor version.
+
+ In the following three paragraphs, a "patent license" is any express
+agreement or commitment, however denominated, not to enforce a patent
+(such as an express permission to practice a patent or covenant not to
+sue for patent infringement). To "grant" such a patent license to a
+party means to make such an agreement or commitment not to enforce a
+patent against the party.
+
+ If you convey a covered work, knowingly relying on a patent license,
+and the Corresponding Source of the work is not available for anyone
+to copy, free of charge and under the terms of this License, through a
+publicly available network server or other readily accessible means,
+then you must either (1) cause the Corresponding Source to be so
+available, or (2) arrange to deprive yourself of the benefit of the
+patent license for this particular work, or (3) arrange, in a manner
+consistent with the requirements of this License, to extend the patent
+license to downstream recipients. "Knowingly relying" means you have
+actual knowledge that, but for the patent license, your conveying the
+covered work in a country, or your recipient's use of the covered work
+in a country, would infringe one or more identifiable patents in that
+country that you have reason to believe are valid.
+
+ If, pursuant to or in connection with a single transaction or
+arrangement, you convey, or propagate by procuring conveyance of, a
+covered work, and grant a patent license to some of the parties
+receiving the covered work authorizing them to use, propagate, modify
+or convey a specific copy of the covered work, then the patent license
+you grant is automatically extended to all recipients of the covered
+work and works based on it.
+
+ A patent license is "discriminatory" if it does not include within
+the scope of its coverage, prohibits the exercise of, or is
+conditioned on the non-exercise of one or more of the rights that are
+specifically granted under this License. You may not convey a covered
+work if you are a party to an arrangement with a third party that is
+in the business of distributing software, under which you make payment
+to the third party based on the extent of your activity of conveying
+the work, and under which the third party grants, to any of the
+parties who would receive the covered work from you, a discriminatory
+patent license (a) in connection with copies of the covered work
+conveyed by you (or copies made from those copies), or (b) primarily
+for and in connection with specific products or compilations that
+contain the covered work, unless you entered into that arrangement,
+or that patent license was granted, prior to 28 March 2007.
+
+ Nothing in this License shall be construed as excluding or limiting
+any implied license or other defenses to infringement that may
+otherwise be available to you under applicable patent law.
+
+ 12. No Surrender of Others' Freedom.
+
+ If conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License. If you cannot convey a
+covered work so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you may
+not convey it at all. For example, if you agree to terms that obligate you
+to collect a royalty for further conveying from those to whom you convey
+the Program, the only way you could satisfy both those terms and this
+License would be to refrain entirely from conveying the Program.
+
+ 13. Use with the GNU Affero General Public License.
+
+ Notwithstanding any other provision of this License, you have
+permission to link or combine any covered work with a work licensed
+under version 3 of the GNU Affero General Public License into a single
+combined work, and to convey the resulting work. The terms of this
+License will continue to apply to the part which is the covered work,
+but the special requirements of the GNU Affero General Public License,
+section 13, concerning interaction through a network will apply to the
+combination as such.
+
+ 14. Revised Versions of this License.
+
+ The Free Software Foundation may publish revised and/or new versions of
+the GNU General Public License from time to time. Such new versions will
+be similar in spirit to the present version, but may differ in detail to
+address new problems or concerns.
+
+ Each version is given a distinguishing version number. If the
+Program specifies that a certain numbered version of the GNU General
+Public License "or any later version" applies to it, you have the
+option of following the terms and conditions either of that numbered
+version or of any later version published by the Free Software
+Foundation. If the Program does not specify a version number of the
+GNU General Public License, you may choose any version ever published
+by the Free Software Foundation.
+
+ If the Program specifies that a proxy can decide which future
+versions of the GNU General Public License can be used, that proxy's
+public statement of acceptance of a version permanently authorizes you
+to choose that version for the Program.
+
+ Later license versions may give you additional or different
+permissions. However, no additional obligations are imposed on any
+author or copyright holder as a result of your choosing to follow a
+later version.
+
+ 15. Disclaimer of Warranty.
+
+ THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY
+APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT
+HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY
+OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO,
+THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM
+IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF
+ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
+
+ 16. Limitation of Liability.
+
+ IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS
+THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY
+GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE
+USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF
+DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD
+PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS),
+EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF
+SUCH DAMAGES.
+
+ 17. Interpretation of Sections 15 and 16.
+
+ If the disclaimer of warranty and limitation of liability provided
+above cannot be given local legal effect according to their terms,
+reviewing courts shall apply local law that most closely approximates
+an absolute waiver of all civil liability in connection with the
+Program, unless a warranty or assumption of liability accompanies a
+copy of the Program in return for a fee.
+
+ END OF TERMS AND CONDITIONS
+
+ How to Apply These Terms to Your New Programs
+
+ If you develop a new program, and you want it to be of the greatest
+possible use to the public, the best way to achieve this is to make it
+free software which everyone can redistribute and change under these terms.
+
+ To do so, attach the following notices to the program. It is safest
+to attach them to the start of each source file to most effectively
+state the exclusion of warranty; and each file should have at least
+the "copyright" line and a pointer to where the full notice is found.
+
+
+ Copyright (C)
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see .
+
+Also add information on how to contact you by electronic and paper mail.
+
+ If the program does terminal interaction, make it output a short
+notice like this when it starts in an interactive mode:
+
+ Copyright (C)
+ This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
+ This is free software, and you are welcome to redistribute it
+ under certain conditions; type `show c' for details.
+
+The hypothetical commands `show w' and `show c' should show the appropriate
+parts of the General Public License. Of course, your program's commands
+might be different; for a GUI interface, you would use an "about box".
+
+ You should also get your employer (if you work as a programmer) or school,
+if any, to sign a "copyright disclaimer" for the program, if necessary.
+For more information on this, and how to apply and follow the GNU GPL, see
+.
+
+ The GNU General Public License does not permit incorporating your program
+into proprietary programs. If your program is a subroutine library, you
+may consider it more useful to permit linking proprietary applications with
+the library. If this is what you want to do, use the GNU Lesser General
+Public License instead of this License. But first, please read
+.
diff --git a/modules/sale_stock_quantity/MANIFEST.in b/modules/sale_stock_quantity/MANIFEST.in
new file mode 100644
index 0000000000..e88b2348a3
--- /dev/null
+++ b/modules/sale_stock_quantity/MANIFEST.in
@@ -0,0 +1,5 @@
+include CHANGELOG
+include COPYRIGHT
+include LICENSE
+include README.rst
+include doc/*
diff --git a/modules/sale_stock_quantity/README.rst b/modules/sale_stock_quantity/README.rst
new file mode 120000
index 0000000000..176d9c2695
--- /dev/null
+++ b/modules/sale_stock_quantity/README.rst
@@ -0,0 +1 @@
+doc/index.rst
\ No newline at end of file
diff --git a/modules/sale_stock_quantity/__init__.py b/modules/sale_stock_quantity/__init__.py
new file mode 100644
index 0000000000..3b8c59f3ee
--- /dev/null
+++ b/modules/sale_stock_quantity/__init__.py
@@ -0,0 +1,11 @@
+# This file is part of Tryton. The COPYRIGHT file at the top level of
+# this repository contains the full copyright notices and license terms.
+
+from trytond.pool import Pool
+from . import sale
+
+
+def register():
+ Pool.register(
+ sale.Sale,
+ module='sale_stock_quantity', type_='model')
diff --git a/modules/sale_stock_quantity/doc/index.rst b/modules/sale_stock_quantity/doc/index.rst
new file mode 100644
index 0000000000..2e0ffef2d4
--- /dev/null
+++ b/modules/sale_stock_quantity/doc/index.rst
@@ -0,0 +1,7 @@
+Sale Stock Quantity
+###################
+
+The sale_stock_quantity module check the stock quantity of the products when
+quoting a sale. The check will warn the user if the forecast quantity at the
+sale date (and further dates until next supply) is lower than the quantity sold
+by considering other sales and the stock forecasts.
diff --git a/modules/sale_stock_quantity/exceptions.py b/modules/sale_stock_quantity/exceptions.py
new file mode 100644
index 0000000000..34b03c1c2f
--- /dev/null
+++ b/modules/sale_stock_quantity/exceptions.py
@@ -0,0 +1,12 @@
+# This file is part of Tryton. The COPYRIGHT file at the top level of
+# this repository contains the full copyright notices and license terms.
+
+from trytond.exceptions import UserError, UserWarning
+
+
+class StockQuantityError(UserError):
+ pass
+
+
+class StockQuantityWarning(UserWarning):
+ pass
diff --git a/modules/sale_stock_quantity/locale/bg.po b/modules/sale_stock_quantity/locale/bg.po
new file mode 100644
index 0000000000..9a9a41e2e0
--- /dev/null
+++ b/modules/sale_stock_quantity/locale/bg.po
@@ -0,0 +1,13 @@
+#
+msgid ""
+msgstr "Content-Type: text/plain; charset=utf-8\n"
+
+msgctxt "model:ir.message,text:msg_sale_stock_quantity"
+msgid ""
+"The forcast quantity (%(forecast_quantity)s%(default_uom)s) for line "
+"\"%(line)s\" is lower than its quantity (%(quantity)s%(unit)s)."
+msgstr ""
+
+msgctxt "model:res.group,name:group_sale_stock_quantity"
+msgid "Sale Stock Quantity"
+msgstr "Sale Stock Quantity"
diff --git a/modules/sale_stock_quantity/locale/ca.po b/modules/sale_stock_quantity/locale/ca.po
new file mode 100644
index 0000000000..767baf7d3b
--- /dev/null
+++ b/modules/sale_stock_quantity/locale/ca.po
@@ -0,0 +1,15 @@
+#
+msgid ""
+msgstr "Content-Type: text/plain; charset=utf-8\n"
+
+msgctxt "model:ir.message,text:msg_sale_stock_quantity"
+msgid ""
+"The forcast quantity (%(forecast_quantity)s%(default_uom)s) for line "
+"\"%(line)s\" is lower than its quantity (%(quantity)s%(unit)s)."
+msgstr ""
+"La quantitat prevista %(forecast_quantity)s%(default_uom)s de la línia "
+"\"%(line)s\" és menor que la seva quantitat %(quantity)s%(unit)s."
+
+msgctxt "model:res.group,name:group_sale_stock_quantity"
+msgid "Sale Stock Quantity"
+msgstr "Força quantitat d'existències en venda"
diff --git a/modules/sale_stock_quantity/locale/cs.po b/modules/sale_stock_quantity/locale/cs.po
new file mode 100644
index 0000000000..9a9a41e2e0
--- /dev/null
+++ b/modules/sale_stock_quantity/locale/cs.po
@@ -0,0 +1,13 @@
+#
+msgid ""
+msgstr "Content-Type: text/plain; charset=utf-8\n"
+
+msgctxt "model:ir.message,text:msg_sale_stock_quantity"
+msgid ""
+"The forcast quantity (%(forecast_quantity)s%(default_uom)s) for line "
+"\"%(line)s\" is lower than its quantity (%(quantity)s%(unit)s)."
+msgstr ""
+
+msgctxt "model:res.group,name:group_sale_stock_quantity"
+msgid "Sale Stock Quantity"
+msgstr "Sale Stock Quantity"
diff --git a/modules/sale_stock_quantity/locale/de.po b/modules/sale_stock_quantity/locale/de.po
new file mode 100644
index 0000000000..cd14014981
--- /dev/null
+++ b/modules/sale_stock_quantity/locale/de.po
@@ -0,0 +1,15 @@
+#
+msgid ""
+msgstr "Content-Type: text/plain; charset=utf-8\n"
+
+msgctxt "model:ir.message,text:msg_sale_stock_quantity"
+msgid ""
+"The forcast quantity (%(forecast_quantity)s%(default_uom)s) for line "
+"\"%(line)s\" is lower than its quantity (%(quantity)s%(unit)s)."
+msgstr ""
+"Die erwartete Menge %(forecast_quantity)s%(default_uom)s von Lagerbewegung "
+"\"%(line)s\" ist geringer als %(quantity)s%(unit)s."
+
+msgctxt "model:res.group,name:group_sale_stock_quantity"
+msgid "Sale Stock Quantity"
+msgstr "Verkauf Lagerbestand"
diff --git a/modules/sale_stock_quantity/locale/es.po b/modules/sale_stock_quantity/locale/es.po
new file mode 100644
index 0000000000..6d8544ba88
--- /dev/null
+++ b/modules/sale_stock_quantity/locale/es.po
@@ -0,0 +1,15 @@
+#
+msgid ""
+msgstr "Content-Type: text/plain; charset=utf-8\n"
+
+msgctxt "model:ir.message,text:msg_sale_stock_quantity"
+msgid ""
+"The forcast quantity (%(forecast_quantity)s%(default_uom)s) for line "
+"\"%(line)s\" is lower than its quantity (%(quantity)s%(unit)s)."
+msgstr ""
+"La cantidad prevista (%(forecast_quantity)s%(default_uom)s ) de la linea "
+"\"%(line)s\" es menor que su cantidad (%(quantity)s%(unit)s)."
+
+msgctxt "model:res.group,name:group_sale_stock_quantity"
+msgid "Sale Stock Quantity"
+msgstr "Forzar cantidad de existencias en venta"
diff --git a/modules/sale_stock_quantity/locale/es_419.po b/modules/sale_stock_quantity/locale/es_419.po
new file mode 100644
index 0000000000..79820c2ee9
--- /dev/null
+++ b/modules/sale_stock_quantity/locale/es_419.po
@@ -0,0 +1,13 @@
+#
+msgid ""
+msgstr "Content-Type: text/plain; charset=utf-8\n"
+
+msgctxt "model:ir.message,text:msg_sale_stock_quantity"
+msgid ""
+"The forcast quantity (%(forecast_quantity)s%(default_uom)s) for line "
+"\"%(line)s\" is lower than its quantity (%(quantity)s%(unit)s)."
+msgstr ""
+
+msgctxt "model:res.group,name:group_sale_stock_quantity"
+msgid "Sale Stock Quantity"
+msgstr ""
diff --git a/modules/sale_stock_quantity/locale/et.po b/modules/sale_stock_quantity/locale/et.po
new file mode 100644
index 0000000000..347b521e48
--- /dev/null
+++ b/modules/sale_stock_quantity/locale/et.po
@@ -0,0 +1,15 @@
+#
+msgid ""
+msgstr "Content-Type: text/plain; charset=utf-8\n"
+
+msgctxt "model:ir.message,text:msg_sale_stock_quantity"
+msgid ""
+"The forcast quantity (%(forecast_quantity)s%(default_uom)s) for line "
+"\"%(line)s\" is lower than its quantity (%(quantity)s%(unit)s)."
+msgstr ""
+"Prognoositav kogus (%(forecast_quantity)s%(default_uom)s) reale \"%(line)s\""
+" on väiksem, kui rida (%(quantity)s%(unit)s)."
+
+msgctxt "model:res.group,name:group_sale_stock_quantity"
+msgid "Sale Stock Quantity"
+msgstr "Vaba laoseis"
diff --git a/modules/sale_stock_quantity/locale/fa.po b/modules/sale_stock_quantity/locale/fa.po
new file mode 100644
index 0000000000..50a633a789
--- /dev/null
+++ b/modules/sale_stock_quantity/locale/fa.po
@@ -0,0 +1,15 @@
+#
+msgid ""
+msgstr "Content-Type: text/plain; charset=utf-8\n"
+
+msgctxt "model:ir.message,text:msg_sale_stock_quantity"
+msgid ""
+"The forcast quantity (%(forecast_quantity)s%(default_uom)s) for line "
+"\"%(line)s\" is lower than its quantity (%(quantity)s%(unit)s)."
+msgstr ""
+"مقدار پیش بینی: \"%s\" با واحداندازه گیری پیش فرض: \"%s\" از سطر: \"%s\" ، "
+"کمتر از مقدار : \"%s\" با واحد : \"%s\" میباشد."
+
+msgctxt "model:res.group,name:group_sale_stock_quantity"
+msgid "Sale Stock Quantity"
+msgstr "مقدار فروش موجودی"
diff --git a/modules/sale_stock_quantity/locale/fi.po b/modules/sale_stock_quantity/locale/fi.po
new file mode 100644
index 0000000000..9a9a41e2e0
--- /dev/null
+++ b/modules/sale_stock_quantity/locale/fi.po
@@ -0,0 +1,13 @@
+#
+msgid ""
+msgstr "Content-Type: text/plain; charset=utf-8\n"
+
+msgctxt "model:ir.message,text:msg_sale_stock_quantity"
+msgid ""
+"The forcast quantity (%(forecast_quantity)s%(default_uom)s) for line "
+"\"%(line)s\" is lower than its quantity (%(quantity)s%(unit)s)."
+msgstr ""
+
+msgctxt "model:res.group,name:group_sale_stock_quantity"
+msgid "Sale Stock Quantity"
+msgstr "Sale Stock Quantity"
diff --git a/modules/sale_stock_quantity/locale/fr.po b/modules/sale_stock_quantity/locale/fr.po
new file mode 100644
index 0000000000..1691259eab
--- /dev/null
+++ b/modules/sale_stock_quantity/locale/fr.po
@@ -0,0 +1,15 @@
+#
+msgid ""
+msgstr "Content-Type: text/plain; charset=utf-8\n"
+
+msgctxt "model:ir.message,text:msg_sale_stock_quantity"
+msgid ""
+"The forcast quantity (%(forecast_quantity)s%(default_uom)s) for line "
+"\"%(line)s\" is lower than its quantity (%(quantity)s%(unit)s)."
+msgstr ""
+"La quantité prévisionnelle (%(forecast_quantity)s%(default_uom)s) de la "
+"ligne « %(line)s » est plus petite que sa quantité (%(quantity)s%(unit)s)."
+
+msgctxt "model:res.group,name:group_sale_stock_quantity"
+msgid "Sale Stock Quantity"
+msgstr "Quantité de stock de vente"
diff --git a/modules/sale_stock_quantity/locale/hu.po b/modules/sale_stock_quantity/locale/hu.po
new file mode 100644
index 0000000000..9a9a41e2e0
--- /dev/null
+++ b/modules/sale_stock_quantity/locale/hu.po
@@ -0,0 +1,13 @@
+#
+msgid ""
+msgstr "Content-Type: text/plain; charset=utf-8\n"
+
+msgctxt "model:ir.message,text:msg_sale_stock_quantity"
+msgid ""
+"The forcast quantity (%(forecast_quantity)s%(default_uom)s) for line "
+"\"%(line)s\" is lower than its quantity (%(quantity)s%(unit)s)."
+msgstr ""
+
+msgctxt "model:res.group,name:group_sale_stock_quantity"
+msgid "Sale Stock Quantity"
+msgstr "Sale Stock Quantity"
diff --git a/modules/sale_stock_quantity/locale/id.po b/modules/sale_stock_quantity/locale/id.po
new file mode 100644
index 0000000000..79820c2ee9
--- /dev/null
+++ b/modules/sale_stock_quantity/locale/id.po
@@ -0,0 +1,13 @@
+#
+msgid ""
+msgstr "Content-Type: text/plain; charset=utf-8\n"
+
+msgctxt "model:ir.message,text:msg_sale_stock_quantity"
+msgid ""
+"The forcast quantity (%(forecast_quantity)s%(default_uom)s) for line "
+"\"%(line)s\" is lower than its quantity (%(quantity)s%(unit)s)."
+msgstr ""
+
+msgctxt "model:res.group,name:group_sale_stock_quantity"
+msgid "Sale Stock Quantity"
+msgstr ""
diff --git a/modules/sale_stock_quantity/locale/it.po b/modules/sale_stock_quantity/locale/it.po
new file mode 100644
index 0000000000..a49404d43a
--- /dev/null
+++ b/modules/sale_stock_quantity/locale/it.po
@@ -0,0 +1,17 @@
+#
+msgid ""
+msgstr "Content-Type: text/plain; charset=utf-8\n"
+
+#, fuzzy
+msgctxt "model:ir.message,text:msg_sale_stock_quantity"
+msgid ""
+"The forcast quantity (%(forecast_quantity)s%(default_uom)s) for line "
+"\"%(line)s\" is lower than its quantity (%(quantity)s%(unit)s)."
+msgstr ""
+"La quantita prevista %(forecast_quantity)s%(default_uom)s di \"%(line)s\" è "
+"minore di %(quantity)s%(unit)s."
+
+#, fuzzy
+msgctxt "model:res.group,name:group_sale_stock_quantity"
+msgid "Sale Stock Quantity"
+msgstr "Sale Stock Quantity"
diff --git a/modules/sale_stock_quantity/locale/lo.po b/modules/sale_stock_quantity/locale/lo.po
new file mode 100644
index 0000000000..a0ae502ad3
--- /dev/null
+++ b/modules/sale_stock_quantity/locale/lo.po
@@ -0,0 +1,17 @@
+#
+msgid ""
+msgstr "Content-Type: text/plain; charset=utf-8\n"
+
+#, fuzzy
+msgctxt "model:ir.message,text:msg_sale_stock_quantity"
+msgid ""
+"The forcast quantity (%(forecast_quantity)s%(default_uom)s) for line "
+"\"%(line)s\" is lower than its quantity (%(quantity)s%(unit)s)."
+msgstr ""
+"ການຄາດຄະເນຈຳນວນ %(forecast_quantity)s%(default_uom)s ຂອງ \"%(line)s\" "
+"ຕໍ່າກວ່າ %(quantity)s%(unit)s."
+
+#, fuzzy
+msgctxt "model:res.group,name:group_sale_stock_quantity"
+msgid "Sale Stock Quantity"
+msgstr "Sale Stock Quantity"
diff --git a/modules/sale_stock_quantity/locale/lt.po b/modules/sale_stock_quantity/locale/lt.po
new file mode 100644
index 0000000000..9a9a41e2e0
--- /dev/null
+++ b/modules/sale_stock_quantity/locale/lt.po
@@ -0,0 +1,13 @@
+#
+msgid ""
+msgstr "Content-Type: text/plain; charset=utf-8\n"
+
+msgctxt "model:ir.message,text:msg_sale_stock_quantity"
+msgid ""
+"The forcast quantity (%(forecast_quantity)s%(default_uom)s) for line "
+"\"%(line)s\" is lower than its quantity (%(quantity)s%(unit)s)."
+msgstr ""
+
+msgctxt "model:res.group,name:group_sale_stock_quantity"
+msgid "Sale Stock Quantity"
+msgstr "Sale Stock Quantity"
diff --git a/modules/sale_stock_quantity/locale/nl.po b/modules/sale_stock_quantity/locale/nl.po
new file mode 100644
index 0000000000..fbfd8e9371
--- /dev/null
+++ b/modules/sale_stock_quantity/locale/nl.po
@@ -0,0 +1,15 @@
+#
+msgid ""
+msgstr "Content-Type: text/plain; charset=utf-8\n"
+
+msgctxt "model:ir.message,text:msg_sale_stock_quantity"
+msgid ""
+"The forcast quantity (%(forecast_quantity)s%(default_uom)s) for line "
+"\"%(line)s\" is lower than its quantity (%(quantity)s%(unit)s)."
+msgstr ""
+"De voorspelde hoeveelheid ((%(forecast_quantity)s%(default_uom)s) voor regel"
+" \"%(line)s\" is kleiner dan de hoeveelheid (%(quantity)s%(unit)s)."
+
+msgctxt "model:res.group,name:group_sale_stock_quantity"
+msgid "Sale Stock Quantity"
+msgstr "Verkoop Voorraad Aantal"
diff --git a/modules/sale_stock_quantity/locale/pl.po b/modules/sale_stock_quantity/locale/pl.po
new file mode 100644
index 0000000000..9a9a41e2e0
--- /dev/null
+++ b/modules/sale_stock_quantity/locale/pl.po
@@ -0,0 +1,13 @@
+#
+msgid ""
+msgstr "Content-Type: text/plain; charset=utf-8\n"
+
+msgctxt "model:ir.message,text:msg_sale_stock_quantity"
+msgid ""
+"The forcast quantity (%(forecast_quantity)s%(default_uom)s) for line "
+"\"%(line)s\" is lower than its quantity (%(quantity)s%(unit)s)."
+msgstr ""
+
+msgctxt "model:res.group,name:group_sale_stock_quantity"
+msgid "Sale Stock Quantity"
+msgstr "Sale Stock Quantity"
diff --git a/modules/sale_stock_quantity/locale/pt.po b/modules/sale_stock_quantity/locale/pt.po
new file mode 100644
index 0000000000..9876171415
--- /dev/null
+++ b/modules/sale_stock_quantity/locale/pt.po
@@ -0,0 +1,17 @@
+#
+msgid ""
+msgstr "Content-Type: text/plain; charset=utf-8\n"
+
+#, fuzzy
+msgctxt "model:ir.message,text:msg_sale_stock_quantity"
+msgid ""
+"The forcast quantity (%(forecast_quantity)s%(default_uom)s) for line "
+"\"%(line)s\" is lower than its quantity (%(quantity)s%(unit)s)."
+msgstr ""
+"A quantidade prevista %(forecast_quantity)s%(default_uom)s da \"%(line)s\" é"
+" menor do que %(quantity)s%(unit)s."
+
+#, fuzzy
+msgctxt "model:res.group,name:group_sale_stock_quantity"
+msgid "Sale Stock Quantity"
+msgstr "Sale Stock Quantity"
diff --git a/modules/sale_stock_quantity/locale/ro.po b/modules/sale_stock_quantity/locale/ro.po
new file mode 100644
index 0000000000..79820c2ee9
--- /dev/null
+++ b/modules/sale_stock_quantity/locale/ro.po
@@ -0,0 +1,13 @@
+#
+msgid ""
+msgstr "Content-Type: text/plain; charset=utf-8\n"
+
+msgctxt "model:ir.message,text:msg_sale_stock_quantity"
+msgid ""
+"The forcast quantity (%(forecast_quantity)s%(default_uom)s) for line "
+"\"%(line)s\" is lower than its quantity (%(quantity)s%(unit)s)."
+msgstr ""
+
+msgctxt "model:res.group,name:group_sale_stock_quantity"
+msgid "Sale Stock Quantity"
+msgstr ""
diff --git a/modules/sale_stock_quantity/locale/ru.po b/modules/sale_stock_quantity/locale/ru.po
new file mode 100644
index 0000000000..9a9a41e2e0
--- /dev/null
+++ b/modules/sale_stock_quantity/locale/ru.po
@@ -0,0 +1,13 @@
+#
+msgid ""
+msgstr "Content-Type: text/plain; charset=utf-8\n"
+
+msgctxt "model:ir.message,text:msg_sale_stock_quantity"
+msgid ""
+"The forcast quantity (%(forecast_quantity)s%(default_uom)s) for line "
+"\"%(line)s\" is lower than its quantity (%(quantity)s%(unit)s)."
+msgstr ""
+
+msgctxt "model:res.group,name:group_sale_stock_quantity"
+msgid "Sale Stock Quantity"
+msgstr "Sale Stock Quantity"
diff --git a/modules/sale_stock_quantity/locale/sl.po b/modules/sale_stock_quantity/locale/sl.po
new file mode 100644
index 0000000000..a85737f998
--- /dev/null
+++ b/modules/sale_stock_quantity/locale/sl.po
@@ -0,0 +1,17 @@
+#
+msgid ""
+msgstr "Content-Type: text/plain; charset=utf-8\n"
+
+#, fuzzy
+msgctxt "model:ir.message,text:msg_sale_stock_quantity"
+msgid ""
+"The forcast quantity (%(forecast_quantity)s%(default_uom)s) for line "
+"\"%(line)s\" is lower than its quantity (%(quantity)s%(unit)s)."
+msgstr ""
+"Predvidena količina %(forecast_quantity)s%(default_uom)s postavke "
+"\"%(line)s\" je manjša kot %(quantity)s%(unit)s."
+
+#, fuzzy
+msgctxt "model:res.group,name:group_sale_stock_quantity"
+msgid "Sale Stock Quantity"
+msgstr "Sale Stock Quantity"
diff --git a/modules/sale_stock_quantity/locale/tr.po b/modules/sale_stock_quantity/locale/tr.po
new file mode 100644
index 0000000000..9a9a41e2e0
--- /dev/null
+++ b/modules/sale_stock_quantity/locale/tr.po
@@ -0,0 +1,13 @@
+#
+msgid ""
+msgstr "Content-Type: text/plain; charset=utf-8\n"
+
+msgctxt "model:ir.message,text:msg_sale_stock_quantity"
+msgid ""
+"The forcast quantity (%(forecast_quantity)s%(default_uom)s) for line "
+"\"%(line)s\" is lower than its quantity (%(quantity)s%(unit)s)."
+msgstr ""
+
+msgctxt "model:res.group,name:group_sale_stock_quantity"
+msgid "Sale Stock Quantity"
+msgstr "Sale Stock Quantity"
diff --git a/modules/sale_stock_quantity/locale/zh_CN.po b/modules/sale_stock_quantity/locale/zh_CN.po
new file mode 100644
index 0000000000..9a9a41e2e0
--- /dev/null
+++ b/modules/sale_stock_quantity/locale/zh_CN.po
@@ -0,0 +1,13 @@
+#
+msgid ""
+msgstr "Content-Type: text/plain; charset=utf-8\n"
+
+msgctxt "model:ir.message,text:msg_sale_stock_quantity"
+msgid ""
+"The forcast quantity (%(forecast_quantity)s%(default_uom)s) for line "
+"\"%(line)s\" is lower than its quantity (%(quantity)s%(unit)s)."
+msgstr ""
+
+msgctxt "model:res.group,name:group_sale_stock_quantity"
+msgid "Sale Stock Quantity"
+msgstr "Sale Stock Quantity"
diff --git a/modules/sale_stock_quantity/message.xml b/modules/sale_stock_quantity/message.xml
new file mode 100644
index 0000000000..0254d7bb62
--- /dev/null
+++ b/modules/sale_stock_quantity/message.xml
@@ -0,0 +1,10 @@
+
+
+
+
+
+ The forcast quantity (%(forecast_quantity)s%(default_uom)s) for line "%(line)s" is lower than its quantity (%(quantity)s%(unit)s).
+
+
+
diff --git a/modules/sale_stock_quantity/sale.py b/modules/sale_stock_quantity/sale.py
new file mode 100644
index 0000000000..8a33913b7e
--- /dev/null
+++ b/modules/sale_stock_quantity/sale.py
@@ -0,0 +1,192 @@
+# This file is part of Tryton. The COPYRIGHT file at the top level of
+# this repository contains the full copyright notices and license terms.
+
+import datetime
+
+from trytond.i18n import gettext
+from trytond.pool import PoolMeta, Pool
+from trytond.model import ModelView, Workflow
+from trytond.transaction import Transaction
+from trytond.tools import grouped_slice
+
+from .exceptions import StockQuantityError, StockQuantityWarning
+
+
+class Sale(metaclass=PoolMeta):
+ __name__ = 'sale.sale'
+
+ @classmethod
+ @ModelView.button
+ @Workflow.transition('quotation')
+ def quote(cls, sales):
+ # Check before setting the number
+ cls._check_stock_quantity(sales)
+ super(Sale, cls).quote(sales)
+
+ @classmethod
+ @ModelView.button
+ @Workflow.transition('confirmed')
+ def confirm(cls, sales):
+ # Check before queueing the process task
+ cls._check_stock_quantity(sales)
+ super(Sale, cls).confirm(sales)
+
+ @classmethod
+ def _check_stock_quantity(cls, sales):
+ for sale in sales:
+ sale.check_stock_quantity()
+
+ @classmethod
+ def _stock_quantity_states(cls):
+ return ['quotation', 'confirmed']
+
+ @classmethod
+ def _stock_quantity_next_supply_date(cls, product):
+ pool = Pool()
+ try:
+ PurchaseRequest = pool.get('purchase.request')
+ except KeyError:
+ PurchaseRequest = None
+
+ if (getattr(PurchaseRequest, 'get_supply_dates', None)
+ and product.purchasable):
+ return PurchaseRequest.get_supply_dates(product)[0]
+ else:
+ # TODO compute supply date for production
+ return datetime.date.max
+
+ def check_stock_quantity(self):
+ pool = Pool()
+ Product = pool.get('product.product')
+ Date = pool.get('ir.date')
+ Uom = pool.get('product.uom')
+ Group = pool.get('res.group')
+ User = pool.get('res.user')
+ ModelData = pool.get('ir.model.data')
+ Line = pool.get('sale.line')
+ Warning = pool.get('res.user.warning')
+
+ if not self.warehouse:
+ return
+
+ transaction = Transaction()
+
+ def in_group():
+ group = Group(ModelData.get_id('sale_stock_quantity',
+ 'group_sale_stock_quantity'))
+ user_id = transaction.user
+ if user_id == 0:
+ user_id = transaction.context.get('user', user_id)
+ if user_id == 0:
+ return True
+ user = User(user_id)
+ return group in user.groups
+
+ def filter_line(line):
+ return (line.product
+ and line.product.type == 'goods'
+ and not line.product.consumable
+ and line.quantity > 0
+ # Use getattr as supply_on_sale comes from sale_supply module
+ and not getattr(line, 'supply_on_sale', False))
+
+ def get_delta(date):
+ 'Compute quantity delta at the date'
+ if date in date2delta:
+ return date2delta[date]
+
+ with transaction.set_context(forecast=True,
+ stock_date_start=date,
+ stock_date_end=date):
+ pbl = Product.products_by_location(
+ [self.warehouse.id],
+ with_childs=True,
+ grouping_filter=(product_ids,))
+ delta = {}
+ for key, qty in pbl.items():
+ _, product_id = key
+ delta[product_id] = qty
+ date2delta[date] = delta
+ return delta
+ date2delta = {}
+
+ def raise_(line_id, message_values):
+ if not in_group():
+ raise StockQuantityError(
+ gettext('sale_stock_quantity.msg_sale_stock_quantity',
+ **message_values))
+ warning_name = 'stock_quantity_warning_%s' % line_id
+ if Warning.check(warning_name):
+ raise StockQuantityWarning(warning_name,
+ gettext('sale_stock_quantity.msg_sale_stock_quantity',
+ **message_values))
+
+ today = Date.today()
+ sale_date = self.sale_date or today
+ product_ids = {l.product.id for l in filter(filter_line, self.lines)}
+ product_ids = list(product_ids)
+
+ # The product must be available at least the day before
+ # for sale in the future
+ stock_date = sale_date
+ if sale_date > today:
+ stock_date -= datetime.timedelta(1)
+
+ with transaction.set_context(
+ locations=[self.warehouse.id],
+ stock_date_end=stock_date,
+ stock_assign=True):
+ products = Product.browse(product_ids)
+ quantities = {p: p.forecast_quantity for p in products}
+
+ # Remove quantities from other sales
+ for sub_product_ids in grouped_slice(product_ids):
+ lines = Line.search([
+ ('sale.company', '=', self.company.id),
+ ('sale.state', 'in', self._stock_quantity_states()),
+ ('sale.id', '!=', self.id),
+ ['OR',
+ ('sale.sale_date', '<=', sale_date),
+ ('sale.sale_date', '=', None),
+ ],
+ ('product', 'in', sub_product_ids),
+ ('quantity', '>', 0),
+ ])
+ for line in lines:
+ product = line.product
+ date = line.sale.sale_date or today
+ if date > today or line.warehouse != self.warehouse:
+ continue
+ quantity = Uom.compute_qty(line.unit, line.quantity,
+ product.default_uom, round=False)
+ quantities[product] -= quantity
+
+ for line in filter(filter_line, self.lines):
+ product = line.product
+ quantity = Uom.compute_qty(line.unit, line.quantity,
+ product.default_uom, round=False)
+ next_supply_date = self._stock_quantity_next_supply_date(product)
+ message_values = {
+ 'line': line.rec_name,
+ 'forecast_quantity': quantities[product],
+ 'default_uom': product.default_uom.symbol,
+ 'quantity': line.quantity,
+ 'unit': line.unit.symbol,
+ }
+ if (quantities[product] < quantity
+ and sale_date < next_supply_date):
+ raise_(line.id, message_values)
+ # Update quantities if the same product is many times in lines
+ quantities[product] -= quantity
+
+ # Check other dates until next supply date
+ if next_supply_date != datetime.date.max:
+ forecast_quantity = quantities[product]
+ date = sale_date + datetime.timedelta(1)
+ while date < next_supply_date:
+ delta = get_delta(date)
+ forecast_quantity += delta.get(product.id, 0)
+ if forecast_quantity < 0:
+ message_values['forecast_quantity'] = forecast_quantity
+ raise_(line.id, message_values)
+ date += datetime.timedelta(1)
diff --git a/modules/sale_stock_quantity/sale.xml b/modules/sale_stock_quantity/sale.xml
new file mode 100644
index 0000000000..1b2f556063
--- /dev/null
+++ b/modules/sale_stock_quantity/sale.xml
@@ -0,0 +1,15 @@
+
+
+
+
+
+ Sale Stock Quantity
+
+
+
+
+
+
+
diff --git a/modules/sale_stock_quantity/setup.py b/modules/sale_stock_quantity/setup.py
new file mode 100755
index 0000000000..86bb7f5efd
--- /dev/null
+++ b/modules/sale_stock_quantity/setup.py
@@ -0,0 +1,154 @@
+#!/usr/bin/env python3
+# This file is part of Tryton. The COPYRIGHT file at the top level of
+# this repository contains the full copyright notices and license terms.
+
+import io
+import os
+import re
+from configparser import ConfigParser
+from setuptools import setup, find_packages
+
+
+def read(fname):
+ return io.open(
+ os.path.join(os.path.dirname(__file__), fname),
+ 'r', encoding='utf-8').read()
+
+
+def get_require_version(name):
+ if minor_version % 2:
+ require = '%s >= %s.%s.dev0, < %s.%s'
+ else:
+ require = '%s >= %s.%s, < %s.%s'
+ require %= (name, major_version, minor_version,
+ major_version, minor_version + 1)
+ return require
+
+
+config = ConfigParser()
+config.read_file(open(os.path.join(os.path.dirname(__file__), 'tryton.cfg')))
+info = dict(config.items('tryton'))
+for key in ('depends', 'extras_depend', 'xml'):
+ if key in info:
+ info[key] = info[key].strip().splitlines()
+version = info.get('version', '0.0.1')
+major_version, minor_version, _ = version.split('.', 2)
+major_version = int(major_version)
+minor_version = int(minor_version)
+name = 'trytond_sale_stock_quantity'
+
+download_url = 'http://downloads.tryton.org/%s.%s/' % (
+ major_version, minor_version)
+if minor_version % 2:
+ version = '%s.%s.dev0' % (major_version, minor_version)
+ download_url = (
+ 'hg+http://hg.tryton.org/modules/%s#egg=%s-%s' % (
+ name[8:], name, version))
+local_version = []
+if os.environ.get('CI_JOB_ID'):
+ local_version.append(os.environ['CI_JOB_ID'])
+else:
+ for build in ['CI_BUILD_NUMBER', 'CI_JOB_NUMBER']:
+ if os.environ.get(build):
+ local_version.append(os.environ[build])
+ else:
+ local_version = []
+ break
+if local_version:
+ version += '+' + '.'.join(local_version)
+
+requires = []
+for dep in info.get('depends', []):
+ if not re.match(r'(ir|res)(\W|$)', dep):
+ requires.append(get_require_version('trytond_%s' % dep))
+requires.append(get_require_version('trytond'))
+
+tests_require = [
+ get_require_version('proteus'),
+ get_require_version('trytond_stock_supply'),
+ ]
+dependency_links = []
+if minor_version % 2:
+ dependency_links.append(
+ 'https://trydevpi.tryton.org/?local_version='
+ + '.'.join(local_version))
+
+setup(name=name,
+ version=version,
+ description='Tryton module to add stock warning on sale',
+ long_description=read('README.rst'),
+ author='Tryton',
+ author_email='bugs@tryton.org',
+ url='http://www.tryton.org/',
+ download_url=download_url,
+ project_urls={
+ "Bug Tracker": 'https://bugs.tryton.org/',
+ "Documentation": 'https://docs.tryton.org/',
+ "Forum": 'https://www.tryton.org/forum',
+ "Source Code": 'https://hg.tryton.org/modules/sale_stock_quantity',
+ },
+ keywords='tryton sale stock',
+ package_dir={'trytond.modules.sale_stock_quantity': '.'},
+ packages=(
+ ['trytond.modules.sale_stock_quantity']
+ + ['trytond.modules.sale_stock_quantity.%s' % p
+ for p in find_packages()]
+ ),
+ package_data={
+ 'trytond.modules.sale_stock_quantity': (info.get('xml', [])
+ + ['tryton.cfg', 'view/*.xml', 'locale/*.po', 'tests/*.rst',
+ '*.fodt']),
+ },
+ classifiers=[
+ 'Development Status :: 5 - Production/Stable',
+ 'Environment :: Plugins',
+ 'Framework :: Tryton',
+ 'Intended Audience :: Developers',
+ 'Intended Audience :: Financial and Insurance Industry',
+ 'Intended Audience :: Legal Industry',
+ 'Intended Audience :: Manufacturing',
+ 'License :: OSI Approved :: '
+ 'GNU General Public License v3 or later (GPLv3+)',
+ 'Natural Language :: Bulgarian',
+ 'Natural Language :: Catalan',
+ 'Natural Language :: Chinese (Simplified)',
+ 'Natural Language :: Czech',
+ 'Natural Language :: Dutch',
+ 'Natural Language :: English',
+ 'Natural Language :: Finnish',
+ 'Natural Language :: French',
+ 'Natural Language :: German',
+ 'Natural Language :: Hungarian',
+ 'Natural Language :: Indonesian',
+ 'Natural Language :: Italian',
+ 'Natural Language :: Persian',
+ 'Natural Language :: Polish',
+ 'Natural Language :: Portuguese (Brazilian)',
+ 'Natural Language :: Romanian',
+ 'Natural Language :: Russian',
+ 'Natural Language :: Slovenian',
+ 'Natural Language :: Spanish',
+ 'Natural Language :: Turkish',
+ 'Operating System :: OS Independent',
+ 'Programming Language :: Python :: 3',
+ 'Programming Language :: Python :: 3.6',
+ 'Programming Language :: Python :: 3.7',
+ 'Programming Language :: Python :: 3.8',
+ 'Programming Language :: Python :: 3.9',
+ 'Programming Language :: Python :: Implementation :: CPython',
+ 'Programming Language :: Python :: Implementation :: PyPy',
+ 'Topic :: Office/Business',
+ ],
+ license='GPL-3',
+ python_requires='>=3.6',
+ install_requires=requires,
+ dependency_links=dependency_links,
+ zip_safe=False,
+ entry_points="""
+ [trytond.modules]
+ sale_stock_quantity = trytond.modules.sale_stock_quantity
+ """,
+ test_suite='tests',
+ test_loader='trytond.test_loader:Loader',
+ tests_require=tests_require,
+ )
diff --git a/modules/sale_stock_quantity/tests/__init__.py b/modules/sale_stock_quantity/tests/__init__.py
new file mode 100644
index 0000000000..8d02d2b574
--- /dev/null
+++ b/modules/sale_stock_quantity/tests/__init__.py
@@ -0,0 +1,9 @@
+# This file is part of Tryton. The COPYRIGHT file at the top level of
+# this repository contains the full copyright notices and license terms.
+
+try:
+ from trytond.modules.sale_stock_quantity.tests.test_sale_stock_quantity import suite # noqa: E501
+except ImportError:
+ from .test_sale_stock_quantity import suite
+
+__all__ = ['suite']
diff --git a/modules/sale_stock_quantity/tests/scenario_sale_stock_quantity.rst b/modules/sale_stock_quantity/tests/scenario_sale_stock_quantity.rst
new file mode 100644
index 0000000000..4325732fab
--- /dev/null
+++ b/modules/sale_stock_quantity/tests/scenario_sale_stock_quantity.rst
@@ -0,0 +1,195 @@
+===================
+Sale Stock Quantity
+===================
+
+Imports::
+
+ >>> import datetime
+ >>> from decimal import Decimal
+ >>> from proteus import Model, Wizard, Report
+ >>> from trytond.tests.tools import activate_modules
+ >>> from trytond.modules.company.tests.tools import create_company, \
+ ... get_company
+ >>> from trytond.modules.account.tests.tools import create_fiscalyear, \
+ ... create_chart, get_accounts
+ >>> from trytond.modules.account_invoice.tests.tools import \
+ ... set_fiscalyear_invoice_sequences, create_payment_term
+ >>> from trytond.modules.stock.exceptions import InventoryFutureWarning
+ >>> today = datetime.date.today()
+
+Activate modules::
+
+ >>> config = activate_modules(['sale_stock_quantity', 'stock_supply'])
+
+Create company::
+
+ >>> _ = create_company()
+ >>> company = get_company()
+
+Create fiscal year::
+
+ >>> fiscalyear = set_fiscalyear_invoice_sequences(
+ ... create_fiscalyear(company))
+ >>> fiscalyear.click('create_period')
+
+Create chart of accounts::
+
+ >>> _ = create_chart(company)
+ >>> accounts = get_accounts(company)
+ >>> revenue = accounts['revenue']
+ >>> expense = accounts['expense']
+
+Create parties::
+
+ >>> Party = Model.get('party.party')
+ >>> customer = Party(name='Customer')
+ >>> customer.save()
+ >>> supplier = Party(name='Supplier')
+ >>> supplier.save()
+
+Create account category::
+
+ >>> ProductCategory = Model.get('product.category')
+ >>> account_category = ProductCategory(name="Account Category")
+ >>> account_category.accounting = True
+ >>> account_category.account_expense = expense
+ >>> account_category.account_revenue = revenue
+ >>> account_category.save()
+
+Create product::
+
+ >>> ProductUom = Model.get('product.uom')
+ >>> unit, = ProductUom.find([('name', '=', 'Unit')])
+ >>> ProductTemplate = Model.get('product.template')
+
+ >>> template = ProductTemplate()
+ >>> template.name = 'product'
+ >>> template.default_uom = unit
+ >>> template.type = 'goods'
+ >>> template.purchasable = True
+ >>> template.salable = True
+ >>> template.list_price = Decimal('10')
+ >>> template.account_category = account_category
+ >>> template.save()
+ >>> product, = template.products
+
+ >>> ProductSupplier = Model.get('purchase.product_supplier')
+ >>> product_supplier = ProductSupplier()
+ >>> product_supplier.template = template
+ >>> product_supplier.party = supplier
+ >>> product_supplier.lead_time = datetime.timedelta(3)
+ >>> product_supplier.save()
+
+Create payment term::
+
+ >>> payment_term = create_payment_term()
+ >>> payment_term.save()
+
+Create an Inventory of 5 products::
+
+ >>> Inventory = Model.get('stock.inventory')
+ >>> Location = Model.get('stock.location')
+ >>> storage, = Location.find([
+ ... ('code', '=', 'STO'),
+ ... ])
+ >>> inventory = Inventory()
+ >>> inventory.location = storage
+ >>> inventory_line = inventory.lines.new(product=product)
+ >>> inventory_line.quantity = 5.0
+ >>> inventory_line.expected_quantity = 0.0
+ >>> inventory.click('confirm')
+ >>> inventory.state
+ 'done'
+
+Sale 3 products with enough stock::
+
+ >>> Sale = Model.get('sale.sale')
+ >>> sale = Sale()
+ >>> sale.party = customer
+ >>> sale.payment_term = payment_term
+ >>> sale_line = sale.lines.new()
+ >>> sale_line.product = product
+ >>> sale_line.quantity = 3.0
+ >>> sale.click('quote')
+
+Sale 1 product with still enough stock::
+
+ >>> sale = Sale()
+ >>> sale.party = customer
+ >>> sale.payment_term = payment_term
+ >>> sale_line = sale.lines.new()
+ >>> sale_line.product = product
+ >>> sale_line.quantity = 1.0
+ >>> sale.click('quote')
+
+Sale 2 more products with not enough stock::
+
+ >>> sale = Sale()
+ >>> sale.party = customer
+ >>> sale.payment_term = payment_term
+ >>> sale_line = sale.lines.new()
+ >>> sale_line.product = product
+ >>> sale_line.quantity = 2.0
+ >>> sale.click('quote') # doctest: +IGNORE_EXCEPTION_DETAIL
+ Traceback (most recent call last):
+ ...
+ StockQuantityWarning: ...
+
+Clean sales::
+
+ >>> Sale.delete(Sale.find([]))
+
+Sale 6 products with not enough stock::
+
+ >>> sale = Sale()
+ >>> sale.party = customer
+ >>> sale.payment_term = payment_term
+ >>> sale_line = sale.lines.new()
+ >>> sale_line.product = product
+ >>> sale_line.quantity = 6.0
+ >>> sale.click('quote') # doctest: +IGNORE_EXCEPTION_DETAIL
+ Traceback (most recent call last):
+ ...
+ StockQuantityWarning: ...
+ >>> sale.delete()
+
+Make an inventory of 3 products in 2 days::
+
+ >>> inventory = Inventory()
+ >>> inventory.location = storage
+ >>> inventory.date = today + datetime.timedelta(2)
+ >>> inventory_line = inventory.lines.new(product=product)
+ >>> inventory_line.quantity = 3.0
+ >>> inventory_line.expected_quantity = 5.0
+ >>> try:
+ ... inventory.click('confirm')
+ ... except InventoryFutureWarning as e:
+ ... Model.get('res.user.warning')(user=config.user, name=e.name).save()
+ >>> inventory.click('confirm')
+ >>> inventory.state
+ 'done'
+
+Sale 4 products with not enough forecast::
+
+ >>> sale = Sale()
+ >>> sale.party = customer
+ >>> sale.payment_term = payment_term
+ >>> sale_line = sale.lines.new()
+ >>> sale_line.product = product
+ >>> sale_line.quantity = 4.0
+ >>> sale.click('quote') # doctest: +IGNORE_EXCEPTION_DETAIL
+ Traceback (most recent call last):
+ ...
+ StockQuantityWarning: ...
+ >>> sale.delete()
+
+Sale 2 products with enough forecast::
+
+ >>> sale = Sale()
+ >>> sale.party = customer
+ >>> sale.payment_term = payment_term
+ >>> sale_line = sale.lines.new()
+ >>> sale_line.product = product
+ >>> sale_line.quantity = 2.0
+ >>> sale.click('quote')
+ >>> sale.delete()
diff --git a/modules/sale_stock_quantity/tests/test_sale_stock_quantity.py b/modules/sale_stock_quantity/tests/test_sale_stock_quantity.py
new file mode 100644
index 0000000000..d7dc9a511c
--- /dev/null
+++ b/modules/sale_stock_quantity/tests/test_sale_stock_quantity.py
@@ -0,0 +1,25 @@
+# This file is part of Tryton. The COPYRIGHT file at the top level of
+# this repository contains the full copyright notices and license terms.
+import unittest
+import doctest
+
+import trytond.tests.test_tryton
+from trytond.tests.test_tryton import ModuleTestCase
+from trytond.tests.test_tryton import doctest_teardown
+from trytond.tests.test_tryton import doctest_checker
+
+
+class SaleStockQuantityTestCase(ModuleTestCase):
+ 'Test Sale Stock Quantity module'
+ module = 'sale_stock_quantity'
+
+
+def suite():
+ suite = trytond.tests.test_tryton.suite()
+ suite.addTests(unittest.TestLoader().loadTestsFromTestCase(
+ SaleStockQuantityTestCase))
+ suite.addTests(doctest.DocFileSuite('scenario_sale_stock_quantity.rst',
+ tearDown=doctest_teardown, encoding='utf-8',
+ checker=doctest_checker,
+ optionflags=doctest.REPORT_ONLY_FIRST_FAILURE))
+ return suite
diff --git a/modules/sale_stock_quantity/tox.ini b/modules/sale_stock_quantity/tox.ini
new file mode 100644
index 0000000000..197496c0cb
--- /dev/null
+++ b/modules/sale_stock_quantity/tox.ini
@@ -0,0 +1,15 @@
+[tox]
+envlist = {py36,py37,py38,py39}-{sqlite,postgresql},pypy3-{sqlite,postgresql}
+
+[testenv]
+commands = {envpython} setup.py test
+deps =
+ {py36,py37,py38,py39}-postgresql: psycopg2 >= 2.5
+ pypy3-postgresql: psycopg2cffi >= 2.5
+ py36-sqlite: sqlitebck
+setenv =
+ sqlite: TRYTOND_DATABASE_URI={env:SQLITE_URI:sqlite://}
+ postgresql: TRYTOND_DATABASE_URI={env:POSTGRESQL_URI:postgresql://}
+ sqlite: DB_NAME={env:SQLITE_NAME::memory:}
+ postgresql: DB_NAME={env:POSTGRESQL_NAME:test}
+install_command = pip install --pre --find-links https://trydevpi.tryton.org/?local_version={env:CI_JOB_ID:{env:CI_BUILD_NUMBER}.{env:CI_JOB_NUMBER}} {opts} {packages}
diff --git a/modules/sale_stock_quantity/tryton.cfg b/modules/sale_stock_quantity/tryton.cfg
new file mode 100644
index 0000000000..5ddd31edb7
--- /dev/null
+++ b/modules/sale_stock_quantity/tryton.cfg
@@ -0,0 +1,12 @@
+[tryton]
+version=6.0.2
+depends:
+ product
+ sale
+ stock
+extras_depend:
+ sale_supply
+ stock_supply
+xml:
+ sale.xml
+ message.xml
diff --git a/modules/sale_subscription/.drone.yml b/modules/sale_subscription/.drone.yml
new file mode 100644
index 0000000000..2049d30a49
--- /dev/null
+++ b/modules/sale_subscription/.drone.yml
@@ -0,0 +1,68 @@
+clone:
+ hg:
+ image: plugins/hg
+ environment:
+ - HG_SHARE_POOL=/root/.cache/hg
+ volumes:
+ - cache:/root/.cache
+
+pipeline:
+ tox:
+ image: ${IMAGE}
+ environment:
+ - CFLAGS=-O0
+ - DB_CACHE=/cache
+ - TOX_TESTENV_PASSENV=CFLAGS DB_CACHE CI_BUILD_NUMBER CI_JOB_NUMBER CI_JOB_ID
+ - POSTGRESQL_URI=postgresql://postgres@postgresql:5432/
+ commands:
+ - echo "[extensions]" >> /root/.hgrc
+ - echo "hgext.share =" >> /root/.hgrc
+ - echo "[share]" >> /root/.hgrc
+ - echo "pool = /root/.cache/hg" >> /root/.hgrc
+ - pip install tox
+ - tox -e "${TOXENV}-${DATABASE}"
+ volumes:
+ - cache:/root/.cache
+ check_dist:
+ image: ${IMAGE}
+ commands:
+ - pip install twine
+ - python setup.py sdist
+ - twine check dist/*
+
+services:
+ postgresql:
+ image: postgres
+ environment:
+ - POSTGRES_HOST_AUTH_METHOD=trust
+ command: "-c fsync=off -c synchronous_commit=off -c full_page_writes=off"
+ when:
+ matrix:
+ DATABASE: postgresql
+
+matrix:
+ include:
+ - IMAGE: python:3.6
+ TOXENV: py36
+ DATABASE: sqlite
+ - IMAGE: python:3.6
+ TOXENV: py36
+ DATABASE: postgresql
+ - IMAGE: python:3.7
+ TOXENV: py37
+ DATABASE: sqlite
+ - IMAGE: python:3.7
+ TOXENV: py37
+ DATABASE: postgresql
+ - IMAGE: python:3.8
+ TOXENV: py38
+ DATABASE: sqlite
+ - IMAGE: python:3.8
+ TOXENV: py38
+ DATABASE: postgresql
+ - IMAGE: python:3.9
+ TOXENV: py39
+ DATABASE: sqlite
+ - IMAGE: python:3.9
+ TOXENV: py39
+ DATABASE: postgresql
diff --git a/modules/sale_subscription/.flake8 b/modules/sale_subscription/.flake8
new file mode 100644
index 0000000000..fa6b4f66d1
--- /dev/null
+++ b/modules/sale_subscription/.flake8
@@ -0,0 +1,2 @@
+[flake8]
+ignore=E123,E124,E126,E128,E741,W503
diff --git a/modules/sale_subscription/CHANGELOG b/modules/sale_subscription/CHANGELOG
new file mode 100644
index 0000000000..fcd59bf847
--- /dev/null
+++ b/modules/sale_subscription/CHANGELOG
@@ -0,0 +1,45 @@
+Version 6.0.2 - 2022-08-03
+* Bug fixes (see mercurial logs for details)
+
+Version 6.0.1 - 2021-09-01
+* Bug fixes (see mercurial logs for details)
+
+Version 6.0.0 - 2021-05-03
+* Bug fixes (see mercurial logs for details)
+
+Version 5.8.0 - 2020-11-02
+* Bug fixes (see mercurial logs for details)
+* Remove support for Python 3.5
+* Rename subscription state from canceled to cancelled
+
+Version 5.6.0 - 2020-05-04
+* Bug fixes (see mercurial logs for details)
+* Add employee on subscriptions for some states
+* Use greatest end date of lines for closed date
+* Add contact and invoice party on subscription
+* Allow invoices to be created in advance
+
+Version 5.4.0 - 2019-11-04
+* Bug fixes (see mercurial logs for details)
+* Allow lines to be finished before next consumption
+* Allow services to be deactivated
+
+Version 5.2.0 - 2019-05-06
+* Bug fixes (see mercurial logs for details)
+* Use ir.calendar.day
+
+Version 5.0.0 - 2018-10-01
+* Bug fixes (see mercurial logs for details)
+* Remove support for Python 2.7
+* Make start date of line required
+* Make description on subscription line optional
+
+Version 4.8.0 - 2018-04-23
+* Bug fixes (see mercurial logs for details)
+* Check pending subscription to erase party
+
+Version 4.6.0 - 2017-10-30
+* Bug fixes (see mercurial logs for details)
+
+Version 4.4.0 - 2017-05-01
+* Initial release
diff --git a/modules/sale_subscription/COPYRIGHT b/modules/sale_subscription/COPYRIGHT
new file mode 100644
index 0000000000..3bf61ea509
--- /dev/null
+++ b/modules/sale_subscription/COPYRIGHT
@@ -0,0 +1,15 @@
+Copyright (C) 2016-2022 Cédric Krier
+Copyright (C) 2016-2022 B2CK SPRL.
+
+This program is free software: you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation, either version 3 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program. If not, see .
diff --git a/modules/sale_subscription/LICENSE b/modules/sale_subscription/LICENSE
new file mode 100644
index 0000000000..94a9ed024d
--- /dev/null
+++ b/modules/sale_subscription/LICENSE
@@ -0,0 +1,674 @@
+ GNU GENERAL PUBLIC LICENSE
+ Version 3, 29 June 2007
+
+ Copyright (C) 2007 Free Software Foundation, Inc.
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+ Preamble
+
+ The GNU General Public License is a free, copyleft license for
+software and other kinds of works.
+
+ The licenses for most software and other practical works are designed
+to take away your freedom to share and change the works. By contrast,
+the GNU General Public License is intended to guarantee your freedom to
+share and change all versions of a program--to make sure it remains free
+software for all its users. We, the Free Software Foundation, use the
+GNU General Public License for most of our software; it applies also to
+any other work released this way by its authors. You can apply it to
+your programs, too.
+
+ When we speak of free software, we are referring to freedom, not
+price. Our General Public Licenses are designed to make sure that you
+have the freedom to distribute copies of free software (and charge for
+them if you wish), that you receive source code or can get it if you
+want it, that you can change the software or use pieces of it in new
+free programs, and that you know you can do these things.
+
+ To protect your rights, we need to prevent others from denying you
+these rights or asking you to surrender the rights. Therefore, you have
+certain responsibilities if you distribute copies of the software, or if
+you modify it: responsibilities to respect the freedom of others.
+
+ For example, if you distribute copies of such a program, whether
+gratis or for a fee, you must pass on to the recipients the same
+freedoms that you received. You must make sure that they, too, receive
+or can get the source code. And you must show them these terms so they
+know their rights.
+
+ Developers that use the GNU GPL protect your rights with two steps:
+(1) assert copyright on the software, and (2) offer you this License
+giving you legal permission to copy, distribute and/or modify it.
+
+ For the developers' and authors' protection, the GPL clearly explains
+that there is no warranty for this free software. For both users' and
+authors' sake, the GPL requires that modified versions be marked as
+changed, so that their problems will not be attributed erroneously to
+authors of previous versions.
+
+ Some devices are designed to deny users access to install or run
+modified versions of the software inside them, although the manufacturer
+can do so. This is fundamentally incompatible with the aim of
+protecting users' freedom to change the software. The systematic
+pattern of such abuse occurs in the area of products for individuals to
+use, which is precisely where it is most unacceptable. Therefore, we
+have designed this version of the GPL to prohibit the practice for those
+products. If such problems arise substantially in other domains, we
+stand ready to extend this provision to those domains in future versions
+of the GPL, as needed to protect the freedom of users.
+
+ Finally, every program is threatened constantly by software patents.
+States should not allow patents to restrict development and use of
+software on general-purpose computers, but in those that do, we wish to
+avoid the special danger that patents applied to a free program could
+make it effectively proprietary. To prevent this, the GPL assures that
+patents cannot be used to render the program non-free.
+
+ The precise terms and conditions for copying, distribution and
+modification follow.
+
+ TERMS AND CONDITIONS
+
+ 0. Definitions.
+
+ "This License" refers to version 3 of the GNU General Public License.
+
+ "Copyright" also means copyright-like laws that apply to other kinds of
+works, such as semiconductor masks.
+
+ "The Program" refers to any copyrightable work licensed under this
+License. Each licensee is addressed as "you". "Licensees" and
+"recipients" may be individuals or organizations.
+
+ To "modify" a work means to copy from or adapt all or part of the work
+in a fashion requiring copyright permission, other than the making of an
+exact copy. The resulting work is called a "modified version" of the
+earlier work or a work "based on" the earlier work.
+
+ A "covered work" means either the unmodified Program or a work based
+on the Program.
+
+ To "propagate" a work means to do anything with it that, without
+permission, would make you directly or secondarily liable for
+infringement under applicable copyright law, except executing it on a
+computer or modifying a private copy. Propagation includes copying,
+distribution (with or without modification), making available to the
+public, and in some countries other activities as well.
+
+ To "convey" a work means any kind of propagation that enables other
+parties to make or receive copies. Mere interaction with a user through
+a computer network, with no transfer of a copy, is not conveying.
+
+ An interactive user interface displays "Appropriate Legal Notices"
+to the extent that it includes a convenient and prominently visible
+feature that (1) displays an appropriate copyright notice, and (2)
+tells the user that there is no warranty for the work (except to the
+extent that warranties are provided), that licensees may convey the
+work under this License, and how to view a copy of this License. If
+the interface presents a list of user commands or options, such as a
+menu, a prominent item in the list meets this criterion.
+
+ 1. Source Code.
+
+ The "source code" for a work means the preferred form of the work
+for making modifications to it. "Object code" means any non-source
+form of a work.
+
+ A "Standard Interface" means an interface that either is an official
+standard defined by a recognized standards body, or, in the case of
+interfaces specified for a particular programming language, one that
+is widely used among developers working in that language.
+
+ The "System Libraries" of an executable work include anything, other
+than the work as a whole, that (a) is included in the normal form of
+packaging a Major Component, but which is not part of that Major
+Component, and (b) serves only to enable use of the work with that
+Major Component, or to implement a Standard Interface for which an
+implementation is available to the public in source code form. A
+"Major Component", in this context, means a major essential component
+(kernel, window system, and so on) of the specific operating system
+(if any) on which the executable work runs, or a compiler used to
+produce the work, or an object code interpreter used to run it.
+
+ The "Corresponding Source" for a work in object code form means all
+the source code needed to generate, install, and (for an executable
+work) run the object code and to modify the work, including scripts to
+control those activities. However, it does not include the work's
+System Libraries, or general-purpose tools or generally available free
+programs which are used unmodified in performing those activities but
+which are not part of the work. For example, Corresponding Source
+includes interface definition files associated with source files for
+the work, and the source code for shared libraries and dynamically
+linked subprograms that the work is specifically designed to require,
+such as by intimate data communication or control flow between those
+subprograms and other parts of the work.
+
+ The Corresponding Source need not include anything that users
+can regenerate automatically from other parts of the Corresponding
+Source.
+
+ The Corresponding Source for a work in source code form is that
+same work.
+
+ 2. Basic Permissions.
+
+ All rights granted under this License are granted for the term of
+copyright on the Program, and are irrevocable provided the stated
+conditions are met. This License explicitly affirms your unlimited
+permission to run the unmodified Program. The output from running a
+covered work is covered by this License only if the output, given its
+content, constitutes a covered work. This License acknowledges your
+rights of fair use or other equivalent, as provided by copyright law.
+
+ You may make, run and propagate covered works that you do not
+convey, without conditions so long as your license otherwise remains
+in force. You may convey covered works to others for the sole purpose
+of having them make modifications exclusively for you, or provide you
+with facilities for running those works, provided that you comply with
+the terms of this License in conveying all material for which you do
+not control copyright. Those thus making or running the covered works
+for you must do so exclusively on your behalf, under your direction
+and control, on terms that prohibit them from making any copies of
+your copyrighted material outside their relationship with you.
+
+ Conveying under any other circumstances is permitted solely under
+the conditions stated below. Sublicensing is not allowed; section 10
+makes it unnecessary.
+
+ 3. Protecting Users' Legal Rights From Anti-Circumvention Law.
+
+ No covered work shall be deemed part of an effective technological
+measure under any applicable law fulfilling obligations under article
+11 of the WIPO copyright treaty adopted on 20 December 1996, or
+similar laws prohibiting or restricting circumvention of such
+measures.
+
+ When you convey a covered work, you waive any legal power to forbid
+circumvention of technological measures to the extent such circumvention
+is effected by exercising rights under this License with respect to
+the covered work, and you disclaim any intention to limit operation or
+modification of the work as a means of enforcing, against the work's
+users, your or third parties' legal rights to forbid circumvention of
+technological measures.
+
+ 4. Conveying Verbatim Copies.
+
+ You may convey verbatim copies of the Program's source code as you
+receive it, in any medium, provided that you conspicuously and
+appropriately publish on each copy an appropriate copyright notice;
+keep intact all notices stating that this License and any
+non-permissive terms added in accord with section 7 apply to the code;
+keep intact all notices of the absence of any warranty; and give all
+recipients a copy of this License along with the Program.
+
+ You may charge any price or no price for each copy that you convey,
+and you may offer support or warranty protection for a fee.
+
+ 5. Conveying Modified Source Versions.
+
+ You may convey a work based on the Program, or the modifications to
+produce it from the Program, in the form of source code under the
+terms of section 4, provided that you also meet all of these conditions:
+
+ a) The work must carry prominent notices stating that you modified
+ it, and giving a relevant date.
+
+ b) The work must carry prominent notices stating that it is
+ released under this License and any conditions added under section
+ 7. This requirement modifies the requirement in section 4 to
+ "keep intact all notices".
+
+ c) You must license the entire work, as a whole, under this
+ License to anyone who comes into possession of a copy. This
+ License will therefore apply, along with any applicable section 7
+ additional terms, to the whole of the work, and all its parts,
+ regardless of how they are packaged. This License gives no
+ permission to license the work in any other way, but it does not
+ invalidate such permission if you have separately received it.
+
+ d) If the work has interactive user interfaces, each must display
+ Appropriate Legal Notices; however, if the Program has interactive
+ interfaces that do not display Appropriate Legal Notices, your
+ work need not make them do so.
+
+ A compilation of a covered work with other separate and independent
+works, which are not by their nature extensions of the covered work,
+and which are not combined with it such as to form a larger program,
+in or on a volume of a storage or distribution medium, is called an
+"aggregate" if the compilation and its resulting copyright are not
+used to limit the access or legal rights of the compilation's users
+beyond what the individual works permit. Inclusion of a covered work
+in an aggregate does not cause this License to apply to the other
+parts of the aggregate.
+
+ 6. Conveying Non-Source Forms.
+
+ You may convey a covered work in object code form under the terms
+of sections 4 and 5, provided that you also convey the
+machine-readable Corresponding Source under the terms of this License,
+in one of these ways:
+
+ a) Convey the object code in, or embodied in, a physical product
+ (including a physical distribution medium), accompanied by the
+ Corresponding Source fixed on a durable physical medium
+ customarily used for software interchange.
+
+ b) Convey the object code in, or embodied in, a physical product
+ (including a physical distribution medium), accompanied by a
+ written offer, valid for at least three years and valid for as
+ long as you offer spare parts or customer support for that product
+ model, to give anyone who possesses the object code either (1) a
+ copy of the Corresponding Source for all the software in the
+ product that is covered by this License, on a durable physical
+ medium customarily used for software interchange, for a price no
+ more than your reasonable cost of physically performing this
+ conveying of source, or (2) access to copy the
+ Corresponding Source from a network server at no charge.
+
+ c) Convey individual copies of the object code with a copy of the
+ written offer to provide the Corresponding Source. This
+ alternative is allowed only occasionally and noncommercially, and
+ only if you received the object code with such an offer, in accord
+ with subsection 6b.
+
+ d) Convey the object code by offering access from a designated
+ place (gratis or for a charge), and offer equivalent access to the
+ Corresponding Source in the same way through the same place at no
+ further charge. You need not require recipients to copy the
+ Corresponding Source along with the object code. If the place to
+ copy the object code is a network server, the Corresponding Source
+ may be on a different server (operated by you or a third party)
+ that supports equivalent copying facilities, provided you maintain
+ clear directions next to the object code saying where to find the
+ Corresponding Source. Regardless of what server hosts the
+ Corresponding Source, you remain obligated to ensure that it is
+ available for as long as needed to satisfy these requirements.
+
+ e) Convey the object code using peer-to-peer transmission, provided
+ you inform other peers where the object code and Corresponding
+ Source of the work are being offered to the general public at no
+ charge under subsection 6d.
+
+ A separable portion of the object code, whose source code is excluded
+from the Corresponding Source as a System Library, need not be
+included in conveying the object code work.
+
+ A "User Product" is either (1) a "consumer product", which means any
+tangible personal property which is normally used for personal, family,
+or household purposes, or (2) anything designed or sold for incorporation
+into a dwelling. In determining whether a product is a consumer product,
+doubtful cases shall be resolved in favor of coverage. For a particular
+product received by a particular user, "normally used" refers to a
+typical or common use of that class of product, regardless of the status
+of the particular user or of the way in which the particular user
+actually uses, or expects or is expected to use, the product. A product
+is a consumer product regardless of whether the product has substantial
+commercial, industrial or non-consumer uses, unless such uses represent
+the only significant mode of use of the product.
+
+ "Installation Information" for a User Product means any methods,
+procedures, authorization keys, or other information required to install
+and execute modified versions of a covered work in that User Product from
+a modified version of its Corresponding Source. The information must
+suffice to ensure that the continued functioning of the modified object
+code is in no case prevented or interfered with solely because
+modification has been made.
+
+ If you convey an object code work under this section in, or with, or
+specifically for use in, a User Product, and the conveying occurs as
+part of a transaction in which the right of possession and use of the
+User Product is transferred to the recipient in perpetuity or for a
+fixed term (regardless of how the transaction is characterized), the
+Corresponding Source conveyed under this section must be accompanied
+by the Installation Information. But this requirement does not apply
+if neither you nor any third party retains the ability to install
+modified object code on the User Product (for example, the work has
+been installed in ROM).
+
+ The requirement to provide Installation Information does not include a
+requirement to continue to provide support service, warranty, or updates
+for a work that has been modified or installed by the recipient, or for
+the User Product in which it has been modified or installed. Access to a
+network may be denied when the modification itself materially and
+adversely affects the operation of the network or violates the rules and
+protocols for communication across the network.
+
+ Corresponding Source conveyed, and Installation Information provided,
+in accord with this section must be in a format that is publicly
+documented (and with an implementation available to the public in
+source code form), and must require no special password or key for
+unpacking, reading or copying.
+
+ 7. Additional Terms.
+
+ "Additional permissions" are terms that supplement the terms of this
+License by making exceptions from one or more of its conditions.
+Additional permissions that are applicable to the entire Program shall
+be treated as though they were included in this License, to the extent
+that they are valid under applicable law. If additional permissions
+apply only to part of the Program, that part may be used separately
+under those permissions, but the entire Program remains governed by
+this License without regard to the additional permissions.
+
+ When you convey a copy of a covered work, you may at your option
+remove any additional permissions from that copy, or from any part of
+it. (Additional permissions may be written to require their own
+removal in certain cases when you modify the work.) You may place
+additional permissions on material, added by you to a covered work,
+for which you have or can give appropriate copyright permission.
+
+ Notwithstanding any other provision of this License, for material you
+add to a covered work, you may (if authorized by the copyright holders of
+that material) supplement the terms of this License with terms:
+
+ a) Disclaiming warranty or limiting liability differently from the
+ terms of sections 15 and 16 of this License; or
+
+ b) Requiring preservation of specified reasonable legal notices or
+ author attributions in that material or in the Appropriate Legal
+ Notices displayed by works containing it; or
+
+ c) Prohibiting misrepresentation of the origin of that material, or
+ requiring that modified versions of such material be marked in
+ reasonable ways as different from the original version; or
+
+ d) Limiting the use for publicity purposes of names of licensors or
+ authors of the material; or
+
+ e) Declining to grant rights under trademark law for use of some
+ trade names, trademarks, or service marks; or
+
+ f) Requiring indemnification of licensors and authors of that
+ material by anyone who conveys the material (or modified versions of
+ it) with contractual assumptions of liability to the recipient, for
+ any liability that these contractual assumptions directly impose on
+ those licensors and authors.
+
+ All other non-permissive additional terms are considered "further
+restrictions" within the meaning of section 10. If the Program as you
+received it, or any part of it, contains a notice stating that it is
+governed by this License along with a term that is a further
+restriction, you may remove that term. If a license document contains
+a further restriction but permits relicensing or conveying under this
+License, you may add to a covered work material governed by the terms
+of that license document, provided that the further restriction does
+not survive such relicensing or conveying.
+
+ If you add terms to a covered work in accord with this section, you
+must place, in the relevant source files, a statement of the
+additional terms that apply to those files, or a notice indicating
+where to find the applicable terms.
+
+ Additional terms, permissive or non-permissive, may be stated in the
+form of a separately written license, or stated as exceptions;
+the above requirements apply either way.
+
+ 8. Termination.
+
+ You may not propagate or modify a covered work except as expressly
+provided under this License. Any attempt otherwise to propagate or
+modify it is void, and will automatically terminate your rights under
+this License (including any patent licenses granted under the third
+paragraph of section 11).
+
+ However, if you cease all violation of this License, then your
+license from a particular copyright holder is reinstated (a)
+provisionally, unless and until the copyright holder explicitly and
+finally terminates your license, and (b) permanently, if the copyright
+holder fails to notify you of the violation by some reasonable means
+prior to 60 days after the cessation.
+
+ Moreover, your license from a particular copyright holder is
+reinstated permanently if the copyright holder notifies you of the
+violation by some reasonable means, this is the first time you have
+received notice of violation of this License (for any work) from that
+copyright holder, and you cure the violation prior to 30 days after
+your receipt of the notice.
+
+ Termination of your rights under this section does not terminate the
+licenses of parties who have received copies or rights from you under
+this License. If your rights have been terminated and not permanently
+reinstated, you do not qualify to receive new licenses for the same
+material under section 10.
+
+ 9. Acceptance Not Required for Having Copies.
+
+ You are not required to accept this License in order to receive or
+run a copy of the Program. Ancillary propagation of a covered work
+occurring solely as a consequence of using peer-to-peer transmission
+to receive a copy likewise does not require acceptance. However,
+nothing other than this License grants you permission to propagate or
+modify any covered work. These actions infringe copyright if you do
+not accept this License. Therefore, by modifying or propagating a
+covered work, you indicate your acceptance of this License to do so.
+
+ 10. Automatic Licensing of Downstream Recipients.
+
+ Each time you convey a covered work, the recipient automatically
+receives a license from the original licensors, to run, modify and
+propagate that work, subject to this License. You are not responsible
+for enforcing compliance by third parties with this License.
+
+ An "entity transaction" is a transaction transferring control of an
+organization, or substantially all assets of one, or subdividing an
+organization, or merging organizations. If propagation of a covered
+work results from an entity transaction, each party to that
+transaction who receives a copy of the work also receives whatever
+licenses to the work the party's predecessor in interest had or could
+give under the previous paragraph, plus a right to possession of the
+Corresponding Source of the work from the predecessor in interest, if
+the predecessor has it or can get it with reasonable efforts.
+
+ You may not impose any further restrictions on the exercise of the
+rights granted or affirmed under this License. For example, you may
+not impose a license fee, royalty, or other charge for exercise of
+rights granted under this License, and you may not initiate litigation
+(including a cross-claim or counterclaim in a lawsuit) alleging that
+any patent claim is infringed by making, using, selling, offering for
+sale, or importing the Program or any portion of it.
+
+ 11. Patents.
+
+ A "contributor" is a copyright holder who authorizes use under this
+License of the Program or a work on which the Program is based. The
+work thus licensed is called the contributor's "contributor version".
+
+ A contributor's "essential patent claims" are all patent claims
+owned or controlled by the contributor, whether already acquired or
+hereafter acquired, that would be infringed by some manner, permitted
+by this License, of making, using, or selling its contributor version,
+but do not include claims that would be infringed only as a
+consequence of further modification of the contributor version. For
+purposes of this definition, "control" includes the right to grant
+patent sublicenses in a manner consistent with the requirements of
+this License.
+
+ Each contributor grants you a non-exclusive, worldwide, royalty-free
+patent license under the contributor's essential patent claims, to
+make, use, sell, offer for sale, import and otherwise run, modify and
+propagate the contents of its contributor version.
+
+ In the following three paragraphs, a "patent license" is any express
+agreement or commitment, however denominated, not to enforce a patent
+(such as an express permission to practice a patent or covenant not to
+sue for patent infringement). To "grant" such a patent license to a
+party means to make such an agreement or commitment not to enforce a
+patent against the party.
+
+ If you convey a covered work, knowingly relying on a patent license,
+and the Corresponding Source of the work is not available for anyone
+to copy, free of charge and under the terms of this License, through a
+publicly available network server or other readily accessible means,
+then you must either (1) cause the Corresponding Source to be so
+available, or (2) arrange to deprive yourself of the benefit of the
+patent license for this particular work, or (3) arrange, in a manner
+consistent with the requirements of this License, to extend the patent
+license to downstream recipients. "Knowingly relying" means you have
+actual knowledge that, but for the patent license, your conveying the
+covered work in a country, or your recipient's use of the covered work
+in a country, would infringe one or more identifiable patents in that
+country that you have reason to believe are valid.
+
+ If, pursuant to or in connection with a single transaction or
+arrangement, you convey, or propagate by procuring conveyance of, a
+covered work, and grant a patent license to some of the parties
+receiving the covered work authorizing them to use, propagate, modify
+or convey a specific copy of the covered work, then the patent license
+you grant is automatically extended to all recipients of the covered
+work and works based on it.
+
+ A patent license is "discriminatory" if it does not include within
+the scope of its coverage, prohibits the exercise of, or is
+conditioned on the non-exercise of one or more of the rights that are
+specifically granted under this License. You may not convey a covered
+work if you are a party to an arrangement with a third party that is
+in the business of distributing software, under which you make payment
+to the third party based on the extent of your activity of conveying
+the work, and under which the third party grants, to any of the
+parties who would receive the covered work from you, a discriminatory
+patent license (a) in connection with copies of the covered work
+conveyed by you (or copies made from those copies), or (b) primarily
+for and in connection with specific products or compilations that
+contain the covered work, unless you entered into that arrangement,
+or that patent license was granted, prior to 28 March 2007.
+
+ Nothing in this License shall be construed as excluding or limiting
+any implied license or other defenses to infringement that may
+otherwise be available to you under applicable patent law.
+
+ 12. No Surrender of Others' Freedom.
+
+ If conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License. If you cannot convey a
+covered work so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you may
+not convey it at all. For example, if you agree to terms that obligate you
+to collect a royalty for further conveying from those to whom you convey
+the Program, the only way you could satisfy both those terms and this
+License would be to refrain entirely from conveying the Program.
+
+ 13. Use with the GNU Affero General Public License.
+
+ Notwithstanding any other provision of this License, you have
+permission to link or combine any covered work with a work licensed
+under version 3 of the GNU Affero General Public License into a single
+combined work, and to convey the resulting work. The terms of this
+License will continue to apply to the part which is the covered work,
+but the special requirements of the GNU Affero General Public License,
+section 13, concerning interaction through a network will apply to the
+combination as such.
+
+ 14. Revised Versions of this License.
+
+ The Free Software Foundation may publish revised and/or new versions of
+the GNU General Public License from time to time. Such new versions will
+be similar in spirit to the present version, but may differ in detail to
+address new problems or concerns.
+
+ Each version is given a distinguishing version number. If the
+Program specifies that a certain numbered version of the GNU General
+Public License "or any later version" applies to it, you have the
+option of following the terms and conditions either of that numbered
+version or of any later version published by the Free Software
+Foundation. If the Program does not specify a version number of the
+GNU General Public License, you may choose any version ever published
+by the Free Software Foundation.
+
+ If the Program specifies that a proxy can decide which future
+versions of the GNU General Public License can be used, that proxy's
+public statement of acceptance of a version permanently authorizes you
+to choose that version for the Program.
+
+ Later license versions may give you additional or different
+permissions. However, no additional obligations are imposed on any
+author or copyright holder as a result of your choosing to follow a
+later version.
+
+ 15. Disclaimer of Warranty.
+
+ THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY
+APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT
+HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY
+OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO,
+THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM
+IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF
+ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
+
+ 16. Limitation of Liability.
+
+ IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS
+THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY
+GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE
+USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF
+DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD
+PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS),
+EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF
+SUCH DAMAGES.
+
+ 17. Interpretation of Sections 15 and 16.
+
+ If the disclaimer of warranty and limitation of liability provided
+above cannot be given local legal effect according to their terms,
+reviewing courts shall apply local law that most closely approximates
+an absolute waiver of all civil liability in connection with the
+Program, unless a warranty or assumption of liability accompanies a
+copy of the Program in return for a fee.
+
+ END OF TERMS AND CONDITIONS
+
+ How to Apply These Terms to Your New Programs
+
+ If you develop a new program, and you want it to be of the greatest
+possible use to the public, the best way to achieve this is to make it
+free software which everyone can redistribute and change under these terms.
+
+ To do so, attach the following notices to the program. It is safest
+to attach them to the start of each source file to most effectively
+state the exclusion of warranty; and each file should have at least
+the "copyright" line and a pointer to where the full notice is found.
+
+
+ Copyright (C)
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see .
+
+Also add information on how to contact you by electronic and paper mail.
+
+ If the program does terminal interaction, make it output a short
+notice like this when it starts in an interactive mode:
+
+ Copyright (C)
+ This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
+ This is free software, and you are welcome to redistribute it
+ under certain conditions; type `show c' for details.
+
+The hypothetical commands `show w' and `show c' should show the appropriate
+parts of the General Public License. Of course, your program's commands
+might be different; for a GUI interface, you would use an "about box".
+
+ You should also get your employer (if you work as a programmer) or school,
+if any, to sign a "copyright disclaimer" for the program, if necessary.
+For more information on this, and how to apply and follow the GNU GPL, see
+.
+
+ The GNU General Public License does not permit incorporating your program
+into proprietary programs. If your program is a subroutine library, you
+may consider it more useful to permit linking proprietary applications with
+the library. If this is what you want to do, use the GNU Lesser General
+Public License instead of this License. But first, please read
+.
diff --git a/modules/sale_subscription/MANIFEST.in b/modules/sale_subscription/MANIFEST.in
new file mode 100644
index 0000000000..94499680c6
--- /dev/null
+++ b/modules/sale_subscription/MANIFEST.in
@@ -0,0 +1,6 @@
+include CHANGELOG
+include COPYRIGHT
+include LICENSE
+include README.rst
+include doc/*
+include icons/LICENSE
diff --git a/modules/sale_subscription/README.rst b/modules/sale_subscription/README.rst
new file mode 120000
index 0000000000..176d9c2695
--- /dev/null
+++ b/modules/sale_subscription/README.rst
@@ -0,0 +1 @@
+doc/index.rst
\ No newline at end of file
diff --git a/modules/sale_subscription/__init__.py b/modules/sale_subscription/__init__.py
new file mode 100644
index 0000000000..e0bd2096e8
--- /dev/null
+++ b/modules/sale_subscription/__init__.py
@@ -0,0 +1,36 @@
+# This file is part of Tryton. The COPYRIGHT file at the top level of
+# this repository contains the full copyright notices and license terms.
+
+from trytond.pool import Pool
+from . import configuration
+from . import recurrence
+from . import service
+from . import subscription
+from . import invoice
+from . import party
+from . import ir
+
+
+def register():
+ Pool.register(
+ configuration.Configuration,
+ configuration.ConfigurationSequence,
+ recurrence.RecurrenceRuleSet,
+ recurrence.RecurrenceRule,
+ service.Service,
+ subscription.Subscription,
+ subscription.Line,
+ subscription.LineConsumption,
+ subscription.CreateLineConsumptionStart,
+ subscription.CreateSubscriptionInvoiceStart,
+ invoice.InvoiceLine,
+ ir.Cron,
+ module='sale_subscription', type_='model')
+ Pool.register(
+ subscription.CreateLineConsumption,
+ subscription.CreateSubscriptionInvoice,
+ party.Replace,
+ party.Erase,
+ module='sale_subscription', type_='wizard')
+ Pool.register(
+ module='sale_subscription', type_='report')
diff --git a/modules/sale_subscription/configuration.py b/modules/sale_subscription/configuration.py
new file mode 100644
index 0000000000..00e34e296c
--- /dev/null
+++ b/modules/sale_subscription/configuration.py
@@ -0,0 +1,52 @@
+# This file is part of Tryton. The COPYRIGHT file at the top level of
+# this repository contains the full copyright notices and license terms.
+from trytond.model import fields
+from trytond.pool import PoolMeta, Pool
+from trytond.pyson import Eval, Id
+
+
+class Configuration(metaclass=PoolMeta):
+ __name__ = 'sale.configuration'
+
+ subscription_sequence = fields.MultiValue(fields.Many2One(
+ 'ir.sequence', "Subscription Sequence", required=True,
+ domain=[
+ ('company', 'in',
+ [Eval('context', {}).get('company', -1), None]),
+ ('sequence_type', '=',
+ Id('sale_subscription', 'sequence_type_subscription')),
+ ]))
+
+ @classmethod
+ def multivalue_model(cls, field):
+ pool = Pool()
+ if field == 'subscription_sequence':
+ return pool.get('sale.configuration.sequence')
+ return super(Configuration, cls).multivalue_model(field)
+
+ @classmethod
+ def default_subscription_sequence(cls, **pattern):
+ return cls.multivalue_model(
+ 'subscription_sequence').default_subscription_sequence()
+
+
+class ConfigurationSequence(metaclass=PoolMeta):
+ __name__ = 'sale.configuration.sequence'
+ subscription_sequence = fields.Many2One(
+ 'ir.sequence', "Subscription Sequence", required=True,
+ domain=[
+ ('company', 'in', [Eval('company', -1), None]),
+ ('sequence_type', '=',
+ Id('sale_subscription', 'sequence_type_subscription')),
+ ],
+ depends=['company'])
+
+ @classmethod
+ def default_subscription_sequence(cls):
+ pool = Pool()
+ ModelData = pool.get('ir.model.data')
+ try:
+ return ModelData.get_id(
+ 'sale_subscription', 'sequence_subscription')
+ except KeyError:
+ return None
diff --git a/modules/sale_subscription/configuration.xml b/modules/sale_subscription/configuration.xml
new file mode 100644
index 0000000000..e02f1721e3
--- /dev/null
+++ b/modules/sale_subscription/configuration.xml
@@ -0,0 +1,37 @@
+
+
+
+
+
+
+
+ Subscription
+
+
+
+
+
+
+
+
+
+
+
+ Subscription
+
+
+
+
+ sale.configuration
+
+ configuration_form
+
+
+
diff --git a/modules/sale_subscription/doc/index.rst b/modules/sale_subscription/doc/index.rst
new file mode 100644
index 0000000000..3dce7bbd92
--- /dev/null
+++ b/modules/sale_subscription/doc/index.rst
@@ -0,0 +1,86 @@
+Sale Subscription Module
+########################
+
+The sale subscription module defines subscription, services and recurrence rule
+models.
+
+Subscription
+************
+
+A subscription defines how some recurring services are periodically invoiced.
+The invoice is generated based on the consumption of each services. Here is the
+extensive list of the fields:
+
+- Party: The customer.
+- Contact: The contact who placed the order.
+- Invoice Party: An optional different party to invoice.
+- Invoice Address: The invoice address of the customer.
+- Number: The internal reference of the subscription.
+- Reference: The optional external reference of the subscription.
+- Description: An optional description for the subscription.
+- Start Date: The date at which the subscription starts.
+- End Date: The optional end date of the subscription.
+- Invoice Start Date: The date at which the invoice starts to be generated.
+- Invoice Recurrence: The definition of the invoicing recurrence.
+- Payment Term: The payment term to apply on the invoices.
+- Currency: Define the currency to use for the subscription. All service prices
+ will be computed accordingly.
+- Lines:
+
+ - Service: A required reference to the service subscribed.
+ - Description: The description of the service subscribed.
+ - Consumption Recurrence: The optional recurrence of consumption of the
+ service.
+ - Quantity: The quantity consumed on each occurrence.
+ - Unit: The unit of measure of the quantity.
+ - Unit Price: The unit price of the service expressed in the currency of
+ the subscription.
+ - Start Date: An optional later start date than the subscription.
+ - End Date: An optional earlier end date than the subscription.
+
+- States: The state of the subscription. May take one of the following values:
+ Draft, Quotation, Running, Closed, Cancelled.
+- Company: The company which issue the sale order.
+
+A running subscription can be modified by going back to draft and edit. Some
+field may not more be editable if the consumption has already started.
+The draft subscription is momentary stopped until it is set back to running.
+
+The consumptions are created by schedulers or by a wizard.
+Idem for the creation of the invoices.
+
+Service
+*******
+
+A subscription service defines the default consumption of a product. It is
+composed of the fields:
+
+- Product: A product of type service.
+- Consumption Recurrence: The recurrence at which the service is consumed.
+- Consumption Delay: A delay to apply between the date the consumption is
+ created and the date of the consumption.
+
+Recurrence Rule
+***************
+
+It defines combination of rules which compute the occurrence dates.
+
+- Name: The name of the rule.
+- Rules:
+
+ - Exclusive: Define if the rule excludes the resulted dates.
+ - Frequency: Daily, Weekly, Monthly, Yearly.
+ - Interval: The interval of the frequency
+ - By Week Day: Defines the list of weekdays where the recurrence will be
+ applied.
+ - By Month Day: Defines the list of month days to apply the recurrence to.
+ - By Year Day: Defines the list of year days to apply the recurrence to.
+ - By Week Number: Defines the list of week numbers (ISO8601) to apply the
+ recurrence to.
+ - By Month: Defines the list of months to apply the recurrence to.
+ - By Position: Defines the list of occurrence positions.
+ - Week Start Day.
+
+The computation of occurrences is base on the `python-dateutil library`_.
+
+.. _`python-dateutil library`: https://dateutil.readthedocs.io/en/stable/rrule.html
diff --git a/modules/sale_subscription/exceptions.py b/modules/sale_subscription/exceptions.py
new file mode 100644
index 0000000000..d3d2d0c7a7
--- /dev/null
+++ b/modules/sale_subscription/exceptions.py
@@ -0,0 +1,17 @@
+# This file is part of Tryton. The COPYRIGHT file at the top level of
+# this repository contains the full copyright notices and license terms.
+
+from trytond.exceptions import UserError
+from trytond.model.exceptions import ValidationError
+
+
+class InvalidRecurrence(ValidationError):
+ pass
+
+
+class InvoiceError(UserError):
+ pass
+
+
+class RecurrenceRuleValidationError(ValidationError):
+ pass
diff --git a/modules/sale_subscription/icons/LICENSE b/modules/sale_subscription/icons/LICENSE
new file mode 100644
index 0000000000..7a4a3ea242
--- /dev/null
+++ b/modules/sale_subscription/icons/LICENSE
@@ -0,0 +1,202 @@
+
+ Apache License
+ Version 2.0, January 2004
+ http://www.apache.org/licenses/
+
+ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+ 1. Definitions.
+
+ "License" shall mean the terms and conditions for use, reproduction,
+ and distribution as defined by Sections 1 through 9 of this document.
+
+ "Licensor" shall mean the copyright owner or entity authorized by
+ the copyright owner that is granting the License.
+
+ "Legal Entity" shall mean the union of the acting entity and all
+ other entities that control, are controlled by, or are under common
+ control with that entity. For the purposes of this definition,
+ "control" means (i) the power, direct or indirect, to cause the
+ direction or management of such entity, whether by contract or
+ otherwise, or (ii) ownership of fifty percent (50%) or more of the
+ outstanding shares, or (iii) beneficial ownership of such entity.
+
+ "You" (or "Your") shall mean an individual or Legal Entity
+ exercising permissions granted by this License.
+
+ "Source" form shall mean the preferred form for making modifications,
+ including but not limited to software source code, documentation
+ source, and configuration files.
+
+ "Object" form shall mean any form resulting from mechanical
+ transformation or translation of a Source form, including but
+ not limited to compiled object code, generated documentation,
+ and conversions to other media types.
+
+ "Work" shall mean the work of authorship, whether in Source or
+ Object form, made available under the License, as indicated by a
+ copyright notice that is included in or attached to the work
+ (an example is provided in the Appendix below).
+
+ "Derivative Works" shall mean any work, whether in Source or Object
+ form, that is based on (or derived from) the Work and for which the
+ editorial revisions, annotations, elaborations, or other modifications
+ represent, as a whole, an original work of authorship. For the purposes
+ of this License, Derivative Works shall not include works that remain
+ separable from, or merely link (or bind by name) to the interfaces of,
+ the Work and Derivative Works thereof.
+
+ "Contribution" shall mean any work of authorship, including
+ the original version of the Work and any modifications or additions
+ to that Work or Derivative Works thereof, that is intentionally
+ submitted to Licensor for inclusion in the Work by the copyright owner
+ or by an individual or Legal Entity authorized to submit on behalf of
+ the copyright owner. For the purposes of this definition, "submitted"
+ means any form of electronic, verbal, or written communication sent
+ to the Licensor or its representatives, including but not limited to
+ communication on electronic mailing lists, source code control systems,
+ and issue tracking systems that are managed by, or on behalf of, the
+ Licensor for the purpose of discussing and improving the Work, but
+ excluding communication that is conspicuously marked or otherwise
+ designated in writing by the copyright owner as "Not a Contribution."
+
+ "Contributor" shall mean Licensor and any individual or Legal Entity
+ on behalf of whom a Contribution has been received by Licensor and
+ subsequently incorporated within the Work.
+
+ 2. Grant of Copyright License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ copyright license to reproduce, prepare Derivative Works of,
+ publicly display, publicly perform, sublicense, and distribute the
+ Work and such Derivative Works in Source or Object form.
+
+ 3. Grant of Patent License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ (except as stated in this section) patent license to make, have made,
+ use, offer to sell, sell, import, and otherwise transfer the Work,
+ where such license applies only to those patent claims licensable
+ by such Contributor that are necessarily infringed by their
+ Contribution(s) alone or by combination of their Contribution(s)
+ with the Work to which such Contribution(s) was submitted. If You
+ institute patent litigation against any entity (including a
+ cross-claim or counterclaim in a lawsuit) alleging that the Work
+ or a Contribution incorporated within the Work constitutes direct
+ or contributory patent infringement, then any patent licenses
+ granted to You under this License for that Work shall terminate
+ as of the date such litigation is filed.
+
+ 4. Redistribution. You may reproduce and distribute copies of the
+ Work or Derivative Works thereof in any medium, with or without
+ modifications, and in Source or Object form, provided that You
+ meet the following conditions:
+
+ (a) You must give any other recipients of the Work or
+ Derivative Works a copy of this License; and
+
+ (b) You must cause any modified files to carry prominent notices
+ stating that You changed the files; and
+
+ (c) You must retain, in the Source form of any Derivative Works
+ that You distribute, all copyright, patent, trademark, and
+ attribution notices from the Source form of the Work,
+ excluding those notices that do not pertain to any part of
+ the Derivative Works; and
+
+ (d) If the Work includes a "NOTICE" text file as part of its
+ distribution, then any Derivative Works that You distribute must
+ include a readable copy of the attribution notices contained
+ within such NOTICE file, excluding those notices that do not
+ pertain to any part of the Derivative Works, in at least one
+ of the following places: within a NOTICE text file distributed
+ as part of the Derivative Works; within the Source form or
+ documentation, if provided along with the Derivative Works; or,
+ within a display generated by the Derivative Works, if and
+ wherever such third-party notices normally appear. The contents
+ of the NOTICE file are for informational purposes only and
+ do not modify the License. You may add Your own attribution
+ notices within Derivative Works that You distribute, alongside
+ or as an addendum to the NOTICE text from the Work, provided
+ that such additional attribution notices cannot be construed
+ as modifying the License.
+
+ You may add Your own copyright statement to Your modifications and
+ may provide additional or different license terms and conditions
+ for use, reproduction, or distribution of Your modifications, or
+ for any such Derivative Works as a whole, provided Your use,
+ reproduction, and distribution of the Work otherwise complies with
+ the conditions stated in this License.
+
+ 5. Submission of Contributions. Unless You explicitly state otherwise,
+ any Contribution intentionally submitted for inclusion in the Work
+ by You to the Licensor shall be under the terms and conditions of
+ this License, without any additional terms or conditions.
+ Notwithstanding the above, nothing herein shall supersede or modify
+ the terms of any separate license agreement you may have executed
+ with Licensor regarding such Contributions.
+
+ 6. Trademarks. This License does not grant permission to use the trade
+ names, trademarks, service marks, or product names of the Licensor,
+ except as required for reasonable and customary use in describing the
+ origin of the Work and reproducing the content of the NOTICE file.
+
+ 7. Disclaimer of Warranty. Unless required by applicable law or
+ agreed to in writing, Licensor provides the Work (and each
+ Contributor provides its Contributions) on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ implied, including, without limitation, any warranties or conditions
+ of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+ PARTICULAR PURPOSE. You are solely responsible for determining the
+ appropriateness of using or redistributing the Work and assume any
+ risks associated with Your exercise of permissions under this License.
+
+ 8. Limitation of Liability. In no event and under no legal theory,
+ whether in tort (including negligence), contract, or otherwise,
+ unless required by applicable law (such as deliberate and grossly
+ negligent acts) or agreed to in writing, shall any Contributor be
+ liable to You for damages, including any direct, indirect, special,
+ incidental, or consequential damages of any character arising as a
+ result of this License or out of the use or inability to use the
+ Work (including but not limited to damages for loss of goodwill,
+ work stoppage, computer failure or malfunction, or any and all
+ other commercial damages or losses), even if such Contributor
+ has been advised of the possibility of such damages.
+
+ 9. Accepting Warranty or Additional Liability. While redistributing
+ the Work or Derivative Works thereof, You may choose to offer,
+ and charge a fee for, acceptance of support, warranty, indemnity,
+ or other liability obligations and/or rights consistent with this
+ License. However, in accepting such obligations, You may act only
+ on Your own behalf and on Your sole responsibility, not on behalf
+ of any other Contributor, and only if You agree to indemnify,
+ defend, and hold each Contributor harmless for any liability
+ incurred by, or claims asserted against, such Contributor by reason
+ of your accepting any such warranty or additional liability.
+
+ END OF TERMS AND CONDITIONS
+
+ APPENDIX: How to apply the Apache License to your work.
+
+ To apply the Apache License to your work, attach the following
+ boilerplate notice, with the fields enclosed by brackets "[]"
+ replaced with your own identifying information. (Don't include
+ the brackets!) The text should be enclosed in the appropriate
+ comment syntax for the file format. We also recommend that a
+ file or class name and description of purpose be included on the
+ same "printed page" as the copyright notice for easier
+ identification within third-party archives.
+
+ Copyright [yyyy] [name of copyright owner]
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
\ No newline at end of file
diff --git a/modules/sale_subscription/icons/tryton-sale-subscription.svg b/modules/sale_subscription/icons/tryton-sale-subscription.svg
new file mode 100644
index 0000000000..03e282bce5
--- /dev/null
+++ b/modules/sale_subscription/icons/tryton-sale-subscription.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/modules/sale_subscription/invoice.py b/modules/sale_subscription/invoice.py
new file mode 100644
index 0000000000..6b3958c22b
--- /dev/null
+++ b/modules/sale_subscription/invoice.py
@@ -0,0 +1,22 @@
+# This file is part of Tryton. The COPYRIGHT file at the top level of
+# this repository contains the full copyright notices and license terms.
+from trytond.pool import Pool, PoolMeta
+
+
+class InvoiceLine(metaclass=PoolMeta):
+ __name__ = 'account.invoice.line'
+
+ @property
+ def origin_name(self):
+ pool = Pool()
+ SubscriptionLine = pool.get('sale.subscription.line')
+ name = super(InvoiceLine, self).origin_name
+ if isinstance(self.origin, SubscriptionLine):
+ name = self.origin.subscription.rec_name
+ return name
+
+ @classmethod
+ def _get_origin(cls):
+ models = super(InvoiceLine, cls)._get_origin()
+ models.append('sale.subscription.line')
+ return models
diff --git a/modules/sale_subscription/ir.py b/modules/sale_subscription/ir.py
new file mode 100644
index 0000000000..6bccef6a1e
--- /dev/null
+++ b/modules/sale_subscription/ir.py
@@ -0,0 +1,17 @@
+# This file is part of Tryton. The COPYRIGHT file at the top level of
+# this repository contains the full copyright notices and license terms.
+from trytond.pool import PoolMeta
+
+
+class Cron(metaclass=PoolMeta):
+ __name__ = 'ir.cron'
+
+ @classmethod
+ def __setup__(cls):
+ super().__setup__()
+ cls.method.selection.extend([
+ ('sale.subscription.line|generate_consumption',
+ "Generate Subscription Line Consumptions"),
+ ('sale.subscription|generate_invoice',
+ "Generate Subscription Invoices"),
+ ])
diff --git a/modules/sale_subscription/locale/bg.po b/modules/sale_subscription/locale/bg.po
new file mode 100644
index 0000000000..4e46c4f6c0
--- /dev/null
+++ b/modules/sale_subscription/locale/bg.po
@@ -0,0 +1,611 @@
+#
+msgid ""
+msgstr "Content-Type: text/plain; charset=utf-8\n"
+
+#, fuzzy
+msgctxt "field:sale.configuration,subscription_sequence:"
+msgid "Subscription Sequence"
+msgstr "Subscription Services"
+
+#, fuzzy
+msgctxt "field:sale.configuration.sequence,subscription_sequence:"
+msgid "Subscription Sequence"
+msgstr "Subscription Services"
+
+msgctxt "field:sale.subscription,company:"
+msgid "Company"
+msgstr ""
+
+msgctxt "field:sale.subscription,contact:"
+msgid "Contact"
+msgstr ""
+
+msgctxt "field:sale.subscription,currency:"
+msgid "Currency"
+msgstr ""
+
+#, fuzzy
+msgctxt "field:sale.subscription,description:"
+msgid "Description"
+msgstr "Subscription"
+
+msgctxt "field:sale.subscription,end_date:"
+msgid "End Date"
+msgstr ""
+
+msgctxt "field:sale.subscription,invoice_address:"
+msgid "Invoice Address"
+msgstr ""
+
+msgctxt "field:sale.subscription,invoice_party:"
+msgid "Invoice Party"
+msgstr ""
+
+msgctxt "field:sale.subscription,invoice_recurrence:"
+msgid "Invoice Recurrence"
+msgstr ""
+
+msgctxt "field:sale.subscription,invoice_start_date:"
+msgid "Invoice Start Date"
+msgstr ""
+
+msgctxt "field:sale.subscription,lines:"
+msgid "Lines"
+msgstr ""
+
+msgctxt "field:sale.subscription,next_invoice_date:"
+msgid "Next Invoice Date"
+msgstr ""
+
+msgctxt "field:sale.subscription,number:"
+msgid "Number"
+msgstr ""
+
+msgctxt "field:sale.subscription,party:"
+msgid "Party"
+msgstr ""
+
+msgctxt "field:sale.subscription,payment_term:"
+msgid "Payment Term"
+msgstr ""
+
+#, fuzzy
+msgctxt "field:sale.subscription,quoted_by:"
+msgid "Quoted By"
+msgstr "Quote"
+
+msgctxt "field:sale.subscription,reference:"
+msgid "Reference"
+msgstr ""
+
+msgctxt "field:sale.subscription,run_by:"
+msgid "Run By"
+msgstr ""
+
+msgctxt "field:sale.subscription,start_date:"
+msgid "Start Date"
+msgstr ""
+
+msgctxt "field:sale.subscription,state:"
+msgid "State"
+msgstr ""
+
+msgctxt "field:sale.subscription.create_invoice.start,date:"
+msgid "Date"
+msgstr ""
+
+msgctxt "field:sale.subscription.line,company:"
+msgid "Company"
+msgstr ""
+
+#, fuzzy
+msgctxt "field:sale.subscription.line,consumed_until:"
+msgid "Consumed until"
+msgstr "Consumptions"
+
+msgctxt "field:sale.subscription.line,consumption_delay:"
+msgid "Consumption Delay"
+msgstr ""
+
+msgctxt "field:sale.subscription.line,consumption_recurrence:"
+msgid "Consumption Recurrence"
+msgstr ""
+
+msgctxt "field:sale.subscription.line,currency:"
+msgid "Currency"
+msgstr ""
+
+#, fuzzy
+msgctxt "field:sale.subscription.line,description:"
+msgid "Description"
+msgstr "Subscription"
+
+msgctxt "field:sale.subscription.line,end_date:"
+msgid "End Date"
+msgstr ""
+
+msgctxt "field:sale.subscription.line,next_consumption_date:"
+msgid "Next Consumption Date"
+msgstr ""
+
+msgctxt "field:sale.subscription.line,next_consumption_date_delayed:"
+msgid "Next Consumption Delayed"
+msgstr ""
+
+msgctxt "field:sale.subscription.line,quantity:"
+msgid "Quantity"
+msgstr ""
+
+msgctxt "field:sale.subscription.line,service:"
+msgid "Service"
+msgstr ""
+
+msgctxt "field:sale.subscription.line,service_unit_category:"
+msgid "Service Unit Category"
+msgstr ""
+
+msgctxt "field:sale.subscription.line,start_date:"
+msgid "Start Date"
+msgstr ""
+
+#, fuzzy
+msgctxt "field:sale.subscription.line,subscription:"
+msgid "Subscription"
+msgstr "Subscription"
+
+#, fuzzy
+msgctxt "field:sale.subscription.line,subscription_end_date:"
+msgid "Subscription End Date"
+msgstr "Subscription Services"
+
+#, fuzzy
+msgctxt "field:sale.subscription.line,subscription_start_date:"
+msgid "Subscription Start Date"
+msgstr "Subscription Services"
+
+#, fuzzy
+msgctxt "field:sale.subscription.line,subscription_state:"
+msgid "Subscription State"
+msgstr "Subscription Services"
+
+msgctxt "field:sale.subscription.line,unit:"
+msgid "Unit"
+msgstr ""
+
+msgctxt "field:sale.subscription.line,unit_digits:"
+msgid "Unit Digits"
+msgstr ""
+
+msgctxt "field:sale.subscription.line,unit_price:"
+msgid "Unit Price"
+msgstr ""
+
+msgctxt "field:sale.subscription.line.consumption,date:"
+msgid "Date"
+msgstr ""
+
+msgctxt "field:sale.subscription.line.consumption,invoice_line:"
+msgid "Invoice Line"
+msgstr ""
+
+msgctxt "field:sale.subscription.line.consumption,line:"
+msgid "Line"
+msgstr ""
+
+msgctxt "field:sale.subscription.line.consumption,quantity:"
+msgid "Quantity"
+msgstr ""
+
+msgctxt "field:sale.subscription.line.consumption,unit_digits:"
+msgid "Unit Digits"
+msgstr ""
+
+msgctxt "field:sale.subscription.line.consumption.create.start,date:"
+msgid "Date"
+msgstr ""
+
+msgctxt "field:sale.subscription.recurrence.rule,bymonth:"
+msgid "By Month"
+msgstr ""
+
+msgctxt "field:sale.subscription.recurrence.rule,bymonthday:"
+msgid "By Month Day"
+msgstr ""
+
+msgctxt "field:sale.subscription.recurrence.rule,bysetpos:"
+msgid "By Position"
+msgstr ""
+
+msgctxt "field:sale.subscription.recurrence.rule,byweekday:"
+msgid "By Week Day"
+msgstr ""
+
+msgctxt "field:sale.subscription.recurrence.rule,byweekno:"
+msgid "By Week Number"
+msgstr ""
+
+msgctxt "field:sale.subscription.recurrence.rule,byyearday:"
+msgid "By Year Day"
+msgstr ""
+
+msgctxt "field:sale.subscription.recurrence.rule,exclusive:"
+msgid "Exclusive"
+msgstr ""
+
+msgctxt "field:sale.subscription.recurrence.rule,freq:"
+msgid "Frequency"
+msgstr ""
+
+msgctxt "field:sale.subscription.recurrence.rule,interval:"
+msgid "Interval"
+msgstr ""
+
+msgctxt "field:sale.subscription.recurrence.rule,set_:"
+msgid "Set"
+msgstr ""
+
+msgctxt "field:sale.subscription.recurrence.rule,week_start_day:"
+msgid "Week Start Day"
+msgstr ""
+
+msgctxt "field:sale.subscription.recurrence.rule.set,name:"
+msgid "Name"
+msgstr ""
+
+msgctxt "field:sale.subscription.recurrence.rule.set,rules:"
+msgid "Rules"
+msgstr ""
+
+msgctxt "field:sale.subscription.service,consumption_delay:"
+msgid "Consumption Delay"
+msgstr ""
+
+msgctxt "field:sale.subscription.service,consumption_recurrence:"
+msgid "Consumption Recurrence"
+msgstr ""
+
+msgctxt "field:sale.subscription.service,product:"
+msgid "Product"
+msgstr ""
+
+msgctxt "help:sale.subscription,company:"
+msgid "Make the subscription belong to the company."
+msgstr ""
+
+msgctxt "help:sale.subscription,number:"
+msgid "The main identification of the subscription."
+msgstr ""
+
+msgctxt "help:sale.subscription,party:"
+msgid "The party who subscribes."
+msgstr ""
+
+msgctxt "help:sale.subscription,reference:"
+msgid "The identification of an external origin."
+msgstr ""
+
+msgctxt "help:sale.subscription,state:"
+msgid "The current state of the subscription."
+msgstr ""
+
+msgctxt "help:sale.subscription.line,subscription:"
+msgid "Add the line below the subscription."
+msgstr ""
+
+msgctxt "help:sale.subscription.recurrence.rule,bymonth:"
+msgid "A comma separated list of integers."
+msgstr ""
+
+msgctxt "help:sale.subscription.recurrence.rule,bymonthday:"
+msgid "A comma separated list of integers."
+msgstr ""
+
+msgctxt "help:sale.subscription.recurrence.rule,bysetpos:"
+msgid "A comma separated list of integers."
+msgstr ""
+
+msgctxt "help:sale.subscription.recurrence.rule,byweekday:"
+msgid "A comma separated list of integers or weekday (MO, TU etc)."
+msgstr ""
+
+msgctxt "help:sale.subscription.recurrence.rule,byweekno:"
+msgid "A comma separated list of integers (ISO8601)."
+msgstr ""
+
+msgctxt "help:sale.subscription.recurrence.rule,byyearday:"
+msgid "A comma separated list of integers."
+msgstr ""
+
+msgctxt "help:sale.subscription.recurrence.rule,set_:"
+msgid "Add the rule below the set."
+msgstr ""
+
+msgctxt "help:sale.subscription.recurrence.rule.set,name:"
+msgid "The main identifier of the rule set."
+msgstr ""
+
+msgctxt "model:ir.action,name:act_create_invoice"
+msgid "Create Subscription Invoices"
+msgstr "Create Subscription Invoices"
+
+msgctxt "model:ir.action,name:act_line_consumption_create"
+msgid "Create Line Consumptions"
+msgstr "Create Line Consumptions"
+
+msgctxt "model:ir.action,name:act_recurrence_rule_set_form"
+msgid "Subscription Recurrence Rule Sets"
+msgstr "Subscription Recurrence Rule Sets"
+
+msgctxt "model:ir.action,name:act_service_form"
+msgid "Subscription Services"
+msgstr "Subscription Services"
+
+msgctxt "model:ir.action,name:act_subscription_form"
+msgid "Subscriptions"
+msgstr "Subscriptions"
+
+msgctxt "model:ir.action,name:act_subscription_invoice_relate"
+msgid "Invoices"
+msgstr ""
+
+msgctxt "model:ir.action,name:act_subscription_line_consumption_form"
+msgid "Consumptions"
+msgstr "Consumptions"
+
+msgctxt ""
+"model:ir.action,name:act_subscription_line_consumption_subscription_line_relate"
+msgid "Consumptions"
+msgstr "Consumptions"
+
+msgctxt ""
+"model:ir.action,name:act_subscription_line_consumption_subscription_relate"
+msgid "Consumptions"
+msgstr "Consumptions"
+
+msgctxt "model:ir.action,name:act_subscription_party_relate"
+msgid "Subscriptions"
+msgstr "Subscriptions"
+
+msgctxt ""
+"model:ir.action.act_window.domain,name:act_subscription_form_domain_all"
+msgid "All"
+msgstr "All"
+
+msgctxt ""
+"model:ir.action.act_window.domain,name:act_subscription_form_domain_draft"
+msgid "Draft"
+msgstr "Draft"
+
+msgctxt ""
+"model:ir.action.act_window.domain,name:act_subscription_form_domain_quotation"
+msgid "Quotation"
+msgstr "Quotation"
+
+msgctxt ""
+"model:ir.action.act_window.domain,name:act_subscription_form_domain_running"
+msgid "Running"
+msgstr "Running"
+
+msgctxt "model:ir.message,text:msg_consumption_delete_invoiced"
+msgid "You cannot delete invoiced consumption \"%(consumption)s\"."
+msgstr ""
+
+msgctxt ""
+"model:ir.message,text:msg_consumption_invoice_missing_account_revenue"
+msgid ""
+"To invoice consumptions you must define an account revenue for product "
+"\"%(product)s\"."
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_consumption_modify_invoiced"
+msgid "You cannot modify invoiced consumption \"%(consumption)s\"."
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_consumption_recurrence_invalid"
+msgid ""
+"The consumption recurrence of line \"%(line)s\" of subscription "
+"\"%(subscription)s\" does not generate any occurrence."
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_erase_party_pending_subscription"
+msgid ""
+"You cannot erase party \"%(party)s\" while they have pending subscriptions "
+"with company \"%(company)s\"."
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_invoice_recurrence_invalid"
+msgid ""
+"The invoice recurrence of subscription \"%(subscription)s\" does not "
+"generate any occurrence."
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_recurrence_rule_invalid_by"
+msgid ""
+"Invalid \"%(field)s\" \"%(value)s\" in recurence rule "
+"\"%(recurrence_rule)s\" with exception \"%(exception)s\"."
+msgstr ""
+
+msgctxt "model:ir.model.button,string:subscription_cancel_button"
+msgid "Cancel"
+msgstr "Cancel"
+
+msgctxt "model:ir.model.button,string:subscription_draft_button"
+msgid "Draft"
+msgstr "Draft"
+
+msgctxt "model:ir.model.button,string:subscription_quote_button"
+msgid "Quote"
+msgstr "Quote"
+
+msgctxt "model:ir.model.button,string:subscription_run_button"
+msgid "Run"
+msgstr "Run"
+
+msgctxt "model:ir.rule.group,name:rule_group_subscription_companies"
+msgid "User in companies"
+msgstr ""
+
+msgctxt "model:ir.sequence,name:sequence_subscription"
+msgid "Subscription"
+msgstr "Subscription"
+
+msgctxt "model:ir.sequence.type,name:sequence_type_subscription"
+msgid "Subscription"
+msgstr "Subscription"
+
+#, fuzzy
+msgctxt "model:ir.ui.menu,name:menu_configuration"
+msgid "Subscription"
+msgstr "Subscription"
+
+msgctxt "model:ir.ui.menu,name:menu_create_invoice"
+msgid "Create Subscription Invoices"
+msgstr "Create Subscription Invoices"
+
+msgctxt "model:ir.ui.menu,name:menu_line_consumption_create"
+msgid "Create Line Consumptions"
+msgstr "Create Line Consumptions"
+
+msgctxt "model:ir.ui.menu,name:menu_recurrence_rule_set_form"
+msgid "Subscription Recurrence Rule Sets"
+msgstr "Subscription Recurrence Rule Sets"
+
+msgctxt "model:ir.ui.menu,name:menu_service_form"
+msgid "Subscription Services"
+msgstr "Subscription Services"
+
+msgctxt "model:ir.ui.menu,name:menu_subscription_form"
+msgid "Subscriptions"
+msgstr "Subscriptions"
+
+#, fuzzy
+msgctxt "model:sale.subscription,name:"
+msgid "Subscription"
+msgstr "Subscription"
+
+#, fuzzy
+msgctxt "model:sale.subscription.create_invoice.start,name:"
+msgid "Create Subscription Invoice"
+msgstr "Create Subscription Invoices"
+
+#, fuzzy
+msgctxt "model:sale.subscription.line,name:"
+msgid "Subscription Line"
+msgstr "Subscription Services"
+
+#, fuzzy
+msgctxt "model:sale.subscription.line.consumption,name:"
+msgid "Subscription Line Consumption"
+msgstr "Generate Subscription Line Consumptions"
+
+#, fuzzy
+msgctxt "model:sale.subscription.line.consumption.create.start,name:"
+msgid "Create Subscription Line Consumption"
+msgstr "Generate Subscription Line Consumptions"
+
+#, fuzzy
+msgctxt "model:sale.subscription.recurrence.rule,name:"
+msgid "Subscription Recurrence Rule"
+msgstr "Subscription Recurrence Rule Sets"
+
+#, fuzzy
+msgctxt "model:sale.subscription.recurrence.rule.set,name:"
+msgid "Subscription Recurrence Rule Set"
+msgstr "Subscription Recurrence Rule Sets"
+
+#, fuzzy
+msgctxt "model:sale.subscription.service,name:"
+msgid "Subscription Service"
+msgstr "Subscription Services"
+
+#, fuzzy
+msgctxt "selection:ir.cron,method:"
+msgid "Generate Subscription Invoices"
+msgstr "Generate Subscription Invoices"
+
+#, fuzzy
+msgctxt "selection:ir.cron,method:"
+msgid "Generate Subscription Line Consumptions"
+msgstr "Generate Subscription Line Consumptions"
+
+#, fuzzy
+msgctxt "selection:sale.subscription,state:"
+msgid "Cancelled"
+msgstr "Cancel"
+
+msgctxt "selection:sale.subscription,state:"
+msgid "Closed"
+msgstr ""
+
+#, fuzzy
+msgctxt "selection:sale.subscription,state:"
+msgid "Draft"
+msgstr "Draft"
+
+#, fuzzy
+msgctxt "selection:sale.subscription,state:"
+msgid "Quotation"
+msgstr "Quotation"
+
+#, fuzzy
+msgctxt "selection:sale.subscription,state:"
+msgid "Running"
+msgstr "Running"
+
+msgctxt "selection:sale.subscription.recurrence.rule,freq:"
+msgid "Daily"
+msgstr ""
+
+msgctxt "selection:sale.subscription.recurrence.rule,freq:"
+msgid "Monthly"
+msgstr ""
+
+msgctxt "selection:sale.subscription.recurrence.rule,freq:"
+msgid "Weekly"
+msgstr ""
+
+msgctxt "selection:sale.subscription.recurrence.rule,freq:"
+msgid "Yearly"
+msgstr ""
+
+#, fuzzy
+msgctxt "view:sale.subscription.create_invoice.start:"
+msgid "Create Subscription Invoices for date"
+msgstr "Create Subscription Invoices"
+
+#, fuzzy
+msgctxt "view:sale.subscription.line.consumption.create.start:"
+msgid "Create Subscription Line Consumptions for date"
+msgstr "Generate Subscription Line Consumptions"
+
+msgctxt "view:sale.subscription.line:"
+msgid "General"
+msgstr ""
+
+msgctxt "view:sale.subscription:"
+msgid "Other Info"
+msgstr ""
+
+#, fuzzy
+msgctxt "view:sale.subscription:"
+msgid "Subscription"
+msgstr "Subscription"
+
+msgctxt "wizard_button:sale.subscription.create_invoice,start,create_:"
+msgid "Create"
+msgstr ""
+
+#, fuzzy
+msgctxt "wizard_button:sale.subscription.create_invoice,start,end:"
+msgid "Cancel"
+msgstr "Cancel"
+
+msgctxt ""
+"wizard_button:sale.subscription.line.consumption.create,start,create_:"
+msgid "Create"
+msgstr ""
+
+#, fuzzy
+msgctxt "wizard_button:sale.subscription.line.consumption.create,start,end:"
+msgid "Cancel"
+msgstr "Cancel"
diff --git a/modules/sale_subscription/locale/ca.po b/modules/sale_subscription/locale/ca.po
new file mode 100644
index 0000000000..f9327874a9
--- /dev/null
+++ b/modules/sale_subscription/locale/ca.po
@@ -0,0 +1,592 @@
+#
+msgid ""
+msgstr "Content-Type: text/plain; charset=utf-8\n"
+
+msgctxt "field:sale.configuration,subscription_sequence:"
+msgid "Subscription Sequence"
+msgstr "Seqüència de subscripció"
+
+msgctxt "field:sale.configuration.sequence,subscription_sequence:"
+msgid "Subscription Sequence"
+msgstr "Seqüència de subscripció"
+
+msgctxt "field:sale.subscription,company:"
+msgid "Company"
+msgstr "Empresa"
+
+msgctxt "field:sale.subscription,contact:"
+msgid "Contact"
+msgstr "Contacte"
+
+msgctxt "field:sale.subscription,currency:"
+msgid "Currency"
+msgstr "Moneda"
+
+msgctxt "field:sale.subscription,description:"
+msgid "Description"
+msgstr "Descripció"
+
+msgctxt "field:sale.subscription,end_date:"
+msgid "End Date"
+msgstr "Data final"
+
+msgctxt "field:sale.subscription,invoice_address:"
+msgid "Invoice Address"
+msgstr "Adreça de facturació"
+
+msgctxt "field:sale.subscription,invoice_party:"
+msgid "Invoice Party"
+msgstr "Tercer de la factura"
+
+msgctxt "field:sale.subscription,invoice_recurrence:"
+msgid "Invoice Recurrence"
+msgstr "Recurrència factura"
+
+msgctxt "field:sale.subscription,invoice_start_date:"
+msgid "Invoice Start Date"
+msgstr "Data inici factura"
+
+msgctxt "field:sale.subscription,lines:"
+msgid "Lines"
+msgstr "Línies"
+
+msgctxt "field:sale.subscription,next_invoice_date:"
+msgid "Next Invoice Date"
+msgstr "Data següent factura"
+
+msgctxt "field:sale.subscription,number:"
+msgid "Number"
+msgstr "Número"
+
+msgctxt "field:sale.subscription,party:"
+msgid "Party"
+msgstr "Tercer"
+
+msgctxt "field:sale.subscription,payment_term:"
+msgid "Payment Term"
+msgstr "Termini de pagament"
+
+msgctxt "field:sale.subscription,quoted_by:"
+msgid "Quoted By"
+msgstr "Pressupostada per"
+
+msgctxt "field:sale.subscription,reference:"
+msgid "Reference"
+msgstr "Referència"
+
+msgctxt "field:sale.subscription,run_by:"
+msgid "Run By"
+msgstr "Executat per"
+
+msgctxt "field:sale.subscription,start_date:"
+msgid "Start Date"
+msgstr "Data inicial"
+
+msgctxt "field:sale.subscription,state:"
+msgid "State"
+msgstr "Estat"
+
+msgctxt "field:sale.subscription.create_invoice.start,date:"
+msgid "Date"
+msgstr "Data"
+
+msgctxt "field:sale.subscription.line,company:"
+msgid "Company"
+msgstr "Empresa"
+
+msgctxt "field:sale.subscription.line,consumed_until:"
+msgid "Consumed until"
+msgstr "Consumit fins"
+
+msgctxt "field:sale.subscription.line,consumption_delay:"
+msgid "Consumption Delay"
+msgstr "Retard consum"
+
+msgctxt "field:sale.subscription.line,consumption_recurrence:"
+msgid "Consumption Recurrence"
+msgstr "Recurrència consum"
+
+msgctxt "field:sale.subscription.line,currency:"
+msgid "Currency"
+msgstr "Moneda"
+
+msgctxt "field:sale.subscription.line,description:"
+msgid "Description"
+msgstr "Descripció"
+
+msgctxt "field:sale.subscription.line,end_date:"
+msgid "End Date"
+msgstr "Data final"
+
+msgctxt "field:sale.subscription.line,next_consumption_date:"
+msgid "Next Consumption Date"
+msgstr "Data següent consum"
+
+msgctxt "field:sale.subscription.line,next_consumption_date_delayed:"
+msgid "Next Consumption Delayed"
+msgstr "Següent consum amb retard"
+
+msgctxt "field:sale.subscription.line,quantity:"
+msgid "Quantity"
+msgstr "Quantitat"
+
+msgctxt "field:sale.subscription.line,service:"
+msgid "Service"
+msgstr "Servei"
+
+msgctxt "field:sale.subscription.line,service_unit_category:"
+msgid "Service Unit Category"
+msgstr "Categoria d'unitat del servei"
+
+msgctxt "field:sale.subscription.line,start_date:"
+msgid "Start Date"
+msgstr "Data inicial"
+
+msgctxt "field:sale.subscription.line,subscription:"
+msgid "Subscription"
+msgstr "Subscripció"
+
+msgctxt "field:sale.subscription.line,subscription_end_date:"
+msgid "Subscription End Date"
+msgstr "Data final subscripció"
+
+msgctxt "field:sale.subscription.line,subscription_start_date:"
+msgid "Subscription Start Date"
+msgstr "Data inici subscripció"
+
+msgctxt "field:sale.subscription.line,subscription_state:"
+msgid "Subscription State"
+msgstr "Estat subscripció"
+
+msgctxt "field:sale.subscription.line,unit:"
+msgid "Unit"
+msgstr "Unitat"
+
+msgctxt "field:sale.subscription.line,unit_digits:"
+msgid "Unit Digits"
+msgstr "Dígits de la unitat"
+
+msgctxt "field:sale.subscription.line,unit_price:"
+msgid "Unit Price"
+msgstr "Preu unitari"
+
+msgctxt "field:sale.subscription.line.consumption,date:"
+msgid "Date"
+msgstr "Data"
+
+msgctxt "field:sale.subscription.line.consumption,invoice_line:"
+msgid "Invoice Line"
+msgstr "Línia de factura"
+
+msgctxt "field:sale.subscription.line.consumption,line:"
+msgid "Line"
+msgstr "Línia"
+
+msgctxt "field:sale.subscription.line.consumption,quantity:"
+msgid "Quantity"
+msgstr "Quantitat"
+
+msgctxt "field:sale.subscription.line.consumption,unit_digits:"
+msgid "Unit Digits"
+msgstr "Dígits de la unitat"
+
+msgctxt "field:sale.subscription.line.consumption.create.start,date:"
+msgid "Date"
+msgstr "Data"
+
+msgctxt "field:sale.subscription.recurrence.rule,bymonth:"
+msgid "By Month"
+msgstr "El més"
+
+msgctxt "field:sale.subscription.recurrence.rule,bymonthday:"
+msgid "By Month Day"
+msgstr "El dia del més"
+
+msgctxt "field:sale.subscription.recurrence.rule,bysetpos:"
+msgid "By Position"
+msgstr "La posició"
+
+msgctxt "field:sale.subscription.recurrence.rule,byweekday:"
+msgid "By Week Day"
+msgstr "El dia de la setmana"
+
+msgctxt "field:sale.subscription.recurrence.rule,byweekno:"
+msgid "By Week Number"
+msgstr "El nombre de setmana"
+
+msgctxt "field:sale.subscription.recurrence.rule,byyearday:"
+msgid "By Year Day"
+msgstr "El dia de l'any"
+
+msgctxt "field:sale.subscription.recurrence.rule,exclusive:"
+msgid "Exclusive"
+msgstr "Exclusiu"
+
+msgctxt "field:sale.subscription.recurrence.rule,freq:"
+msgid "Frequency"
+msgstr "Freqüència"
+
+msgctxt "field:sale.subscription.recurrence.rule,interval:"
+msgid "Interval"
+msgstr "Interval"
+
+msgctxt "field:sale.subscription.recurrence.rule,set_:"
+msgid "Set"
+msgstr "Conjunt"
+
+msgctxt "field:sale.subscription.recurrence.rule,week_start_day:"
+msgid "Week Start Day"
+msgstr "Dia setmana inici"
+
+msgctxt "field:sale.subscription.recurrence.rule.set,name:"
+msgid "Name"
+msgstr "Nom"
+
+msgctxt "field:sale.subscription.recurrence.rule.set,rules:"
+msgid "Rules"
+msgstr "Regles"
+
+msgctxt "field:sale.subscription.service,consumption_delay:"
+msgid "Consumption Delay"
+msgstr "Retràs consum"
+
+msgctxt "field:sale.subscription.service,consumption_recurrence:"
+msgid "Consumption Recurrence"
+msgstr "Recurrència consum"
+
+msgctxt "field:sale.subscription.service,product:"
+msgid "Product"
+msgstr "Producte"
+
+msgctxt "help:sale.subscription,company:"
+msgid "Make the subscription belong to the company."
+msgstr "Feu que la subscripció pertanyi a l'empresa."
+
+msgctxt "help:sale.subscription,number:"
+msgid "The main identification of the subscription."
+msgstr "El identificador principal de la subscripció."
+
+msgctxt "help:sale.subscription,party:"
+msgid "The party who subscribes."
+msgstr "El tercer que es subscriu."
+
+msgctxt "help:sale.subscription,reference:"
+msgid "The identification of an external origin."
+msgstr "La identificació d'un origen extern."
+
+msgctxt "help:sale.subscription,state:"
+msgid "The current state of the subscription."
+msgstr "L'estat actual de la subscripció."
+
+msgctxt "help:sale.subscription.line,subscription:"
+msgid "Add the line below the subscription."
+msgstr "Afegiu línies a la subscripció."
+
+msgctxt "help:sale.subscription.recurrence.rule,bymonth:"
+msgid "A comma separated list of integers."
+msgstr "Una llista de nombres separada per comes."
+
+msgctxt "help:sale.subscription.recurrence.rule,bymonthday:"
+msgid "A comma separated list of integers."
+msgstr "Una llista de nombres separada per comes."
+
+msgctxt "help:sale.subscription.recurrence.rule,bysetpos:"
+msgid "A comma separated list of integers."
+msgstr "Una llista de nombres separada per comes."
+
+msgctxt "help:sale.subscription.recurrence.rule,byweekday:"
+msgid "A comma separated list of integers or weekday (MO, TU etc)."
+msgstr ""
+"Una llista de nombres o dies de la setmana (MO, TU, etc) separada per comes."
+
+msgctxt "help:sale.subscription.recurrence.rule,byweekno:"
+msgid "A comma separated list of integers (ISO8601)."
+msgstr "Una llista de nombres (ISO8601) separada per comes."
+
+msgctxt "help:sale.subscription.recurrence.rule,byyearday:"
+msgid "A comma separated list of integers."
+msgstr "Una llista de nombres separada per comes."
+
+msgctxt "help:sale.subscription.recurrence.rule,set_:"
+msgid "Add the rule below the set."
+msgstr "Afegir regles al conjunt."
+
+msgctxt "help:sale.subscription.recurrence.rule.set,name:"
+msgid "The main identifier of the rule set."
+msgstr "El identificador principal del conjunt de regles."
+
+msgctxt "model:ir.action,name:act_create_invoice"
+msgid "Create Subscription Invoices"
+msgstr "Crea factures de subscripció"
+
+msgctxt "model:ir.action,name:act_line_consumption_create"
+msgid "Create Line Consumptions"
+msgstr "Crea consums de les línies"
+
+msgctxt "model:ir.action,name:act_recurrence_rule_set_form"
+msgid "Subscription Recurrence Rule Sets"
+msgstr "Conjunts de regles de recurrència"
+
+msgctxt "model:ir.action,name:act_service_form"
+msgid "Subscription Services"
+msgstr "Serveis de subscripció"
+
+msgctxt "model:ir.action,name:act_subscription_form"
+msgid "Subscriptions"
+msgstr "Subscripcions"
+
+msgctxt "model:ir.action,name:act_subscription_invoice_relate"
+msgid "Invoices"
+msgstr "Factures"
+
+msgctxt "model:ir.action,name:act_subscription_line_consumption_form"
+msgid "Consumptions"
+msgstr "Consums"
+
+msgctxt ""
+"model:ir.action,name:act_subscription_line_consumption_subscription_line_relate"
+msgid "Consumptions"
+msgstr "Consums"
+
+msgctxt ""
+"model:ir.action,name:act_subscription_line_consumption_subscription_relate"
+msgid "Consumptions"
+msgstr "Consums"
+
+msgctxt "model:ir.action,name:act_subscription_party_relate"
+msgid "Subscriptions"
+msgstr "Subscripcions"
+
+msgctxt ""
+"model:ir.action.act_window.domain,name:act_subscription_form_domain_all"
+msgid "All"
+msgstr "Tot"
+
+msgctxt ""
+"model:ir.action.act_window.domain,name:act_subscription_form_domain_draft"
+msgid "Draft"
+msgstr "Esborrany"
+
+msgctxt ""
+"model:ir.action.act_window.domain,name:act_subscription_form_domain_quotation"
+msgid "Quotation"
+msgstr "Pressupost"
+
+msgctxt ""
+"model:ir.action.act_window.domain,name:act_subscription_form_domain_running"
+msgid "Running"
+msgstr "En execució"
+
+msgctxt "model:ir.message,text:msg_consumption_delete_invoiced"
+msgid "You cannot delete invoiced consumption \"%(consumption)s\"."
+msgstr "No podeu eliminar el consum facturat \"%(consumption)s\"."
+
+msgctxt ""
+"model:ir.message,text:msg_consumption_invoice_missing_account_revenue"
+msgid ""
+"To invoice consumptions you must define an account revenue for product "
+"\"%(product)s\"."
+msgstr ""
+"Per facturar els consums heu de definir un compte d'ingressos pel producte "
+"\"%(product)s\"."
+
+msgctxt "model:ir.message,text:msg_consumption_modify_invoiced"
+msgid "You cannot modify invoiced consumption \"%(consumption)s\"."
+msgstr "No podeu modificar el consum facturat \"%(consumption)s\"."
+
+msgctxt "model:ir.message,text:msg_consumption_recurrence_invalid"
+msgid ""
+"The consumption recurrence of line \"%(line)s\" of subscription "
+"\"%(subscription)s\" does not generate any occurrence."
+msgstr ""
+"El recurrència de consum de la línia \"%(line)s\" de la subscripció "
+"\"%(subscription)s\" no genera cap ocurrència."
+
+msgctxt "model:ir.message,text:msg_erase_party_pending_subscription"
+msgid ""
+"You cannot erase party \"%(party)s\" while they have pending subscriptions "
+"with company \"%(company)s\"."
+msgstr ""
+"No podeu eliminar el tercer \"%(party)s\" mentre tingui subscripcions "
+"pendents amb l'empresa \"%(company)s\"."
+
+msgctxt "model:ir.message,text:msg_invoice_recurrence_invalid"
+msgid ""
+"The invoice recurrence of subscription \"%(subscription)s\" does not "
+"generate any occurrence."
+msgstr ""
+"El recurrència de facturació de la subscripció \"%(subscription)s\" no "
+"genera cap ocurrència."
+
+msgctxt "model:ir.message,text:msg_recurrence_rule_invalid_by"
+msgid ""
+"Invalid \"%(field)s\" \"%(value)s\" in recurence rule "
+"\"%(recurrence_rule)s\" with exception \"%(exception)s\"."
+msgstr ""
+"Invalid \"%(fields)\" \"%(value)s\" a la regla de recurrència "
+"\"%(recurrence_rule)s\" amb l'excpeció \"%(exception)s\"."
+
+msgctxt "model:ir.model.button,string:subscription_cancel_button"
+msgid "Cancel"
+msgstr "Cancel·la"
+
+msgctxt "model:ir.model.button,string:subscription_draft_button"
+msgid "Draft"
+msgstr "Esborrany"
+
+msgctxt "model:ir.model.button,string:subscription_quote_button"
+msgid "Quote"
+msgstr "Pressupost"
+
+msgctxt "model:ir.model.button,string:subscription_run_button"
+msgid "Run"
+msgstr "Executa"
+
+msgctxt "model:ir.rule.group,name:rule_group_subscription_companies"
+msgid "User in companies"
+msgstr "Usuari a les empreses"
+
+msgctxt "model:ir.sequence,name:sequence_subscription"
+msgid "Subscription"
+msgstr "Subscripció"
+
+msgctxt "model:ir.sequence.type,name:sequence_type_subscription"
+msgid "Subscription"
+msgstr "Subscripció"
+
+msgctxt "model:ir.ui.menu,name:menu_configuration"
+msgid "Subscription"
+msgstr "Subscripció"
+
+msgctxt "model:ir.ui.menu,name:menu_create_invoice"
+msgid "Create Subscription Invoices"
+msgstr "Crea factures de subscripció"
+
+msgctxt "model:ir.ui.menu,name:menu_line_consumption_create"
+msgid "Create Line Consumptions"
+msgstr "Crea consums de les línies"
+
+msgctxt "model:ir.ui.menu,name:menu_recurrence_rule_set_form"
+msgid "Subscription Recurrence Rule Sets"
+msgstr "Conjunts de regles de recurrència"
+
+msgctxt "model:ir.ui.menu,name:menu_service_form"
+msgid "Subscription Services"
+msgstr "Serveis de subscripció"
+
+msgctxt "model:ir.ui.menu,name:menu_subscription_form"
+msgid "Subscriptions"
+msgstr "Subscripcions"
+
+msgctxt "model:sale.subscription,name:"
+msgid "Subscription"
+msgstr "Subscripció"
+
+msgctxt "model:sale.subscription.create_invoice.start,name:"
+msgid "Create Subscription Invoice"
+msgstr "Crea factures de subscripció"
+
+msgctxt "model:sale.subscription.line,name:"
+msgid "Subscription Line"
+msgstr "Línia de subscripció"
+
+msgctxt "model:sale.subscription.line.consumption,name:"
+msgid "Subscription Line Consumption"
+msgstr "Consum de Línia de subscripció"
+
+msgctxt "model:sale.subscription.line.consumption.create.start,name:"
+msgid "Create Subscription Line Consumption"
+msgstr "Crea consums de línies de subscripció"
+
+msgctxt "model:sale.subscription.recurrence.rule,name:"
+msgid "Subscription Recurrence Rule"
+msgstr "Regles de recurrència de les subscripcions"
+
+msgctxt "model:sale.subscription.recurrence.rule.set,name:"
+msgid "Subscription Recurrence Rule Set"
+msgstr "Conjunt de regles de recurrència de les subscripcions"
+
+msgctxt "model:sale.subscription.service,name:"
+msgid "Subscription Service"
+msgstr "Serveis de subcripció"
+
+msgctxt "selection:ir.cron,method:"
+msgid "Generate Subscription Invoices"
+msgstr "Genera les factures de les subscripcions"
+
+msgctxt "selection:ir.cron,method:"
+msgid "Generate Subscription Line Consumptions"
+msgstr "Genera consums de les línies de subscripció"
+
+msgctxt "selection:sale.subscription,state:"
+msgid "Cancelled"
+msgstr "Cancel·lada"
+
+msgctxt "selection:sale.subscription,state:"
+msgid "Closed"
+msgstr "Tancat"
+
+msgctxt "selection:sale.subscription,state:"
+msgid "Draft"
+msgstr "Esborrany"
+
+msgctxt "selection:sale.subscription,state:"
+msgid "Quotation"
+msgstr "Pressupost"
+
+msgctxt "selection:sale.subscription,state:"
+msgid "Running"
+msgstr "En execució"
+
+msgctxt "selection:sale.subscription.recurrence.rule,freq:"
+msgid "Daily"
+msgstr "Diàriament"
+
+msgctxt "selection:sale.subscription.recurrence.rule,freq:"
+msgid "Monthly"
+msgstr "Mensualment"
+
+msgctxt "selection:sale.subscription.recurrence.rule,freq:"
+msgid "Weekly"
+msgstr "Setmanalment"
+
+msgctxt "selection:sale.subscription.recurrence.rule,freq:"
+msgid "Yearly"
+msgstr "Anualment"
+
+msgctxt "view:sale.subscription.create_invoice.start:"
+msgid "Create Subscription Invoices for date"
+msgstr "Crea les factures de subscripció fins la data"
+
+msgctxt "view:sale.subscription.line.consumption.create.start:"
+msgid "Create Subscription Line Consumptions for date"
+msgstr "Crea els consums de subscripció fins la data"
+
+msgctxt "view:sale.subscription.line:"
+msgid "General"
+msgstr "General"
+
+msgctxt "view:sale.subscription:"
+msgid "Other Info"
+msgstr "Informació addicional"
+
+msgctxt "view:sale.subscription:"
+msgid "Subscription"
+msgstr "Subscripció"
+
+msgctxt "wizard_button:sale.subscription.create_invoice,start,create_:"
+msgid "Create"
+msgstr "Crea"
+
+msgctxt "wizard_button:sale.subscription.create_invoice,start,end:"
+msgid "Cancel"
+msgstr "Cancel·la"
+
+msgctxt ""
+"wizard_button:sale.subscription.line.consumption.create,start,create_:"
+msgid "Create"
+msgstr "Crea"
+
+msgctxt "wizard_button:sale.subscription.line.consumption.create,start,end:"
+msgid "Cancel"
+msgstr "Cancel·la"
diff --git a/modules/sale_subscription/locale/cs.po b/modules/sale_subscription/locale/cs.po
new file mode 100644
index 0000000000..4e46c4f6c0
--- /dev/null
+++ b/modules/sale_subscription/locale/cs.po
@@ -0,0 +1,611 @@
+#
+msgid ""
+msgstr "Content-Type: text/plain; charset=utf-8\n"
+
+#, fuzzy
+msgctxt "field:sale.configuration,subscription_sequence:"
+msgid "Subscription Sequence"
+msgstr "Subscription Services"
+
+#, fuzzy
+msgctxt "field:sale.configuration.sequence,subscription_sequence:"
+msgid "Subscription Sequence"
+msgstr "Subscription Services"
+
+msgctxt "field:sale.subscription,company:"
+msgid "Company"
+msgstr ""
+
+msgctxt "field:sale.subscription,contact:"
+msgid "Contact"
+msgstr ""
+
+msgctxt "field:sale.subscription,currency:"
+msgid "Currency"
+msgstr ""
+
+#, fuzzy
+msgctxt "field:sale.subscription,description:"
+msgid "Description"
+msgstr "Subscription"
+
+msgctxt "field:sale.subscription,end_date:"
+msgid "End Date"
+msgstr ""
+
+msgctxt "field:sale.subscription,invoice_address:"
+msgid "Invoice Address"
+msgstr ""
+
+msgctxt "field:sale.subscription,invoice_party:"
+msgid "Invoice Party"
+msgstr ""
+
+msgctxt "field:sale.subscription,invoice_recurrence:"
+msgid "Invoice Recurrence"
+msgstr ""
+
+msgctxt "field:sale.subscription,invoice_start_date:"
+msgid "Invoice Start Date"
+msgstr ""
+
+msgctxt "field:sale.subscription,lines:"
+msgid "Lines"
+msgstr ""
+
+msgctxt "field:sale.subscription,next_invoice_date:"
+msgid "Next Invoice Date"
+msgstr ""
+
+msgctxt "field:sale.subscription,number:"
+msgid "Number"
+msgstr ""
+
+msgctxt "field:sale.subscription,party:"
+msgid "Party"
+msgstr ""
+
+msgctxt "field:sale.subscription,payment_term:"
+msgid "Payment Term"
+msgstr ""
+
+#, fuzzy
+msgctxt "field:sale.subscription,quoted_by:"
+msgid "Quoted By"
+msgstr "Quote"
+
+msgctxt "field:sale.subscription,reference:"
+msgid "Reference"
+msgstr ""
+
+msgctxt "field:sale.subscription,run_by:"
+msgid "Run By"
+msgstr ""
+
+msgctxt "field:sale.subscription,start_date:"
+msgid "Start Date"
+msgstr ""
+
+msgctxt "field:sale.subscription,state:"
+msgid "State"
+msgstr ""
+
+msgctxt "field:sale.subscription.create_invoice.start,date:"
+msgid "Date"
+msgstr ""
+
+msgctxt "field:sale.subscription.line,company:"
+msgid "Company"
+msgstr ""
+
+#, fuzzy
+msgctxt "field:sale.subscription.line,consumed_until:"
+msgid "Consumed until"
+msgstr "Consumptions"
+
+msgctxt "field:sale.subscription.line,consumption_delay:"
+msgid "Consumption Delay"
+msgstr ""
+
+msgctxt "field:sale.subscription.line,consumption_recurrence:"
+msgid "Consumption Recurrence"
+msgstr ""
+
+msgctxt "field:sale.subscription.line,currency:"
+msgid "Currency"
+msgstr ""
+
+#, fuzzy
+msgctxt "field:sale.subscription.line,description:"
+msgid "Description"
+msgstr "Subscription"
+
+msgctxt "field:sale.subscription.line,end_date:"
+msgid "End Date"
+msgstr ""
+
+msgctxt "field:sale.subscription.line,next_consumption_date:"
+msgid "Next Consumption Date"
+msgstr ""
+
+msgctxt "field:sale.subscription.line,next_consumption_date_delayed:"
+msgid "Next Consumption Delayed"
+msgstr ""
+
+msgctxt "field:sale.subscription.line,quantity:"
+msgid "Quantity"
+msgstr ""
+
+msgctxt "field:sale.subscription.line,service:"
+msgid "Service"
+msgstr ""
+
+msgctxt "field:sale.subscription.line,service_unit_category:"
+msgid "Service Unit Category"
+msgstr ""
+
+msgctxt "field:sale.subscription.line,start_date:"
+msgid "Start Date"
+msgstr ""
+
+#, fuzzy
+msgctxt "field:sale.subscription.line,subscription:"
+msgid "Subscription"
+msgstr "Subscription"
+
+#, fuzzy
+msgctxt "field:sale.subscription.line,subscription_end_date:"
+msgid "Subscription End Date"
+msgstr "Subscription Services"
+
+#, fuzzy
+msgctxt "field:sale.subscription.line,subscription_start_date:"
+msgid "Subscription Start Date"
+msgstr "Subscription Services"
+
+#, fuzzy
+msgctxt "field:sale.subscription.line,subscription_state:"
+msgid "Subscription State"
+msgstr "Subscription Services"
+
+msgctxt "field:sale.subscription.line,unit:"
+msgid "Unit"
+msgstr ""
+
+msgctxt "field:sale.subscription.line,unit_digits:"
+msgid "Unit Digits"
+msgstr ""
+
+msgctxt "field:sale.subscription.line,unit_price:"
+msgid "Unit Price"
+msgstr ""
+
+msgctxt "field:sale.subscription.line.consumption,date:"
+msgid "Date"
+msgstr ""
+
+msgctxt "field:sale.subscription.line.consumption,invoice_line:"
+msgid "Invoice Line"
+msgstr ""
+
+msgctxt "field:sale.subscription.line.consumption,line:"
+msgid "Line"
+msgstr ""
+
+msgctxt "field:sale.subscription.line.consumption,quantity:"
+msgid "Quantity"
+msgstr ""
+
+msgctxt "field:sale.subscription.line.consumption,unit_digits:"
+msgid "Unit Digits"
+msgstr ""
+
+msgctxt "field:sale.subscription.line.consumption.create.start,date:"
+msgid "Date"
+msgstr ""
+
+msgctxt "field:sale.subscription.recurrence.rule,bymonth:"
+msgid "By Month"
+msgstr ""
+
+msgctxt "field:sale.subscription.recurrence.rule,bymonthday:"
+msgid "By Month Day"
+msgstr ""
+
+msgctxt "field:sale.subscription.recurrence.rule,bysetpos:"
+msgid "By Position"
+msgstr ""
+
+msgctxt "field:sale.subscription.recurrence.rule,byweekday:"
+msgid "By Week Day"
+msgstr ""
+
+msgctxt "field:sale.subscription.recurrence.rule,byweekno:"
+msgid "By Week Number"
+msgstr ""
+
+msgctxt "field:sale.subscription.recurrence.rule,byyearday:"
+msgid "By Year Day"
+msgstr ""
+
+msgctxt "field:sale.subscription.recurrence.rule,exclusive:"
+msgid "Exclusive"
+msgstr ""
+
+msgctxt "field:sale.subscription.recurrence.rule,freq:"
+msgid "Frequency"
+msgstr ""
+
+msgctxt "field:sale.subscription.recurrence.rule,interval:"
+msgid "Interval"
+msgstr ""
+
+msgctxt "field:sale.subscription.recurrence.rule,set_:"
+msgid "Set"
+msgstr ""
+
+msgctxt "field:sale.subscription.recurrence.rule,week_start_day:"
+msgid "Week Start Day"
+msgstr ""
+
+msgctxt "field:sale.subscription.recurrence.rule.set,name:"
+msgid "Name"
+msgstr ""
+
+msgctxt "field:sale.subscription.recurrence.rule.set,rules:"
+msgid "Rules"
+msgstr ""
+
+msgctxt "field:sale.subscription.service,consumption_delay:"
+msgid "Consumption Delay"
+msgstr ""
+
+msgctxt "field:sale.subscription.service,consumption_recurrence:"
+msgid "Consumption Recurrence"
+msgstr ""
+
+msgctxt "field:sale.subscription.service,product:"
+msgid "Product"
+msgstr ""
+
+msgctxt "help:sale.subscription,company:"
+msgid "Make the subscription belong to the company."
+msgstr ""
+
+msgctxt "help:sale.subscription,number:"
+msgid "The main identification of the subscription."
+msgstr ""
+
+msgctxt "help:sale.subscription,party:"
+msgid "The party who subscribes."
+msgstr ""
+
+msgctxt "help:sale.subscription,reference:"
+msgid "The identification of an external origin."
+msgstr ""
+
+msgctxt "help:sale.subscription,state:"
+msgid "The current state of the subscription."
+msgstr ""
+
+msgctxt "help:sale.subscription.line,subscription:"
+msgid "Add the line below the subscription."
+msgstr ""
+
+msgctxt "help:sale.subscription.recurrence.rule,bymonth:"
+msgid "A comma separated list of integers."
+msgstr ""
+
+msgctxt "help:sale.subscription.recurrence.rule,bymonthday:"
+msgid "A comma separated list of integers."
+msgstr ""
+
+msgctxt "help:sale.subscription.recurrence.rule,bysetpos:"
+msgid "A comma separated list of integers."
+msgstr ""
+
+msgctxt "help:sale.subscription.recurrence.rule,byweekday:"
+msgid "A comma separated list of integers or weekday (MO, TU etc)."
+msgstr ""
+
+msgctxt "help:sale.subscription.recurrence.rule,byweekno:"
+msgid "A comma separated list of integers (ISO8601)."
+msgstr ""
+
+msgctxt "help:sale.subscription.recurrence.rule,byyearday:"
+msgid "A comma separated list of integers."
+msgstr ""
+
+msgctxt "help:sale.subscription.recurrence.rule,set_:"
+msgid "Add the rule below the set."
+msgstr ""
+
+msgctxt "help:sale.subscription.recurrence.rule.set,name:"
+msgid "The main identifier of the rule set."
+msgstr ""
+
+msgctxt "model:ir.action,name:act_create_invoice"
+msgid "Create Subscription Invoices"
+msgstr "Create Subscription Invoices"
+
+msgctxt "model:ir.action,name:act_line_consumption_create"
+msgid "Create Line Consumptions"
+msgstr "Create Line Consumptions"
+
+msgctxt "model:ir.action,name:act_recurrence_rule_set_form"
+msgid "Subscription Recurrence Rule Sets"
+msgstr "Subscription Recurrence Rule Sets"
+
+msgctxt "model:ir.action,name:act_service_form"
+msgid "Subscription Services"
+msgstr "Subscription Services"
+
+msgctxt "model:ir.action,name:act_subscription_form"
+msgid "Subscriptions"
+msgstr "Subscriptions"
+
+msgctxt "model:ir.action,name:act_subscription_invoice_relate"
+msgid "Invoices"
+msgstr ""
+
+msgctxt "model:ir.action,name:act_subscription_line_consumption_form"
+msgid "Consumptions"
+msgstr "Consumptions"
+
+msgctxt ""
+"model:ir.action,name:act_subscription_line_consumption_subscription_line_relate"
+msgid "Consumptions"
+msgstr "Consumptions"
+
+msgctxt ""
+"model:ir.action,name:act_subscription_line_consumption_subscription_relate"
+msgid "Consumptions"
+msgstr "Consumptions"
+
+msgctxt "model:ir.action,name:act_subscription_party_relate"
+msgid "Subscriptions"
+msgstr "Subscriptions"
+
+msgctxt ""
+"model:ir.action.act_window.domain,name:act_subscription_form_domain_all"
+msgid "All"
+msgstr "All"
+
+msgctxt ""
+"model:ir.action.act_window.domain,name:act_subscription_form_domain_draft"
+msgid "Draft"
+msgstr "Draft"
+
+msgctxt ""
+"model:ir.action.act_window.domain,name:act_subscription_form_domain_quotation"
+msgid "Quotation"
+msgstr "Quotation"
+
+msgctxt ""
+"model:ir.action.act_window.domain,name:act_subscription_form_domain_running"
+msgid "Running"
+msgstr "Running"
+
+msgctxt "model:ir.message,text:msg_consumption_delete_invoiced"
+msgid "You cannot delete invoiced consumption \"%(consumption)s\"."
+msgstr ""
+
+msgctxt ""
+"model:ir.message,text:msg_consumption_invoice_missing_account_revenue"
+msgid ""
+"To invoice consumptions you must define an account revenue for product "
+"\"%(product)s\"."
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_consumption_modify_invoiced"
+msgid "You cannot modify invoiced consumption \"%(consumption)s\"."
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_consumption_recurrence_invalid"
+msgid ""
+"The consumption recurrence of line \"%(line)s\" of subscription "
+"\"%(subscription)s\" does not generate any occurrence."
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_erase_party_pending_subscription"
+msgid ""
+"You cannot erase party \"%(party)s\" while they have pending subscriptions "
+"with company \"%(company)s\"."
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_invoice_recurrence_invalid"
+msgid ""
+"The invoice recurrence of subscription \"%(subscription)s\" does not "
+"generate any occurrence."
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_recurrence_rule_invalid_by"
+msgid ""
+"Invalid \"%(field)s\" \"%(value)s\" in recurence rule "
+"\"%(recurrence_rule)s\" with exception \"%(exception)s\"."
+msgstr ""
+
+msgctxt "model:ir.model.button,string:subscription_cancel_button"
+msgid "Cancel"
+msgstr "Cancel"
+
+msgctxt "model:ir.model.button,string:subscription_draft_button"
+msgid "Draft"
+msgstr "Draft"
+
+msgctxt "model:ir.model.button,string:subscription_quote_button"
+msgid "Quote"
+msgstr "Quote"
+
+msgctxt "model:ir.model.button,string:subscription_run_button"
+msgid "Run"
+msgstr "Run"
+
+msgctxt "model:ir.rule.group,name:rule_group_subscription_companies"
+msgid "User in companies"
+msgstr ""
+
+msgctxt "model:ir.sequence,name:sequence_subscription"
+msgid "Subscription"
+msgstr "Subscription"
+
+msgctxt "model:ir.sequence.type,name:sequence_type_subscription"
+msgid "Subscription"
+msgstr "Subscription"
+
+#, fuzzy
+msgctxt "model:ir.ui.menu,name:menu_configuration"
+msgid "Subscription"
+msgstr "Subscription"
+
+msgctxt "model:ir.ui.menu,name:menu_create_invoice"
+msgid "Create Subscription Invoices"
+msgstr "Create Subscription Invoices"
+
+msgctxt "model:ir.ui.menu,name:menu_line_consumption_create"
+msgid "Create Line Consumptions"
+msgstr "Create Line Consumptions"
+
+msgctxt "model:ir.ui.menu,name:menu_recurrence_rule_set_form"
+msgid "Subscription Recurrence Rule Sets"
+msgstr "Subscription Recurrence Rule Sets"
+
+msgctxt "model:ir.ui.menu,name:menu_service_form"
+msgid "Subscription Services"
+msgstr "Subscription Services"
+
+msgctxt "model:ir.ui.menu,name:menu_subscription_form"
+msgid "Subscriptions"
+msgstr "Subscriptions"
+
+#, fuzzy
+msgctxt "model:sale.subscription,name:"
+msgid "Subscription"
+msgstr "Subscription"
+
+#, fuzzy
+msgctxt "model:sale.subscription.create_invoice.start,name:"
+msgid "Create Subscription Invoice"
+msgstr "Create Subscription Invoices"
+
+#, fuzzy
+msgctxt "model:sale.subscription.line,name:"
+msgid "Subscription Line"
+msgstr "Subscription Services"
+
+#, fuzzy
+msgctxt "model:sale.subscription.line.consumption,name:"
+msgid "Subscription Line Consumption"
+msgstr "Generate Subscription Line Consumptions"
+
+#, fuzzy
+msgctxt "model:sale.subscription.line.consumption.create.start,name:"
+msgid "Create Subscription Line Consumption"
+msgstr "Generate Subscription Line Consumptions"
+
+#, fuzzy
+msgctxt "model:sale.subscription.recurrence.rule,name:"
+msgid "Subscription Recurrence Rule"
+msgstr "Subscription Recurrence Rule Sets"
+
+#, fuzzy
+msgctxt "model:sale.subscription.recurrence.rule.set,name:"
+msgid "Subscription Recurrence Rule Set"
+msgstr "Subscription Recurrence Rule Sets"
+
+#, fuzzy
+msgctxt "model:sale.subscription.service,name:"
+msgid "Subscription Service"
+msgstr "Subscription Services"
+
+#, fuzzy
+msgctxt "selection:ir.cron,method:"
+msgid "Generate Subscription Invoices"
+msgstr "Generate Subscription Invoices"
+
+#, fuzzy
+msgctxt "selection:ir.cron,method:"
+msgid "Generate Subscription Line Consumptions"
+msgstr "Generate Subscription Line Consumptions"
+
+#, fuzzy
+msgctxt "selection:sale.subscription,state:"
+msgid "Cancelled"
+msgstr "Cancel"
+
+msgctxt "selection:sale.subscription,state:"
+msgid "Closed"
+msgstr ""
+
+#, fuzzy
+msgctxt "selection:sale.subscription,state:"
+msgid "Draft"
+msgstr "Draft"
+
+#, fuzzy
+msgctxt "selection:sale.subscription,state:"
+msgid "Quotation"
+msgstr "Quotation"
+
+#, fuzzy
+msgctxt "selection:sale.subscription,state:"
+msgid "Running"
+msgstr "Running"
+
+msgctxt "selection:sale.subscription.recurrence.rule,freq:"
+msgid "Daily"
+msgstr ""
+
+msgctxt "selection:sale.subscription.recurrence.rule,freq:"
+msgid "Monthly"
+msgstr ""
+
+msgctxt "selection:sale.subscription.recurrence.rule,freq:"
+msgid "Weekly"
+msgstr ""
+
+msgctxt "selection:sale.subscription.recurrence.rule,freq:"
+msgid "Yearly"
+msgstr ""
+
+#, fuzzy
+msgctxt "view:sale.subscription.create_invoice.start:"
+msgid "Create Subscription Invoices for date"
+msgstr "Create Subscription Invoices"
+
+#, fuzzy
+msgctxt "view:sale.subscription.line.consumption.create.start:"
+msgid "Create Subscription Line Consumptions for date"
+msgstr "Generate Subscription Line Consumptions"
+
+msgctxt "view:sale.subscription.line:"
+msgid "General"
+msgstr ""
+
+msgctxt "view:sale.subscription:"
+msgid "Other Info"
+msgstr ""
+
+#, fuzzy
+msgctxt "view:sale.subscription:"
+msgid "Subscription"
+msgstr "Subscription"
+
+msgctxt "wizard_button:sale.subscription.create_invoice,start,create_:"
+msgid "Create"
+msgstr ""
+
+#, fuzzy
+msgctxt "wizard_button:sale.subscription.create_invoice,start,end:"
+msgid "Cancel"
+msgstr "Cancel"
+
+msgctxt ""
+"wizard_button:sale.subscription.line.consumption.create,start,create_:"
+msgid "Create"
+msgstr ""
+
+#, fuzzy
+msgctxt "wizard_button:sale.subscription.line.consumption.create,start,end:"
+msgid "Cancel"
+msgstr "Cancel"
diff --git a/modules/sale_subscription/locale/de.po b/modules/sale_subscription/locale/de.po
new file mode 100644
index 0000000000..4942f6a334
--- /dev/null
+++ b/modules/sale_subscription/locale/de.po
@@ -0,0 +1,596 @@
+#
+msgid ""
+msgstr "Content-Type: text/plain; charset=utf-8\n"
+
+msgctxt "field:sale.configuration,subscription_sequence:"
+msgid "Subscription Sequence"
+msgstr "Nummernkreis Abonnement"
+
+msgctxt "field:sale.configuration.sequence,subscription_sequence:"
+msgid "Subscription Sequence"
+msgstr "Nummernkreis Abonnement"
+
+msgctxt "field:sale.subscription,company:"
+msgid "Company"
+msgstr "Unternehmen"
+
+msgctxt "field:sale.subscription,contact:"
+msgid "Contact"
+msgstr "Kontakt"
+
+msgctxt "field:sale.subscription,currency:"
+msgid "Currency"
+msgstr "Währung"
+
+msgctxt "field:sale.subscription,description:"
+msgid "Description"
+msgstr "Beschreibung"
+
+msgctxt "field:sale.subscription,end_date:"
+msgid "End Date"
+msgstr "Enddatum"
+
+msgctxt "field:sale.subscription,invoice_address:"
+msgid "Invoice Address"
+msgstr "Rechnungsadresse"
+
+msgctxt "field:sale.subscription,invoice_party:"
+msgid "Invoice Party"
+msgstr "Rechnungsempfänger"
+
+msgctxt "field:sale.subscription,invoice_recurrence:"
+msgid "Invoice Recurrence"
+msgstr "Wiederkehrende Rechnung"
+
+msgctxt "field:sale.subscription,invoice_start_date:"
+msgid "Invoice Start Date"
+msgstr "Startdatum der Verrechnung"
+
+msgctxt "field:sale.subscription,lines:"
+msgid "Lines"
+msgstr "Positionen"
+
+msgctxt "field:sale.subscription,next_invoice_date:"
+msgid "Next Invoice Date"
+msgstr "Nächstes Rechnungsdatum"
+
+msgctxt "field:sale.subscription,number:"
+msgid "Number"
+msgstr "Nummer"
+
+msgctxt "field:sale.subscription,party:"
+msgid "Party"
+msgstr "Partei"
+
+msgctxt "field:sale.subscription,payment_term:"
+msgid "Payment Term"
+msgstr "Zahlungsbedingung"
+
+msgctxt "field:sale.subscription,quoted_by:"
+msgid "Quoted By"
+msgstr "Angeboten von"
+
+msgctxt "field:sale.subscription,reference:"
+msgid "Reference"
+msgstr "Referenz"
+
+msgctxt "field:sale.subscription,run_by:"
+msgid "Run By"
+msgstr "Ausgeführt von"
+
+msgctxt "field:sale.subscription,start_date:"
+msgid "Start Date"
+msgstr "Startdatum"
+
+msgctxt "field:sale.subscription,state:"
+msgid "State"
+msgstr "Status"
+
+msgctxt "field:sale.subscription.create_invoice.start,date:"
+msgid "Date"
+msgstr "Datum"
+
+msgctxt "field:sale.subscription.line,company:"
+msgid "Company"
+msgstr "Unternehmen"
+
+msgctxt "field:sale.subscription.line,consumed_until:"
+msgid "Consumed until"
+msgstr "Verbraucht bis"
+
+msgctxt "field:sale.subscription.line,consumption_delay:"
+msgid "Consumption Delay"
+msgstr "Verbrauchszeitraum"
+
+msgctxt "field:sale.subscription.line,consumption_recurrence:"
+msgid "Consumption Recurrence"
+msgstr "Wiederkehrender Verbrauch"
+
+msgctxt "field:sale.subscription.line,currency:"
+msgid "Currency"
+msgstr "Währung"
+
+msgctxt "field:sale.subscription.line,description:"
+msgid "Description"
+msgstr "Beschreibung"
+
+msgctxt "field:sale.subscription.line,end_date:"
+msgid "End Date"
+msgstr "Enddatum"
+
+msgctxt "field:sale.subscription.line,next_consumption_date:"
+msgid "Next Consumption Date"
+msgstr "Nächstes Verbrauchsdatum"
+
+msgctxt "field:sale.subscription.line,next_consumption_date_delayed:"
+msgid "Next Consumption Delayed"
+msgstr "Nächster Verbrauch verzögert"
+
+msgctxt "field:sale.subscription.line,quantity:"
+msgid "Quantity"
+msgstr "Menge"
+
+msgctxt "field:sale.subscription.line,service:"
+msgid "Service"
+msgstr "Dienstleistung"
+
+msgctxt "field:sale.subscription.line,service_unit_category:"
+msgid "Service Unit Category"
+msgstr "Einheitenkategorie Dienstleistung"
+
+msgctxt "field:sale.subscription.line,start_date:"
+msgid "Start Date"
+msgstr "Startdatum"
+
+msgctxt "field:sale.subscription.line,subscription:"
+msgid "Subscription"
+msgstr "Abonnement"
+
+msgctxt "field:sale.subscription.line,subscription_end_date:"
+msgid "Subscription End Date"
+msgstr "Ablaufdatum des Abonnements"
+
+msgctxt "field:sale.subscription.line,subscription_start_date:"
+msgid "Subscription Start Date"
+msgstr "Startdatum des Abonnements"
+
+msgctxt "field:sale.subscription.line,subscription_state:"
+msgid "Subscription State"
+msgstr "Status des Abonnements"
+
+msgctxt "field:sale.subscription.line,unit:"
+msgid "Unit"
+msgstr "Einheit"
+
+msgctxt "field:sale.subscription.line,unit_digits:"
+msgid "Unit Digits"
+msgstr "Nachkommastellen"
+
+msgctxt "field:sale.subscription.line,unit_price:"
+msgid "Unit Price"
+msgstr "Einzelpreis"
+
+msgctxt "field:sale.subscription.line.consumption,date:"
+msgid "Date"
+msgstr "Datum"
+
+msgctxt "field:sale.subscription.line.consumption,invoice_line:"
+msgid "Invoice Line"
+msgstr "Rechnungsposition"
+
+msgctxt "field:sale.subscription.line.consumption,line:"
+msgid "Line"
+msgstr "Position"
+
+msgctxt "field:sale.subscription.line.consumption,quantity:"
+msgid "Quantity"
+msgstr "Menge"
+
+msgctxt "field:sale.subscription.line.consumption,unit_digits:"
+msgid "Unit Digits"
+msgstr "Nachkommastellen"
+
+msgctxt "field:sale.subscription.line.consumption.create.start,date:"
+msgid "Date"
+msgstr "Datum"
+
+msgctxt "field:sale.subscription.recurrence.rule,bymonth:"
+msgid "By Month"
+msgstr "Pro Monat"
+
+msgctxt "field:sale.subscription.recurrence.rule,bymonthday:"
+msgid "By Month Day"
+msgstr "Pro Tag des Monats"
+
+msgctxt "field:sale.subscription.recurrence.rule,bysetpos:"
+msgid "By Position"
+msgstr "Pro Position"
+
+msgctxt "field:sale.subscription.recurrence.rule,byweekday:"
+msgid "By Week Day"
+msgstr "Pro Wochentag"
+
+msgctxt "field:sale.subscription.recurrence.rule,byweekno:"
+msgid "By Week Number"
+msgstr "Pro Kalenderwoche"
+
+msgctxt "field:sale.subscription.recurrence.rule,byyearday:"
+msgid "By Year Day"
+msgstr "Pro Tag im Jahr"
+
+msgctxt "field:sale.subscription.recurrence.rule,exclusive:"
+msgid "Exclusive"
+msgstr "Exklusiv"
+
+msgctxt "field:sale.subscription.recurrence.rule,freq:"
+msgid "Frequency"
+msgstr "Frequenz"
+
+msgctxt "field:sale.subscription.recurrence.rule,interval:"
+msgid "Interval"
+msgstr "Intervall"
+
+msgctxt "field:sale.subscription.recurrence.rule,set_:"
+msgid "Set"
+msgstr "Satz"
+
+msgctxt "field:sale.subscription.recurrence.rule,week_start_day:"
+msgid "Week Start Day"
+msgstr "Erster Wochentag"
+
+msgctxt "field:sale.subscription.recurrence.rule.set,name:"
+msgid "Name"
+msgstr "Name"
+
+msgctxt "field:sale.subscription.recurrence.rule.set,rules:"
+msgid "Rules"
+msgstr "Regeln"
+
+msgctxt "field:sale.subscription.service,consumption_delay:"
+msgid "Consumption Delay"
+msgstr "Verbrauchszeitraum"
+
+msgctxt "field:sale.subscription.service,consumption_recurrence:"
+msgid "Consumption Recurrence"
+msgstr "Wiederkehrender Verbrauch"
+
+msgctxt "field:sale.subscription.service,product:"
+msgid "Product"
+msgstr "Artikel"
+
+msgctxt "help:sale.subscription,company:"
+msgid "Make the subscription belong to the company."
+msgstr "Das Abonnement dem Unternehmen zuordnen."
+
+msgctxt "help:sale.subscription,number:"
+msgid "The main identification of the subscription."
+msgstr "Die Hauptbezeichnung des Abonnements."
+
+msgctxt "help:sale.subscription,party:"
+msgid "The party who subscribes."
+msgstr "Die Partei die abonniert."
+
+msgctxt "help:sale.subscription,reference:"
+msgid "The identification of an external origin."
+msgstr "Die Identifikation für eine externe Herkunft."
+
+msgctxt "help:sale.subscription,state:"
+msgid "The current state of the subscription."
+msgstr "Der aktuelle Status des Abonnements."
+
+msgctxt "help:sale.subscription.line,subscription:"
+msgid "Add the line below the subscription."
+msgstr "Die Position unter dem Abonnement hinzufügen."
+
+msgctxt "help:sale.subscription.recurrence.rule,bymonth:"
+msgid "A comma separated list of integers."
+msgstr "Durch Komma getrennte Liste von Ganzzahlen."
+
+msgctxt "help:sale.subscription.recurrence.rule,bymonthday:"
+msgid "A comma separated list of integers."
+msgstr "Durch Komma getrennte Liste von Ganzzahlen."
+
+msgctxt "help:sale.subscription.recurrence.rule,bysetpos:"
+msgid "A comma separated list of integers."
+msgstr "Durch Komma getrennte Liste von Ganzzahlen."
+
+msgctxt "help:sale.subscription.recurrence.rule,byweekday:"
+msgid "A comma separated list of integers or weekday (MO, TU etc)."
+msgstr ""
+"Durch Komma getrennte Liste von Ganzzahlen oder Wochentagen (MO, TU etc)."
+
+msgctxt "help:sale.subscription.recurrence.rule,byweekno:"
+msgid "A comma separated list of integers (ISO8601)."
+msgstr "Durch Komma getrennte Liste von Ganzzahlen (ISO8601)."
+
+msgctxt "help:sale.subscription.recurrence.rule,byyearday:"
+msgid "A comma separated list of integers."
+msgstr "Durch Komma getrennte Liste von Ganzzahlen."
+
+msgctxt "help:sale.subscription.recurrence.rule,set_:"
+msgid "Add the rule below the set."
+msgstr "Die Regel am Ende hinzufügen."
+
+msgctxt "help:sale.subscription.recurrence.rule.set,name:"
+msgid "The main identifier of the rule set."
+msgstr "Das Hauptidentifizierungsmerkmal des Regelsatzes."
+
+msgctxt "model:ir.action,name:act_create_invoice"
+msgid "Create Subscription Invoices"
+msgstr "Rechnungen für Abonnements erstellen"
+
+msgctxt "model:ir.action,name:act_line_consumption_create"
+msgid "Create Line Consumptions"
+msgstr "Verbrauchspositionen erstellen"
+
+msgctxt "model:ir.action,name:act_recurrence_rule_set_form"
+msgid "Subscription Recurrence Rule Sets"
+msgstr "Abonnement Wiederholungsregelsätze"
+
+msgctxt "model:ir.action,name:act_service_form"
+msgid "Subscription Services"
+msgstr "Abonnement Dienstleistungen"
+
+msgctxt "model:ir.action,name:act_subscription_form"
+msgid "Subscriptions"
+msgstr "Abonnements"
+
+msgctxt "model:ir.action,name:act_subscription_invoice_relate"
+msgid "Invoices"
+msgstr "Rechnungen"
+
+msgctxt "model:ir.action,name:act_subscription_line_consumption_form"
+msgid "Consumptions"
+msgstr "Verbrauch"
+
+msgctxt ""
+"model:ir.action,name:act_subscription_line_consumption_subscription_line_relate"
+msgid "Consumptions"
+msgstr "Verbrauch"
+
+msgctxt ""
+"model:ir.action,name:act_subscription_line_consumption_subscription_relate"
+msgid "Consumptions"
+msgstr "Verbrauch"
+
+msgctxt "model:ir.action,name:act_subscription_party_relate"
+msgid "Subscriptions"
+msgstr "Abonnements"
+
+msgctxt ""
+"model:ir.action.act_window.domain,name:act_subscription_form_domain_all"
+msgid "All"
+msgstr "Alle"
+
+msgctxt ""
+"model:ir.action.act_window.domain,name:act_subscription_form_domain_draft"
+msgid "Draft"
+msgstr "Entwurf"
+
+msgctxt ""
+"model:ir.action.act_window.domain,name:act_subscription_form_domain_quotation"
+msgid "Quotation"
+msgstr "Angebot"
+
+msgctxt ""
+"model:ir.action.act_window.domain,name:act_subscription_form_domain_running"
+msgid "Running"
+msgstr "In Ausführung"
+
+msgctxt "model:ir.message,text:msg_consumption_delete_invoiced"
+msgid "You cannot delete invoiced consumption \"%(consumption)s\"."
+msgstr ""
+"Der bereits abgerechnete Verbrauch \"%(consumption)s\" kann nicht gelöscht "
+"werden."
+
+msgctxt ""
+"model:ir.message,text:msg_consumption_invoice_missing_account_revenue"
+msgid ""
+"To invoice consumptions you must define an account revenue for product "
+"\"%(product)s\"."
+msgstr ""
+"Damit der Verbrauch abgerechnet werden kann, muss zuerst ein Ertragskonto "
+"für Artikel \"%(product)s\" konfiguriert werden."
+
+msgctxt "model:ir.message,text:msg_consumption_modify_invoiced"
+msgid "You cannot modify invoiced consumption \"%(consumption)s\"."
+msgstr ""
+"Der bereits abgerechnete Verbrauch \"%(consumption)s\" kann nicht mehr "
+"geändert werden."
+
+msgctxt "model:ir.message,text:msg_consumption_recurrence_invalid"
+msgid ""
+"The consumption recurrence of line \"%(line)s\" of subscription "
+"\"%(subscription)s\" does not generate any occurrence."
+msgstr ""
+"Die Verbrauchswiederholung von Position \"%(line)s\" von Abonnement "
+"\"%(subscription)s\" erzeugt keine Vorkommnisse."
+
+msgctxt "model:ir.message,text:msg_erase_party_pending_subscription"
+msgid ""
+"You cannot erase party \"%(party)s\" while they have pending subscriptions "
+"with company \"%(company)s\"."
+msgstr ""
+"Die Partei \"%(party)s\" kann nicht gelöscht werden, solange für sie noch "
+"unerledigte Abonnements bei Unternehmen \"%(company)s\" bestehen."
+
+msgctxt "model:ir.message,text:msg_invoice_recurrence_invalid"
+msgid ""
+"The invoice recurrence of subscription \"%(subscription)s\" does not "
+"generate any occurrence."
+msgstr ""
+"Die Rechnungswiederholung von Abonnement \"%(subscription)s\" erzeugt keine "
+"Vorkommnisse."
+
+msgctxt "model:ir.message,text:msg_recurrence_rule_invalid_by"
+msgid ""
+"Invalid \"%(field)s\" \"%(value)s\" in recurence rule "
+"\"%(recurrence_rule)s\" with exception \"%(exception)s\"."
+msgstr ""
+"\"%(field)s\" \"%(value)s\" in Wiederholungsregel \"%(recurrence_rule)s\" "
+"ist ungültig mit Fehler \"%(exception)s\"."
+
+msgctxt "model:ir.model.button,string:subscription_cancel_button"
+msgid "Cancel"
+msgstr "Annullieren"
+
+msgctxt "model:ir.model.button,string:subscription_draft_button"
+msgid "Draft"
+msgstr "Entwurf"
+
+msgctxt "model:ir.model.button,string:subscription_quote_button"
+msgid "Quote"
+msgstr "Angebot"
+
+msgctxt "model:ir.model.button,string:subscription_run_button"
+msgid "Run"
+msgstr "Ausführen"
+
+msgctxt "model:ir.rule.group,name:rule_group_subscription_companies"
+msgid "User in companies"
+msgstr "Benutzer im Unternehmen"
+
+msgctxt "model:ir.sequence,name:sequence_subscription"
+msgid "Subscription"
+msgstr "Abonnement"
+
+msgctxt "model:ir.sequence.type,name:sequence_type_subscription"
+msgid "Subscription"
+msgstr "Abonnement"
+
+msgctxt "model:ir.ui.menu,name:menu_configuration"
+msgid "Subscription"
+msgstr "Abonnement"
+
+msgctxt "model:ir.ui.menu,name:menu_create_invoice"
+msgid "Create Subscription Invoices"
+msgstr "Rechnungen für Abonnements erstellen"
+
+msgctxt "model:ir.ui.menu,name:menu_line_consumption_create"
+msgid "Create Line Consumptions"
+msgstr "Verbrauchspositionen erstellen"
+
+msgctxt "model:ir.ui.menu,name:menu_recurrence_rule_set_form"
+msgid "Subscription Recurrence Rule Sets"
+msgstr "Abonnement Wiederholungsregelsätze"
+
+msgctxt "model:ir.ui.menu,name:menu_service_form"
+msgid "Subscription Services"
+msgstr "Abonnement Dienstleistungen"
+
+msgctxt "model:ir.ui.menu,name:menu_subscription_form"
+msgid "Subscriptions"
+msgstr "Abonnements"
+
+msgctxt "model:sale.subscription,name:"
+msgid "Subscription"
+msgstr "Abonnement"
+
+msgctxt "model:sale.subscription.create_invoice.start,name:"
+msgid "Create Subscription Invoice"
+msgstr "Rechnung für Abonnement erstellen"
+
+msgctxt "model:sale.subscription.line,name:"
+msgid "Subscription Line"
+msgstr "Abonnement Position"
+
+msgctxt "model:sale.subscription.line.consumption,name:"
+msgid "Subscription Line Consumption"
+msgstr "Abonnement Position Verbrauch"
+
+msgctxt "model:sale.subscription.line.consumption.create.start,name:"
+msgid "Create Subscription Line Consumption"
+msgstr "Verbrauch für die Abonnementsposition erstellen"
+
+msgctxt "model:sale.subscription.recurrence.rule,name:"
+msgid "Subscription Recurrence Rule"
+msgstr "Abonnement Wiederholungsregel"
+
+msgctxt "model:sale.subscription.recurrence.rule.set,name:"
+msgid "Subscription Recurrence Rule Set"
+msgstr "Abonnement Wiederholungsregelsatz"
+
+msgctxt "model:sale.subscription.service,name:"
+msgid "Subscription Service"
+msgstr "Abonnement Dienstleistung"
+
+msgctxt "selection:ir.cron,method:"
+msgid "Generate Subscription Invoices"
+msgstr "Rechnungen für Abonnements erstellen"
+
+msgctxt "selection:ir.cron,method:"
+msgid "Generate Subscription Line Consumptions"
+msgstr "Verbrauchspositionen für Abonnements erstellen"
+
+msgctxt "selection:sale.subscription,state:"
+msgid "Cancelled"
+msgstr "Annulliert"
+
+msgctxt "selection:sale.subscription,state:"
+msgid "Closed"
+msgstr "Geschlossen"
+
+msgctxt "selection:sale.subscription,state:"
+msgid "Draft"
+msgstr "Entwurf"
+
+msgctxt "selection:sale.subscription,state:"
+msgid "Quotation"
+msgstr "Angebot"
+
+msgctxt "selection:sale.subscription,state:"
+msgid "Running"
+msgstr "In Ausführung"
+
+msgctxt "selection:sale.subscription.recurrence.rule,freq:"
+msgid "Daily"
+msgstr "Täglich"
+
+msgctxt "selection:sale.subscription.recurrence.rule,freq:"
+msgid "Monthly"
+msgstr "Monatlich"
+
+msgctxt "selection:sale.subscription.recurrence.rule,freq:"
+msgid "Weekly"
+msgstr "Wöchentlich"
+
+msgctxt "selection:sale.subscription.recurrence.rule,freq:"
+msgid "Yearly"
+msgstr "Jährlich"
+
+msgctxt "view:sale.subscription.create_invoice.start:"
+msgid "Create Subscription Invoices for date"
+msgstr "Rechnungen für Abonnements für ein Datum erstellen"
+
+msgctxt "view:sale.subscription.line.consumption.create.start:"
+msgid "Create Subscription Line Consumptions for date"
+msgstr "Verbrauch für die Abonnementsposition für ein Datum erstellen"
+
+msgctxt "view:sale.subscription.line:"
+msgid "General"
+msgstr "Allgemein"
+
+msgctxt "view:sale.subscription:"
+msgid "Other Info"
+msgstr "Sonstiges"
+
+msgctxt "view:sale.subscription:"
+msgid "Subscription"
+msgstr "Abonnement"
+
+msgctxt "wizard_button:sale.subscription.create_invoice,start,create_:"
+msgid "Create"
+msgstr "Erstellen"
+
+msgctxt "wizard_button:sale.subscription.create_invoice,start,end:"
+msgid "Cancel"
+msgstr "Abbrechen"
+
+msgctxt ""
+"wizard_button:sale.subscription.line.consumption.create,start,create_:"
+msgid "Create"
+msgstr "Erstellen"
+
+msgctxt "wizard_button:sale.subscription.line.consumption.create,start,end:"
+msgid "Cancel"
+msgstr "Abbrechen"
diff --git a/modules/sale_subscription/locale/es.po b/modules/sale_subscription/locale/es.po
new file mode 100644
index 0000000000..9e2d9fa271
--- /dev/null
+++ b/modules/sale_subscription/locale/es.po
@@ -0,0 +1,592 @@
+#
+msgid ""
+msgstr "Content-Type: text/plain; charset=utf-8\n"
+
+msgctxt "field:sale.configuration,subscription_sequence:"
+msgid "Subscription Sequence"
+msgstr "Sequencia de suscripción"
+
+msgctxt "field:sale.configuration.sequence,subscription_sequence:"
+msgid "Subscription Sequence"
+msgstr "Solicitud de suscripción"
+
+msgctxt "field:sale.subscription,company:"
+msgid "Company"
+msgstr "Empresa"
+
+msgctxt "field:sale.subscription,contact:"
+msgid "Contact"
+msgstr "Contacto"
+
+msgctxt "field:sale.subscription,currency:"
+msgid "Currency"
+msgstr "Moneda"
+
+msgctxt "field:sale.subscription,description:"
+msgid "Description"
+msgstr "Descripción"
+
+msgctxt "field:sale.subscription,end_date:"
+msgid "End Date"
+msgstr "Fecha final"
+
+msgctxt "field:sale.subscription,invoice_address:"
+msgid "Invoice Address"
+msgstr "Dirección de facturación"
+
+msgctxt "field:sale.subscription,invoice_party:"
+msgid "Invoice Party"
+msgstr "Tercero de la factura"
+
+msgctxt "field:sale.subscription,invoice_recurrence:"
+msgid "Invoice Recurrence"
+msgstr "Recurrencia de facturación"
+
+msgctxt "field:sale.subscription,invoice_start_date:"
+msgid "Invoice Start Date"
+msgstr "Fecha inicial de facturación"
+
+msgctxt "field:sale.subscription,lines:"
+msgid "Lines"
+msgstr "Líneas"
+
+msgctxt "field:sale.subscription,next_invoice_date:"
+msgid "Next Invoice Date"
+msgstr "Fecha próxima factura"
+
+msgctxt "field:sale.subscription,number:"
+msgid "Number"
+msgstr "Número"
+
+msgctxt "field:sale.subscription,party:"
+msgid "Party"
+msgstr "Tercero"
+
+msgctxt "field:sale.subscription,payment_term:"
+msgid "Payment Term"
+msgstr "Plazo de pago"
+
+msgctxt "field:sale.subscription,quoted_by:"
+msgid "Quoted By"
+msgstr "Presupuestada por"
+
+msgctxt "field:sale.subscription,reference:"
+msgid "Reference"
+msgstr "Referencia"
+
+msgctxt "field:sale.subscription,run_by:"
+msgid "Run By"
+msgstr "Ejecutado por"
+
+msgctxt "field:sale.subscription,start_date:"
+msgid "Start Date"
+msgstr "Fecha inicial"
+
+msgctxt "field:sale.subscription,state:"
+msgid "State"
+msgstr "Estado"
+
+msgctxt "field:sale.subscription.create_invoice.start,date:"
+msgid "Date"
+msgstr "Fecha"
+
+msgctxt "field:sale.subscription.line,company:"
+msgid "Company"
+msgstr "Empresa"
+
+msgctxt "field:sale.subscription.line,consumed_until:"
+msgid "Consumed until"
+msgstr "Consumido hasta"
+
+msgctxt "field:sale.subscription.line,consumption_delay:"
+msgid "Consumption Delay"
+msgstr "Retraso del consumo"
+
+msgctxt "field:sale.subscription.line,consumption_recurrence:"
+msgid "Consumption Recurrence"
+msgstr "Recurrencia del consumo"
+
+msgctxt "field:sale.subscription.line,currency:"
+msgid "Currency"
+msgstr "Moneda"
+
+msgctxt "field:sale.subscription.line,description:"
+msgid "Description"
+msgstr "Descripción"
+
+msgctxt "field:sale.subscription.line,end_date:"
+msgid "End Date"
+msgstr "Fecha final"
+
+msgctxt "field:sale.subscription.line,next_consumption_date:"
+msgid "Next Consumption Date"
+msgstr "Fecha siguiente consumo"
+
+msgctxt "field:sale.subscription.line,next_consumption_date_delayed:"
+msgid "Next Consumption Delayed"
+msgstr "Fecha siguiente consumo con retraso"
+
+msgctxt "field:sale.subscription.line,quantity:"
+msgid "Quantity"
+msgstr "Cantidad"
+
+msgctxt "field:sale.subscription.line,service:"
+msgid "Service"
+msgstr "Servicio"
+
+msgctxt "field:sale.subscription.line,service_unit_category:"
+msgid "Service Unit Category"
+msgstr "Categoría de unidad de servicio"
+
+msgctxt "field:sale.subscription.line,start_date:"
+msgid "Start Date"
+msgstr "Fecha inicial"
+
+msgctxt "field:sale.subscription.line,subscription:"
+msgid "Subscription"
+msgstr "Suscripción"
+
+msgctxt "field:sale.subscription.line,subscription_end_date:"
+msgid "Subscription End Date"
+msgstr "Fecha final suscripción"
+
+msgctxt "field:sale.subscription.line,subscription_start_date:"
+msgid "Subscription Start Date"
+msgstr "Fecha inicial suscripción"
+
+msgctxt "field:sale.subscription.line,subscription_state:"
+msgid "Subscription State"
+msgstr "Estado suscripción"
+
+msgctxt "field:sale.subscription.line,unit:"
+msgid "Unit"
+msgstr "Unidad"
+
+msgctxt "field:sale.subscription.line,unit_digits:"
+msgid "Unit Digits"
+msgstr "Dígitos de la unidad"
+
+msgctxt "field:sale.subscription.line,unit_price:"
+msgid "Unit Price"
+msgstr "Precio unitario"
+
+msgctxt "field:sale.subscription.line.consumption,date:"
+msgid "Date"
+msgstr "Fecha"
+
+msgctxt "field:sale.subscription.line.consumption,invoice_line:"
+msgid "Invoice Line"
+msgstr "Línea de factura"
+
+msgctxt "field:sale.subscription.line.consumption,line:"
+msgid "Line"
+msgstr "Línea"
+
+msgctxt "field:sale.subscription.line.consumption,quantity:"
+msgid "Quantity"
+msgstr "Cantidad"
+
+msgctxt "field:sale.subscription.line.consumption,unit_digits:"
+msgid "Unit Digits"
+msgstr "Dígitos de la unidad"
+
+msgctxt "field:sale.subscription.line.consumption.create.start,date:"
+msgid "Date"
+msgstr "Fecha"
+
+msgctxt "field:sale.subscription.recurrence.rule,bymonth:"
+msgid "By Month"
+msgstr "El mes"
+
+msgctxt "field:sale.subscription.recurrence.rule,bymonthday:"
+msgid "By Month Day"
+msgstr "El día del mes"
+
+msgctxt "field:sale.subscription.recurrence.rule,bysetpos:"
+msgid "By Position"
+msgstr "La posición"
+
+msgctxt "field:sale.subscription.recurrence.rule,byweekday:"
+msgid "By Week Day"
+msgstr "El día de la semana"
+
+msgctxt "field:sale.subscription.recurrence.rule,byweekno:"
+msgid "By Week Number"
+msgstr "El número de semana"
+
+msgctxt "field:sale.subscription.recurrence.rule,byyearday:"
+msgid "By Year Day"
+msgstr "El día del año"
+
+msgctxt "field:sale.subscription.recurrence.rule,exclusive:"
+msgid "Exclusive"
+msgstr "Exclusivo"
+
+msgctxt "field:sale.subscription.recurrence.rule,freq:"
+msgid "Frequency"
+msgstr "Frecuencia"
+
+msgctxt "field:sale.subscription.recurrence.rule,interval:"
+msgid "Interval"
+msgstr "Intervalo"
+
+msgctxt "field:sale.subscription.recurrence.rule,set_:"
+msgid "Set"
+msgstr "Conjunto"
+
+msgctxt "field:sale.subscription.recurrence.rule,week_start_day:"
+msgid "Week Start Day"
+msgstr "Día semana inicio"
+
+msgctxt "field:sale.subscription.recurrence.rule.set,name:"
+msgid "Name"
+msgstr "Nombre"
+
+msgctxt "field:sale.subscription.recurrence.rule.set,rules:"
+msgid "Rules"
+msgstr "Reglas"
+
+msgctxt "field:sale.subscription.service,consumption_delay:"
+msgid "Consumption Delay"
+msgstr "Retraso de consumo"
+
+msgctxt "field:sale.subscription.service,consumption_recurrence:"
+msgid "Consumption Recurrence"
+msgstr "Recurrencia consumo"
+
+msgctxt "field:sale.subscription.service,product:"
+msgid "Product"
+msgstr "Producto"
+
+msgctxt "help:sale.subscription,company:"
+msgid "Make the subscription belong to the company."
+msgstr "Hacer que la suscripción pertenezca a la compañía."
+
+msgctxt "help:sale.subscription,number:"
+msgid "The main identification of the subscription."
+msgstr "El identificador principal de la suscripción."
+
+msgctxt "help:sale.subscription,party:"
+msgid "The party who subscribes."
+msgstr "El tercero que se suscribe."
+
+msgctxt "help:sale.subscription,reference:"
+msgid "The identification of an external origin."
+msgstr "La identificación en un origen externo."
+
+msgctxt "help:sale.subscription,state:"
+msgid "The current state of the subscription."
+msgstr "El estado actual de la suscripción."
+
+msgctxt "help:sale.subscription.line,subscription:"
+msgid "Add the line below the subscription."
+msgstr "Añade lineas a la suscripción."
+
+msgctxt "help:sale.subscription.recurrence.rule,bymonth:"
+msgid "A comma separated list of integers."
+msgstr "Una lista de números separada por comas."
+
+msgctxt "help:sale.subscription.recurrence.rule,bymonthday:"
+msgid "A comma separated list of integers."
+msgstr "Una lista de números separada por comas."
+
+msgctxt "help:sale.subscription.recurrence.rule,bysetpos:"
+msgid "A comma separated list of integers."
+msgstr "Una lista de números separada por comas."
+
+msgctxt "help:sale.subscription.recurrence.rule,byweekday:"
+msgid "A comma separated list of integers or weekday (MO, TU etc)."
+msgstr ""
+"Una lista de números o días de la semana (MO, TU, etc) separada por comas."
+
+msgctxt "help:sale.subscription.recurrence.rule,byweekno:"
+msgid "A comma separated list of integers (ISO8601)."
+msgstr "Una lista de números (ISO8601) separada por comas."
+
+msgctxt "help:sale.subscription.recurrence.rule,byyearday:"
+msgid "A comma separated list of integers."
+msgstr "Una lista de números separada por comas."
+
+msgctxt "help:sale.subscription.recurrence.rule,set_:"
+msgid "Add the rule below the set."
+msgstr "Añade reglas al conjunto."
+
+msgctxt "help:sale.subscription.recurrence.rule.set,name:"
+msgid "The main identifier of the rule set."
+msgstr "El identificador principal del conjunto de reglas."
+
+msgctxt "model:ir.action,name:act_create_invoice"
+msgid "Create Subscription Invoices"
+msgstr "Crear facturas de suscripción"
+
+msgctxt "model:ir.action,name:act_line_consumption_create"
+msgid "Create Line Consumptions"
+msgstr "Crear consumos de las líneas"
+
+msgctxt "model:ir.action,name:act_recurrence_rule_set_form"
+msgid "Subscription Recurrence Rule Sets"
+msgstr "Conjuntos de reglas de recurrencia"
+
+msgctxt "model:ir.action,name:act_service_form"
+msgid "Subscription Services"
+msgstr "Servicios de suscripción"
+
+msgctxt "model:ir.action,name:act_subscription_form"
+msgid "Subscriptions"
+msgstr "Suscripciones"
+
+msgctxt "model:ir.action,name:act_subscription_invoice_relate"
+msgid "Invoices"
+msgstr "Facturas"
+
+msgctxt "model:ir.action,name:act_subscription_line_consumption_form"
+msgid "Consumptions"
+msgstr "Consumos"
+
+msgctxt ""
+"model:ir.action,name:act_subscription_line_consumption_subscription_line_relate"
+msgid "Consumptions"
+msgstr "Consumos"
+
+msgctxt ""
+"model:ir.action,name:act_subscription_line_consumption_subscription_relate"
+msgid "Consumptions"
+msgstr "Consumos"
+
+msgctxt "model:ir.action,name:act_subscription_party_relate"
+msgid "Subscriptions"
+msgstr "Suscripciones"
+
+msgctxt ""
+"model:ir.action.act_window.domain,name:act_subscription_form_domain_all"
+msgid "All"
+msgstr "Todo"
+
+msgctxt ""
+"model:ir.action.act_window.domain,name:act_subscription_form_domain_draft"
+msgid "Draft"
+msgstr "Borrador"
+
+msgctxt ""
+"model:ir.action.act_window.domain,name:act_subscription_form_domain_quotation"
+msgid "Quotation"
+msgstr "Presupuesto"
+
+msgctxt ""
+"model:ir.action.act_window.domain,name:act_subscription_form_domain_running"
+msgid "Running"
+msgstr "En ejecución"
+
+msgctxt "model:ir.message,text:msg_consumption_delete_invoiced"
+msgid "You cannot delete invoiced consumption \"%(consumption)s\"."
+msgstr "No puede eliminar el consumo facturado \"%(consumption)s\"."
+
+msgctxt ""
+"model:ir.message,text:msg_consumption_invoice_missing_account_revenue"
+msgid ""
+"To invoice consumptions you must define an account revenue for product "
+"\"%(product)s\"."
+msgstr ""
+"Para facturar los consumos debe definir una cuenta de ingresos para el "
+"producto \"%(product)s\"."
+
+msgctxt "model:ir.message,text:msg_consumption_modify_invoiced"
+msgid "You cannot modify invoiced consumption \"%(consumption)s\"."
+msgstr "No puede modificar el consumo facturado \"%(consumption)s\"."
+
+msgctxt "model:ir.message,text:msg_consumption_recurrence_invalid"
+msgid ""
+"The consumption recurrence of line \"%(line)s\" of subscription "
+"\"%(subscription)s\" does not generate any occurrence."
+msgstr ""
+"El recurrencia de consumo de la línea \"%(line)s\" de la suscripción "
+"\"%(subscription)s\" no genera ninguna ocurrencia."
+
+msgctxt "model:ir.message,text:msg_erase_party_pending_subscription"
+msgid ""
+"You cannot erase party \"%(party)s\" while they have pending subscriptions "
+"with company \"%(company)s\"."
+msgstr ""
+"No puede eliminar el tercero \"%(party)s\" mientras tenga subscripciones "
+"pendientes con la empresa \"%(company)s\"."
+
+msgctxt "model:ir.message,text:msg_invoice_recurrence_invalid"
+msgid ""
+"The invoice recurrence of subscription \"%(subscription)s\" does not "
+"generate any occurrence."
+msgstr ""
+"El recurrencia de facturación de la suscripción \"%(subscription)s\" no "
+"genera ninguna ocurrencia."
+
+msgctxt "model:ir.message,text:msg_recurrence_rule_invalid_by"
+msgid ""
+"Invalid \"%(field)s\" \"%(value)s\" in recurence rule "
+"\"%(recurrence_rule)s\" with exception \"%(exception)s\"."
+msgstr ""
+"Inválido \"%(field)s\" \"%(value)s\" en la regla de recurrencia "
+"\"%(recurrence_rule)s\" con excepción \"%(exception)s\"."
+
+msgctxt "model:ir.model.button,string:subscription_cancel_button"
+msgid "Cancel"
+msgstr "Cancelar"
+
+msgctxt "model:ir.model.button,string:subscription_draft_button"
+msgid "Draft"
+msgstr "Borrador"
+
+msgctxt "model:ir.model.button,string:subscription_quote_button"
+msgid "Quote"
+msgstr "Presupuesto"
+
+msgctxt "model:ir.model.button,string:subscription_run_button"
+msgid "Run"
+msgstr "Ejecutar"
+
+msgctxt "model:ir.rule.group,name:rule_group_subscription_companies"
+msgid "User in companies"
+msgstr "Usuario en las empresas"
+
+msgctxt "model:ir.sequence,name:sequence_subscription"
+msgid "Subscription"
+msgstr "Suscripción"
+
+msgctxt "model:ir.sequence.type,name:sequence_type_subscription"
+msgid "Subscription"
+msgstr "Suscripción"
+
+msgctxt "model:ir.ui.menu,name:menu_configuration"
+msgid "Subscription"
+msgstr "Suscripción"
+
+msgctxt "model:ir.ui.menu,name:menu_create_invoice"
+msgid "Create Subscription Invoices"
+msgstr "Crear facturas de suscripción"
+
+msgctxt "model:ir.ui.menu,name:menu_line_consumption_create"
+msgid "Create Line Consumptions"
+msgstr "Crear consumos de las líneas"
+
+msgctxt "model:ir.ui.menu,name:menu_recurrence_rule_set_form"
+msgid "Subscription Recurrence Rule Sets"
+msgstr "Conjuntos de reglas de recurrencia"
+
+msgctxt "model:ir.ui.menu,name:menu_service_form"
+msgid "Subscription Services"
+msgstr "Servicios de suscripción"
+
+msgctxt "model:ir.ui.menu,name:menu_subscription_form"
+msgid "Subscriptions"
+msgstr "Suscripciones"
+
+msgctxt "model:sale.subscription,name:"
+msgid "Subscription"
+msgstr "Suscripción"
+
+msgctxt "model:sale.subscription.create_invoice.start,name:"
+msgid "Create Subscription Invoice"
+msgstr "Crear facturas de suscripción"
+
+msgctxt "model:sale.subscription.line,name:"
+msgid "Subscription Line"
+msgstr "Linea de suscripción"
+
+msgctxt "model:sale.subscription.line.consumption,name:"
+msgid "Subscription Line Consumption"
+msgstr "Consumo de linea de suscripción"
+
+msgctxt "model:sale.subscription.line.consumption.create.start,name:"
+msgid "Create Subscription Line Consumption"
+msgstr "Crear consumos de lineas de suscripción"
+
+msgctxt "model:sale.subscription.recurrence.rule,name:"
+msgid "Subscription Recurrence Rule"
+msgstr "Reglas de recurrencia de la suscripción"
+
+msgctxt "model:sale.subscription.recurrence.rule.set,name:"
+msgid "Subscription Recurrence Rule Set"
+msgstr "Conjunto de reglas de recurrencia de la suscripción"
+
+msgctxt "model:sale.subscription.service,name:"
+msgid "Subscription Service"
+msgstr "Servicios de suscripción"
+
+msgctxt "selection:ir.cron,method:"
+msgid "Generate Subscription Invoices"
+msgstr "Generar las facturas de las suscripciones"
+
+msgctxt "selection:ir.cron,method:"
+msgid "Generate Subscription Line Consumptions"
+msgstr "Generar consumos de las lineas de suscripción"
+
+msgctxt "selection:sale.subscription,state:"
+msgid "Cancelled"
+msgstr "Cancelada"
+
+msgctxt "selection:sale.subscription,state:"
+msgid "Closed"
+msgstr "Cerrada"
+
+msgctxt "selection:sale.subscription,state:"
+msgid "Draft"
+msgstr "Borrador"
+
+msgctxt "selection:sale.subscription,state:"
+msgid "Quotation"
+msgstr "Presupuesto"
+
+msgctxt "selection:sale.subscription,state:"
+msgid "Running"
+msgstr "En ejecución"
+
+msgctxt "selection:sale.subscription.recurrence.rule,freq:"
+msgid "Daily"
+msgstr "Diariamente"
+
+msgctxt "selection:sale.subscription.recurrence.rule,freq:"
+msgid "Monthly"
+msgstr "Mensualmente"
+
+msgctxt "selection:sale.subscription.recurrence.rule,freq:"
+msgid "Weekly"
+msgstr "Semanalmente"
+
+msgctxt "selection:sale.subscription.recurrence.rule,freq:"
+msgid "Yearly"
+msgstr "Anualmente"
+
+msgctxt "view:sale.subscription.create_invoice.start:"
+msgid "Create Subscription Invoices for date"
+msgstr "Crear las facturas de suscripción hasta la fecha"
+
+msgctxt "view:sale.subscription.line.consumption.create.start:"
+msgid "Create Subscription Line Consumptions for date"
+msgstr "Crear los consumos de suscripción hasta la fecha"
+
+msgctxt "view:sale.subscription.line:"
+msgid "General"
+msgstr "General"
+
+msgctxt "view:sale.subscription:"
+msgid "Other Info"
+msgstr "Información adicional"
+
+msgctxt "view:sale.subscription:"
+msgid "Subscription"
+msgstr "Suscripción"
+
+msgctxt "wizard_button:sale.subscription.create_invoice,start,create_:"
+msgid "Create"
+msgstr "Crear"
+
+msgctxt "wizard_button:sale.subscription.create_invoice,start,end:"
+msgid "Cancel"
+msgstr "Cancelar"
+
+msgctxt ""
+"wizard_button:sale.subscription.line.consumption.create,start,create_:"
+msgid "Create"
+msgstr "Crear"
+
+msgctxt "wizard_button:sale.subscription.line.consumption.create,start,end:"
+msgid "Cancel"
+msgstr "Cancelar"
diff --git a/modules/sale_subscription/locale/es_419.po b/modules/sale_subscription/locale/es_419.po
new file mode 100644
index 0000000000..d395d67df6
--- /dev/null
+++ b/modules/sale_subscription/locale/es_419.po
@@ -0,0 +1,581 @@
+#
+msgid ""
+msgstr "Content-Type: text/plain; charset=utf-8\n"
+
+msgctxt "field:sale.configuration,subscription_sequence:"
+msgid "Subscription Sequence"
+msgstr ""
+
+msgctxt "field:sale.configuration.sequence,subscription_sequence:"
+msgid "Subscription Sequence"
+msgstr ""
+
+msgctxt "field:sale.subscription,company:"
+msgid "Company"
+msgstr ""
+
+msgctxt "field:sale.subscription,contact:"
+msgid "Contact"
+msgstr ""
+
+msgctxt "field:sale.subscription,currency:"
+msgid "Currency"
+msgstr ""
+
+msgctxt "field:sale.subscription,description:"
+msgid "Description"
+msgstr ""
+
+msgctxt "field:sale.subscription,end_date:"
+msgid "End Date"
+msgstr ""
+
+msgctxt "field:sale.subscription,invoice_address:"
+msgid "Invoice Address"
+msgstr ""
+
+msgctxt "field:sale.subscription,invoice_party:"
+msgid "Invoice Party"
+msgstr ""
+
+msgctxt "field:sale.subscription,invoice_recurrence:"
+msgid "Invoice Recurrence"
+msgstr ""
+
+msgctxt "field:sale.subscription,invoice_start_date:"
+msgid "Invoice Start Date"
+msgstr ""
+
+msgctxt "field:sale.subscription,lines:"
+msgid "Lines"
+msgstr ""
+
+msgctxt "field:sale.subscription,next_invoice_date:"
+msgid "Next Invoice Date"
+msgstr ""
+
+msgctxt "field:sale.subscription,number:"
+msgid "Number"
+msgstr ""
+
+msgctxt "field:sale.subscription,party:"
+msgid "Party"
+msgstr ""
+
+msgctxt "field:sale.subscription,payment_term:"
+msgid "Payment Term"
+msgstr ""
+
+msgctxt "field:sale.subscription,quoted_by:"
+msgid "Quoted By"
+msgstr ""
+
+msgctxt "field:sale.subscription,reference:"
+msgid "Reference"
+msgstr ""
+
+msgctxt "field:sale.subscription,run_by:"
+msgid "Run By"
+msgstr ""
+
+msgctxt "field:sale.subscription,start_date:"
+msgid "Start Date"
+msgstr ""
+
+msgctxt "field:sale.subscription,state:"
+msgid "State"
+msgstr ""
+
+msgctxt "field:sale.subscription.create_invoice.start,date:"
+msgid "Date"
+msgstr ""
+
+msgctxt "field:sale.subscription.line,company:"
+msgid "Company"
+msgstr ""
+
+msgctxt "field:sale.subscription.line,consumed_until:"
+msgid "Consumed until"
+msgstr ""
+
+msgctxt "field:sale.subscription.line,consumption_delay:"
+msgid "Consumption Delay"
+msgstr ""
+
+msgctxt "field:sale.subscription.line,consumption_recurrence:"
+msgid "Consumption Recurrence"
+msgstr ""
+
+msgctxt "field:sale.subscription.line,currency:"
+msgid "Currency"
+msgstr ""
+
+msgctxt "field:sale.subscription.line,description:"
+msgid "Description"
+msgstr ""
+
+msgctxt "field:sale.subscription.line,end_date:"
+msgid "End Date"
+msgstr ""
+
+msgctxt "field:sale.subscription.line,next_consumption_date:"
+msgid "Next Consumption Date"
+msgstr ""
+
+msgctxt "field:sale.subscription.line,next_consumption_date_delayed:"
+msgid "Next Consumption Delayed"
+msgstr ""
+
+msgctxt "field:sale.subscription.line,quantity:"
+msgid "Quantity"
+msgstr ""
+
+msgctxt "field:sale.subscription.line,service:"
+msgid "Service"
+msgstr ""
+
+msgctxt "field:sale.subscription.line,service_unit_category:"
+msgid "Service Unit Category"
+msgstr ""
+
+msgctxt "field:sale.subscription.line,start_date:"
+msgid "Start Date"
+msgstr ""
+
+msgctxt "field:sale.subscription.line,subscription:"
+msgid "Subscription"
+msgstr ""
+
+msgctxt "field:sale.subscription.line,subscription_end_date:"
+msgid "Subscription End Date"
+msgstr ""
+
+msgctxt "field:sale.subscription.line,subscription_start_date:"
+msgid "Subscription Start Date"
+msgstr ""
+
+msgctxt "field:sale.subscription.line,subscription_state:"
+msgid "Subscription State"
+msgstr ""
+
+msgctxt "field:sale.subscription.line,unit:"
+msgid "Unit"
+msgstr ""
+
+msgctxt "field:sale.subscription.line,unit_digits:"
+msgid "Unit Digits"
+msgstr ""
+
+msgctxt "field:sale.subscription.line,unit_price:"
+msgid "Unit Price"
+msgstr ""
+
+msgctxt "field:sale.subscription.line.consumption,date:"
+msgid "Date"
+msgstr ""
+
+msgctxt "field:sale.subscription.line.consumption,invoice_line:"
+msgid "Invoice Line"
+msgstr ""
+
+msgctxt "field:sale.subscription.line.consumption,line:"
+msgid "Line"
+msgstr ""
+
+msgctxt "field:sale.subscription.line.consumption,quantity:"
+msgid "Quantity"
+msgstr ""
+
+msgctxt "field:sale.subscription.line.consumption,unit_digits:"
+msgid "Unit Digits"
+msgstr ""
+
+msgctxt "field:sale.subscription.line.consumption.create.start,date:"
+msgid "Date"
+msgstr ""
+
+msgctxt "field:sale.subscription.recurrence.rule,bymonth:"
+msgid "By Month"
+msgstr ""
+
+msgctxt "field:sale.subscription.recurrence.rule,bymonthday:"
+msgid "By Month Day"
+msgstr ""
+
+msgctxt "field:sale.subscription.recurrence.rule,bysetpos:"
+msgid "By Position"
+msgstr ""
+
+msgctxt "field:sale.subscription.recurrence.rule,byweekday:"
+msgid "By Week Day"
+msgstr ""
+
+msgctxt "field:sale.subscription.recurrence.rule,byweekno:"
+msgid "By Week Number"
+msgstr ""
+
+msgctxt "field:sale.subscription.recurrence.rule,byyearday:"
+msgid "By Year Day"
+msgstr ""
+
+msgctxt "field:sale.subscription.recurrence.rule,exclusive:"
+msgid "Exclusive"
+msgstr ""
+
+msgctxt "field:sale.subscription.recurrence.rule,freq:"
+msgid "Frequency"
+msgstr ""
+
+msgctxt "field:sale.subscription.recurrence.rule,interval:"
+msgid "Interval"
+msgstr ""
+
+msgctxt "field:sale.subscription.recurrence.rule,set_:"
+msgid "Set"
+msgstr ""
+
+msgctxt "field:sale.subscription.recurrence.rule,week_start_day:"
+msgid "Week Start Day"
+msgstr ""
+
+msgctxt "field:sale.subscription.recurrence.rule.set,name:"
+msgid "Name"
+msgstr ""
+
+msgctxt "field:sale.subscription.recurrence.rule.set,rules:"
+msgid "Rules"
+msgstr ""
+
+msgctxt "field:sale.subscription.service,consumption_delay:"
+msgid "Consumption Delay"
+msgstr ""
+
+msgctxt "field:sale.subscription.service,consumption_recurrence:"
+msgid "Consumption Recurrence"
+msgstr ""
+
+msgctxt "field:sale.subscription.service,product:"
+msgid "Product"
+msgstr ""
+
+msgctxt "help:sale.subscription,company:"
+msgid "Make the subscription belong to the company."
+msgstr ""
+
+msgctxt "help:sale.subscription,number:"
+msgid "The main identification of the subscription."
+msgstr ""
+
+msgctxt "help:sale.subscription,party:"
+msgid "The party who subscribes."
+msgstr ""
+
+msgctxt "help:sale.subscription,reference:"
+msgid "The identification of an external origin."
+msgstr ""
+
+msgctxt "help:sale.subscription,state:"
+msgid "The current state of the subscription."
+msgstr ""
+
+msgctxt "help:sale.subscription.line,subscription:"
+msgid "Add the line below the subscription."
+msgstr ""
+
+msgctxt "help:sale.subscription.recurrence.rule,bymonth:"
+msgid "A comma separated list of integers."
+msgstr ""
+
+msgctxt "help:sale.subscription.recurrence.rule,bymonthday:"
+msgid "A comma separated list of integers."
+msgstr ""
+
+msgctxt "help:sale.subscription.recurrence.rule,bysetpos:"
+msgid "A comma separated list of integers."
+msgstr ""
+
+msgctxt "help:sale.subscription.recurrence.rule,byweekday:"
+msgid "A comma separated list of integers or weekday (MO, TU etc)."
+msgstr ""
+
+msgctxt "help:sale.subscription.recurrence.rule,byweekno:"
+msgid "A comma separated list of integers (ISO8601)."
+msgstr ""
+
+msgctxt "help:sale.subscription.recurrence.rule,byyearday:"
+msgid "A comma separated list of integers."
+msgstr ""
+
+msgctxt "help:sale.subscription.recurrence.rule,set_:"
+msgid "Add the rule below the set."
+msgstr ""
+
+msgctxt "help:sale.subscription.recurrence.rule.set,name:"
+msgid "The main identifier of the rule set."
+msgstr ""
+
+msgctxt "model:ir.action,name:act_create_invoice"
+msgid "Create Subscription Invoices"
+msgstr ""
+
+msgctxt "model:ir.action,name:act_line_consumption_create"
+msgid "Create Line Consumptions"
+msgstr ""
+
+msgctxt "model:ir.action,name:act_recurrence_rule_set_form"
+msgid "Subscription Recurrence Rule Sets"
+msgstr ""
+
+msgctxt "model:ir.action,name:act_service_form"
+msgid "Subscription Services"
+msgstr ""
+
+msgctxt "model:ir.action,name:act_subscription_form"
+msgid "Subscriptions"
+msgstr ""
+
+msgctxt "model:ir.action,name:act_subscription_invoice_relate"
+msgid "Invoices"
+msgstr ""
+
+msgctxt "model:ir.action,name:act_subscription_line_consumption_form"
+msgid "Consumptions"
+msgstr ""
+
+msgctxt ""
+"model:ir.action,name:act_subscription_line_consumption_subscription_line_relate"
+msgid "Consumptions"
+msgstr ""
+
+msgctxt ""
+"model:ir.action,name:act_subscription_line_consumption_subscription_relate"
+msgid "Consumptions"
+msgstr ""
+
+msgctxt "model:ir.action,name:act_subscription_party_relate"
+msgid "Subscriptions"
+msgstr ""
+
+msgctxt ""
+"model:ir.action.act_window.domain,name:act_subscription_form_domain_all"
+msgid "All"
+msgstr ""
+
+msgctxt ""
+"model:ir.action.act_window.domain,name:act_subscription_form_domain_draft"
+msgid "Draft"
+msgstr ""
+
+msgctxt ""
+"model:ir.action.act_window.domain,name:act_subscription_form_domain_quotation"
+msgid "Quotation"
+msgstr ""
+
+msgctxt ""
+"model:ir.action.act_window.domain,name:act_subscription_form_domain_running"
+msgid "Running"
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_consumption_delete_invoiced"
+msgid "You cannot delete invoiced consumption \"%(consumption)s\"."
+msgstr ""
+
+msgctxt ""
+"model:ir.message,text:msg_consumption_invoice_missing_account_revenue"
+msgid ""
+"To invoice consumptions you must define an account revenue for product "
+"\"%(product)s\"."
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_consumption_modify_invoiced"
+msgid "You cannot modify invoiced consumption \"%(consumption)s\"."
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_consumption_recurrence_invalid"
+msgid ""
+"The consumption recurrence of line \"%(line)s\" of subscription "
+"\"%(subscription)s\" does not generate any occurrence."
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_erase_party_pending_subscription"
+msgid ""
+"You cannot erase party \"%(party)s\" while they have pending subscriptions "
+"with company \"%(company)s\"."
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_invoice_recurrence_invalid"
+msgid ""
+"The invoice recurrence of subscription \"%(subscription)s\" does not "
+"generate any occurrence."
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_recurrence_rule_invalid_by"
+msgid ""
+"Invalid \"%(field)s\" \"%(value)s\" in recurence rule "
+"\"%(recurrence_rule)s\" with exception \"%(exception)s\"."
+msgstr ""
+
+msgctxt "model:ir.model.button,string:subscription_cancel_button"
+msgid "Cancel"
+msgstr ""
+
+msgctxt "model:ir.model.button,string:subscription_draft_button"
+msgid "Draft"
+msgstr ""
+
+msgctxt "model:ir.model.button,string:subscription_quote_button"
+msgid "Quote"
+msgstr ""
+
+msgctxt "model:ir.model.button,string:subscription_run_button"
+msgid "Run"
+msgstr ""
+
+msgctxt "model:ir.rule.group,name:rule_group_subscription_companies"
+msgid "User in companies"
+msgstr ""
+
+msgctxt "model:ir.sequence,name:sequence_subscription"
+msgid "Subscription"
+msgstr ""
+
+msgctxt "model:ir.sequence.type,name:sequence_type_subscription"
+msgid "Subscription"
+msgstr ""
+
+msgctxt "model:ir.ui.menu,name:menu_configuration"
+msgid "Subscription"
+msgstr ""
+
+msgctxt "model:ir.ui.menu,name:menu_create_invoice"
+msgid "Create Subscription Invoices"
+msgstr ""
+
+msgctxt "model:ir.ui.menu,name:menu_line_consumption_create"
+msgid "Create Line Consumptions"
+msgstr ""
+
+msgctxt "model:ir.ui.menu,name:menu_recurrence_rule_set_form"
+msgid "Subscription Recurrence Rule Sets"
+msgstr ""
+
+msgctxt "model:ir.ui.menu,name:menu_service_form"
+msgid "Subscription Services"
+msgstr ""
+
+msgctxt "model:ir.ui.menu,name:menu_subscription_form"
+msgid "Subscriptions"
+msgstr ""
+
+msgctxt "model:sale.subscription,name:"
+msgid "Subscription"
+msgstr ""
+
+msgctxt "model:sale.subscription.create_invoice.start,name:"
+msgid "Create Subscription Invoice"
+msgstr ""
+
+msgctxt "model:sale.subscription.line,name:"
+msgid "Subscription Line"
+msgstr ""
+
+msgctxt "model:sale.subscription.line.consumption,name:"
+msgid "Subscription Line Consumption"
+msgstr ""
+
+msgctxt "model:sale.subscription.line.consumption.create.start,name:"
+msgid "Create Subscription Line Consumption"
+msgstr ""
+
+msgctxt "model:sale.subscription.recurrence.rule,name:"
+msgid "Subscription Recurrence Rule"
+msgstr ""
+
+msgctxt "model:sale.subscription.recurrence.rule.set,name:"
+msgid "Subscription Recurrence Rule Set"
+msgstr ""
+
+msgctxt "model:sale.subscription.service,name:"
+msgid "Subscription Service"
+msgstr ""
+
+msgctxt "selection:ir.cron,method:"
+msgid "Generate Subscription Invoices"
+msgstr ""
+
+msgctxt "selection:ir.cron,method:"
+msgid "Generate Subscription Line Consumptions"
+msgstr ""
+
+msgctxt "selection:sale.subscription,state:"
+msgid "Cancelled"
+msgstr ""
+
+msgctxt "selection:sale.subscription,state:"
+msgid "Closed"
+msgstr ""
+
+msgctxt "selection:sale.subscription,state:"
+msgid "Draft"
+msgstr ""
+
+msgctxt "selection:sale.subscription,state:"
+msgid "Quotation"
+msgstr ""
+
+msgctxt "selection:sale.subscription,state:"
+msgid "Running"
+msgstr ""
+
+msgctxt "selection:sale.subscription.recurrence.rule,freq:"
+msgid "Daily"
+msgstr ""
+
+msgctxt "selection:sale.subscription.recurrence.rule,freq:"
+msgid "Monthly"
+msgstr ""
+
+msgctxt "selection:sale.subscription.recurrence.rule,freq:"
+msgid "Weekly"
+msgstr ""
+
+msgctxt "selection:sale.subscription.recurrence.rule,freq:"
+msgid "Yearly"
+msgstr ""
+
+msgctxt "view:sale.subscription.create_invoice.start:"
+msgid "Create Subscription Invoices for date"
+msgstr ""
+
+msgctxt "view:sale.subscription.line.consumption.create.start:"
+msgid "Create Subscription Line Consumptions for date"
+msgstr ""
+
+msgctxt "view:sale.subscription.line:"
+msgid "General"
+msgstr ""
+
+msgctxt "view:sale.subscription:"
+msgid "Other Info"
+msgstr ""
+
+msgctxt "view:sale.subscription:"
+msgid "Subscription"
+msgstr ""
+
+msgctxt "wizard_button:sale.subscription.create_invoice,start,create_:"
+msgid "Create"
+msgstr ""
+
+msgctxt "wizard_button:sale.subscription.create_invoice,start,end:"
+msgid "Cancel"
+msgstr ""
+
+msgctxt ""
+"wizard_button:sale.subscription.line.consumption.create,start,create_:"
+msgid "Create"
+msgstr ""
+
+msgctxt "wizard_button:sale.subscription.line.consumption.create,start,end:"
+msgid "Cancel"
+msgstr ""
diff --git a/modules/sale_subscription/locale/et.po b/modules/sale_subscription/locale/et.po
new file mode 100644
index 0000000000..ab2c1e1bd1
--- /dev/null
+++ b/modules/sale_subscription/locale/et.po
@@ -0,0 +1,591 @@
+#
+msgid ""
+msgstr "Content-Type: text/plain; charset=utf-8\n"
+
+msgctxt "field:sale.configuration,subscription_sequence:"
+msgid "Subscription Sequence"
+msgstr "Tellimuse jada"
+
+msgctxt "field:sale.configuration.sequence,subscription_sequence:"
+msgid "Subscription Sequence"
+msgstr "Tellimuse jada"
+
+msgctxt "field:sale.subscription,company:"
+msgid "Company"
+msgstr "Ettevõte"
+
+msgctxt "field:sale.subscription,contact:"
+msgid "Contact"
+msgstr ""
+
+msgctxt "field:sale.subscription,currency:"
+msgid "Currency"
+msgstr "Valuuta"
+
+msgctxt "field:sale.subscription,description:"
+msgid "Description"
+msgstr "Selgitus"
+
+msgctxt "field:sale.subscription,end_date:"
+msgid "End Date"
+msgstr "Lõppkuupäev"
+
+msgctxt "field:sale.subscription,invoice_address:"
+msgid "Invoice Address"
+msgstr "Arve aadress"
+
+#, fuzzy
+msgctxt "field:sale.subscription,invoice_party:"
+msgid "Invoice Party"
+msgstr "Arve alguskuupäev"
+
+msgctxt "field:sale.subscription,invoice_recurrence:"
+msgid "Invoice Recurrence"
+msgstr "Arve kordus"
+
+msgctxt "field:sale.subscription,invoice_start_date:"
+msgid "Invoice Start Date"
+msgstr "Arve alguskuupäev"
+
+msgctxt "field:sale.subscription,lines:"
+msgid "Lines"
+msgstr "Read"
+
+msgctxt "field:sale.subscription,next_invoice_date:"
+msgid "Next Invoice Date"
+msgstr "Järgmise arve kuupäev"
+
+msgctxt "field:sale.subscription,number:"
+msgid "Number"
+msgstr "Number"
+
+msgctxt "field:sale.subscription,party:"
+msgid "Party"
+msgstr "Osapool"
+
+msgctxt "field:sale.subscription,payment_term:"
+msgid "Payment Term"
+msgstr "Maksetingimus"
+
+#, fuzzy
+msgctxt "field:sale.subscription,quoted_by:"
+msgid "Quoted By"
+msgstr "Päring"
+
+msgctxt "field:sale.subscription,reference:"
+msgid "Reference"
+msgstr "Viide"
+
+msgctxt "field:sale.subscription,run_by:"
+msgid "Run By"
+msgstr ""
+
+msgctxt "field:sale.subscription,start_date:"
+msgid "Start Date"
+msgstr "Alguskuupäev"
+
+msgctxt "field:sale.subscription,state:"
+msgid "State"
+msgstr "Staatus"
+
+msgctxt "field:sale.subscription.create_invoice.start,date:"
+msgid "Date"
+msgstr "Kuupäev"
+
+#, fuzzy
+msgctxt "field:sale.subscription.line,company:"
+msgid "Company"
+msgstr "Ettevõte"
+
+#, fuzzy
+msgctxt "field:sale.subscription.line,consumed_until:"
+msgid "Consumed until"
+msgstr "Kasutatud"
+
+msgctxt "field:sale.subscription.line,consumption_delay:"
+msgid "Consumption Delay"
+msgstr "Kasutuse viide"
+
+msgctxt "field:sale.subscription.line,consumption_recurrence:"
+msgid "Consumption Recurrence"
+msgstr "Kasutuse kordus"
+
+#, fuzzy
+msgctxt "field:sale.subscription.line,currency:"
+msgid "Currency"
+msgstr "Valuuta"
+
+msgctxt "field:sale.subscription.line,description:"
+msgid "Description"
+msgstr "Selgitus"
+
+msgctxt "field:sale.subscription.line,end_date:"
+msgid "End Date"
+msgstr "Lõppkuupäev"
+
+msgctxt "field:sale.subscription.line,next_consumption_date:"
+msgid "Next Consumption Date"
+msgstr "Järgmise kasutuse kuupäev"
+
+msgctxt "field:sale.subscription.line,next_consumption_date_delayed:"
+msgid "Next Consumption Delayed"
+msgstr "Järgmise kasutuse viide"
+
+msgctxt "field:sale.subscription.line,quantity:"
+msgid "Quantity"
+msgstr "Kogus"
+
+msgctxt "field:sale.subscription.line,service:"
+msgid "Service"
+msgstr "Teenus"
+
+msgctxt "field:sale.subscription.line,service_unit_category:"
+msgid "Service Unit Category"
+msgstr "Teenuse ühiku kategooria"
+
+msgctxt "field:sale.subscription.line,start_date:"
+msgid "Start Date"
+msgstr "Alguskuupäev"
+
+msgctxt "field:sale.subscription.line,subscription:"
+msgid "Subscription"
+msgstr "Tellimus"
+
+msgctxt "field:sale.subscription.line,subscription_end_date:"
+msgid "Subscription End Date"
+msgstr "Tellimuse lõppkuupäev"
+
+msgctxt "field:sale.subscription.line,subscription_start_date:"
+msgid "Subscription Start Date"
+msgstr "Tellimuse alguskuupäev"
+
+msgctxt "field:sale.subscription.line,subscription_state:"
+msgid "Subscription State"
+msgstr "Tellimuse olek"
+
+msgctxt "field:sale.subscription.line,unit:"
+msgid "Unit"
+msgstr "Ühik"
+
+msgctxt "field:sale.subscription.line,unit_digits:"
+msgid "Unit Digits"
+msgstr "Ühiku numbriväärtus"
+
+msgctxt "field:sale.subscription.line,unit_price:"
+msgid "Unit Price"
+msgstr "Ühiku hind"
+
+msgctxt "field:sale.subscription.line.consumption,date:"
+msgid "Date"
+msgstr "Kuupäev"
+
+msgctxt "field:sale.subscription.line.consumption,invoice_line:"
+msgid "Invoice Line"
+msgstr "Arve rida"
+
+msgctxt "field:sale.subscription.line.consumption,line:"
+msgid "Line"
+msgstr "Rida"
+
+msgctxt "field:sale.subscription.line.consumption,quantity:"
+msgid "Quantity"
+msgstr "Kogus"
+
+msgctxt "field:sale.subscription.line.consumption,unit_digits:"
+msgid "Unit Digits"
+msgstr "Ühiku numbriväärtus"
+
+msgctxt "field:sale.subscription.line.consumption.create.start,date:"
+msgid "Date"
+msgstr "Kuupäev"
+
+msgctxt "field:sale.subscription.recurrence.rule,bymonth:"
+msgid "By Month"
+msgstr "Kuude lõikes"
+
+msgctxt "field:sale.subscription.recurrence.rule,bymonthday:"
+msgid "By Month Day"
+msgstr "Kuu päeva lõikes"
+
+msgctxt "field:sale.subscription.recurrence.rule,bysetpos:"
+msgid "By Position"
+msgstr "Postisooni lõikes"
+
+msgctxt "field:sale.subscription.recurrence.rule,byweekday:"
+msgid "By Week Day"
+msgstr "Nädalapäeva lõikes"
+
+msgctxt "field:sale.subscription.recurrence.rule,byweekno:"
+msgid "By Week Number"
+msgstr "Nädala numbri lõikes"
+
+msgctxt "field:sale.subscription.recurrence.rule,byyearday:"
+msgid "By Year Day"
+msgstr "Aasta päeva lõikes"
+
+msgctxt "field:sale.subscription.recurrence.rule,exclusive:"
+msgid "Exclusive"
+msgstr "Eksklusiivne"
+
+msgctxt "field:sale.subscription.recurrence.rule,freq:"
+msgid "Frequency"
+msgstr "Sagedus"
+
+msgctxt "field:sale.subscription.recurrence.rule,interval:"
+msgid "Interval"
+msgstr "Intervall"
+
+msgctxt "field:sale.subscription.recurrence.rule,set_:"
+msgid "Set"
+msgstr "Komplekt"
+
+msgctxt "field:sale.subscription.recurrence.rule,week_start_day:"
+msgid "Week Start Day"
+msgstr "Nädala alguse päev"
+
+msgctxt "field:sale.subscription.recurrence.rule.set,name:"
+msgid "Name"
+msgstr "Nimi"
+
+msgctxt "field:sale.subscription.recurrence.rule.set,rules:"
+msgid "Rules"
+msgstr "Reegel"
+
+msgctxt "field:sale.subscription.service,consumption_delay:"
+msgid "Consumption Delay"
+msgstr "Tarbimise viide"
+
+msgctxt "field:sale.subscription.service,consumption_recurrence:"
+msgid "Consumption Recurrence"
+msgstr "Tarbimise kordus"
+
+msgctxt "field:sale.subscription.service,product:"
+msgid "Product"
+msgstr "Toode"
+
+msgctxt "help:sale.subscription,company:"
+msgid "Make the subscription belong to the company."
+msgstr ""
+
+msgctxt "help:sale.subscription,number:"
+msgid "The main identification of the subscription."
+msgstr ""
+
+msgctxt "help:sale.subscription,party:"
+msgid "The party who subscribes."
+msgstr "Teenuse tellija osapool"
+
+msgctxt "help:sale.subscription,reference:"
+msgid "The identification of an external origin."
+msgstr ""
+
+msgctxt "help:sale.subscription,state:"
+msgid "The current state of the subscription."
+msgstr ""
+
+msgctxt "help:sale.subscription.line,subscription:"
+msgid "Add the line below the subscription."
+msgstr ""
+
+msgctxt "help:sale.subscription.recurrence.rule,bymonth:"
+msgid "A comma separated list of integers."
+msgstr ""
+
+msgctxt "help:sale.subscription.recurrence.rule,bymonthday:"
+msgid "A comma separated list of integers."
+msgstr ""
+
+msgctxt "help:sale.subscription.recurrence.rule,bysetpos:"
+msgid "A comma separated list of integers."
+msgstr ""
+
+msgctxt "help:sale.subscription.recurrence.rule,byweekday:"
+msgid "A comma separated list of integers or weekday (MO, TU etc)."
+msgstr ""
+
+msgctxt "help:sale.subscription.recurrence.rule,byweekno:"
+msgid "A comma separated list of integers (ISO8601)."
+msgstr ""
+
+msgctxt "help:sale.subscription.recurrence.rule,byyearday:"
+msgid "A comma separated list of integers."
+msgstr ""
+
+msgctxt "help:sale.subscription.recurrence.rule,set_:"
+msgid "Add the rule below the set."
+msgstr ""
+
+msgctxt "help:sale.subscription.recurrence.rule.set,name:"
+msgid "The main identifier of the rule set."
+msgstr ""
+
+msgctxt "model:ir.action,name:act_create_invoice"
+msgid "Create Subscription Invoices"
+msgstr "Loo tellimuse arved"
+
+msgctxt "model:ir.action,name:act_line_consumption_create"
+msgid "Create Line Consumptions"
+msgstr ""
+
+msgctxt "model:ir.action,name:act_recurrence_rule_set_form"
+msgid "Subscription Recurrence Rule Sets"
+msgstr ""
+
+#, fuzzy
+msgctxt "model:ir.action,name:act_service_form"
+msgid "Subscription Services"
+msgstr "Tellimuse teenused"
+
+msgctxt "model:ir.action,name:act_subscription_form"
+msgid "Subscriptions"
+msgstr "Tellimused"
+
+msgctxt "model:ir.action,name:act_subscription_invoice_relate"
+msgid "Invoices"
+msgstr "Arved"
+
+msgctxt "model:ir.action,name:act_subscription_line_consumption_form"
+msgid "Consumptions"
+msgstr "Tarbimised"
+
+msgctxt ""
+"model:ir.action,name:act_subscription_line_consumption_subscription_line_relate"
+msgid "Consumptions"
+msgstr "Tarbimised"
+
+msgctxt ""
+"model:ir.action,name:act_subscription_line_consumption_subscription_relate"
+msgid "Consumptions"
+msgstr "Tarbimised"
+
+msgctxt "model:ir.action,name:act_subscription_party_relate"
+msgid "Subscriptions"
+msgstr "Tellimused"
+
+msgctxt ""
+"model:ir.action.act_window.domain,name:act_subscription_form_domain_all"
+msgid "All"
+msgstr "Kõik"
+
+msgctxt ""
+"model:ir.action.act_window.domain,name:act_subscription_form_domain_draft"
+msgid "Draft"
+msgstr "Mustand"
+
+msgctxt ""
+"model:ir.action.act_window.domain,name:act_subscription_form_domain_quotation"
+msgid "Quotation"
+msgstr "Päring"
+
+msgctxt ""
+"model:ir.action.act_window.domain,name:act_subscription_form_domain_running"
+msgid "Running"
+msgstr "Töös"
+
+msgctxt "model:ir.message,text:msg_consumption_delete_invoiced"
+msgid "You cannot delete invoiced consumption \"%(consumption)s\"."
+msgstr ""
+
+msgctxt ""
+"model:ir.message,text:msg_consumption_invoice_missing_account_revenue"
+msgid ""
+"To invoice consumptions you must define an account revenue for product "
+"\"%(product)s\"."
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_consumption_modify_invoiced"
+msgid "You cannot modify invoiced consumption \"%(consumption)s\"."
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_consumption_recurrence_invalid"
+msgid ""
+"The consumption recurrence of line \"%(line)s\" of subscription "
+"\"%(subscription)s\" does not generate any occurrence."
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_erase_party_pending_subscription"
+msgid ""
+"You cannot erase party \"%(party)s\" while they have pending subscriptions "
+"with company \"%(company)s\"."
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_invoice_recurrence_invalid"
+msgid ""
+"The invoice recurrence of subscription \"%(subscription)s\" does not "
+"generate any occurrence."
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_recurrence_rule_invalid_by"
+msgid ""
+"Invalid \"%(field)s\" \"%(value)s\" in recurence rule "
+"\"%(recurrence_rule)s\" with exception \"%(exception)s\"."
+msgstr ""
+
+msgctxt "model:ir.model.button,string:subscription_cancel_button"
+msgid "Cancel"
+msgstr "Tühista"
+
+msgctxt "model:ir.model.button,string:subscription_draft_button"
+msgid "Draft"
+msgstr "Mustand"
+
+msgctxt "model:ir.model.button,string:subscription_quote_button"
+msgid "Quote"
+msgstr "Päring"
+
+msgctxt "model:ir.model.button,string:subscription_run_button"
+msgid "Run"
+msgstr "Käivit"
+
+msgctxt "model:ir.rule.group,name:rule_group_subscription_companies"
+msgid "User in companies"
+msgstr ""
+
+msgctxt "model:ir.sequence,name:sequence_subscription"
+msgid "Subscription"
+msgstr "Tellimus"
+
+msgctxt "model:ir.sequence.type,name:sequence_type_subscription"
+msgid "Subscription"
+msgstr "Tellimus"
+
+#, fuzzy
+msgctxt "model:ir.ui.menu,name:menu_configuration"
+msgid "Subscription"
+msgstr "Tellimus"
+
+msgctxt "model:ir.ui.menu,name:menu_create_invoice"
+msgid "Create Subscription Invoices"
+msgstr "Loo tellimuse arved"
+
+msgctxt "model:ir.ui.menu,name:menu_line_consumption_create"
+msgid "Create Line Consumptions"
+msgstr ""
+
+msgctxt "model:ir.ui.menu,name:menu_recurrence_rule_set_form"
+msgid "Subscription Recurrence Rule Sets"
+msgstr ""
+
+msgctxt "model:ir.ui.menu,name:menu_service_form"
+msgid "Subscription Services"
+msgstr "Tellimuse teenused"
+
+msgctxt "model:ir.ui.menu,name:menu_subscription_form"
+msgid "Subscriptions"
+msgstr "Tellimused"
+
+msgctxt "model:sale.subscription,name:"
+msgid "Subscription"
+msgstr "Tellimus"
+
+msgctxt "model:sale.subscription.create_invoice.start,name:"
+msgid "Create Subscription Invoice"
+msgstr "Loo tellimuse arve"
+
+msgctxt "model:sale.subscription.line,name:"
+msgid "Subscription Line"
+msgstr "Tellimuse rida"
+
+msgctxt "model:sale.subscription.line.consumption,name:"
+msgid "Subscription Line Consumption"
+msgstr ""
+
+msgctxt "model:sale.subscription.line.consumption.create.start,name:"
+msgid "Create Subscription Line Consumption"
+msgstr ""
+
+msgctxt "model:sale.subscription.recurrence.rule,name:"
+msgid "Subscription Recurrence Rule"
+msgstr ""
+
+msgctxt "model:sale.subscription.recurrence.rule.set,name:"
+msgid "Subscription Recurrence Rule Set"
+msgstr ""
+
+msgctxt "model:sale.subscription.service,name:"
+msgid "Subscription Service"
+msgstr "Tellimuse teenus"
+
+#, fuzzy
+msgctxt "selection:ir.cron,method:"
+msgid "Generate Subscription Invoices"
+msgstr "Loo tellimuse arved"
+
+msgctxt "selection:ir.cron,method:"
+msgid "Generate Subscription Line Consumptions"
+msgstr ""
+
+#, fuzzy
+msgctxt "selection:sale.subscription,state:"
+msgid "Cancelled"
+msgstr "Tühistatud"
+
+msgctxt "selection:sale.subscription,state:"
+msgid "Closed"
+msgstr "Suletud"
+
+msgctxt "selection:sale.subscription,state:"
+msgid "Draft"
+msgstr "Mustand"
+
+msgctxt "selection:sale.subscription,state:"
+msgid "Quotation"
+msgstr "Päring"
+
+msgctxt "selection:sale.subscription,state:"
+msgid "Running"
+msgstr "Töös"
+
+msgctxt "selection:sale.subscription.recurrence.rule,freq:"
+msgid "Daily"
+msgstr "Igapäevane"
+
+msgctxt "selection:sale.subscription.recurrence.rule,freq:"
+msgid "Monthly"
+msgstr "Igakuine"
+
+msgctxt "selection:sale.subscription.recurrence.rule,freq:"
+msgid "Weekly"
+msgstr "Iganädalane"
+
+msgctxt "selection:sale.subscription.recurrence.rule,freq:"
+msgid "Yearly"
+msgstr "Iga-aastane"
+
+#, fuzzy
+msgctxt "view:sale.subscription.create_invoice.start:"
+msgid "Create Subscription Invoices for date"
+msgstr "Loo tellimuse arved"
+
+msgctxt "view:sale.subscription.line.consumption.create.start:"
+msgid "Create Subscription Line Consumptions for date"
+msgstr ""
+
+msgctxt "view:sale.subscription.line:"
+msgid "General"
+msgstr "Üldine"
+
+msgctxt "view:sale.subscription:"
+msgid "Other Info"
+msgstr "Muu info"
+
+msgctxt "view:sale.subscription:"
+msgid "Subscription"
+msgstr "Tellimus"
+
+msgctxt "wizard_button:sale.subscription.create_invoice,start,create_:"
+msgid "Create"
+msgstr "Loo"
+
+msgctxt "wizard_button:sale.subscription.create_invoice,start,end:"
+msgid "Cancel"
+msgstr "Tühista"
+
+msgctxt ""
+"wizard_button:sale.subscription.line.consumption.create,start,create_:"
+msgid "Create"
+msgstr "Loo"
+
+msgctxt "wizard_button:sale.subscription.line.consumption.create,start,end:"
+msgid "Cancel"
+msgstr "Tühista"
diff --git a/modules/sale_subscription/locale/fa.po b/modules/sale_subscription/locale/fa.po
new file mode 100644
index 0000000000..6647096a78
--- /dev/null
+++ b/modules/sale_subscription/locale/fa.po
@@ -0,0 +1,597 @@
+#
+msgid ""
+msgstr "Content-Type: text/plain; charset=utf-8\n"
+
+msgctxt "field:sale.configuration,subscription_sequence:"
+msgid "Subscription Sequence"
+msgstr "دنباله اشتراک"
+
+msgctxt "field:sale.configuration.sequence,subscription_sequence:"
+msgid "Subscription Sequence"
+msgstr "دنباله اشتراک"
+
+msgctxt "field:sale.subscription,company:"
+msgid "Company"
+msgstr "شرکت"
+
+msgctxt "field:sale.subscription,contact:"
+msgid "Contact"
+msgstr ""
+
+msgctxt "field:sale.subscription,currency:"
+msgid "Currency"
+msgstr "واحد پول"
+
+msgctxt "field:sale.subscription,description:"
+msgid "Description"
+msgstr "شرح"
+
+msgctxt "field:sale.subscription,end_date:"
+msgid "End Date"
+msgstr "تاریخ پایان"
+
+msgctxt "field:sale.subscription,invoice_address:"
+msgid "Invoice Address"
+msgstr "آدرس صورتحساب"
+
+#, fuzzy
+msgctxt "field:sale.subscription,invoice_party:"
+msgid "Invoice Party"
+msgstr "تاریخ شروع صورتحساب"
+
+msgctxt "field:sale.subscription,invoice_recurrence:"
+msgid "Invoice Recurrence"
+msgstr "باز تکرار صورتحساب"
+
+msgctxt "field:sale.subscription,invoice_start_date:"
+msgid "Invoice Start Date"
+msgstr "تاریخ شروع صورتحساب"
+
+msgctxt "field:sale.subscription,lines:"
+msgid "Lines"
+msgstr "سطرها"
+
+msgctxt "field:sale.subscription,next_invoice_date:"
+msgid "Next Invoice Date"
+msgstr "تاریخ صورت حساب بعدی"
+
+msgctxt "field:sale.subscription,number:"
+msgid "Number"
+msgstr "شماره"
+
+msgctxt "field:sale.subscription,party:"
+msgid "Party"
+msgstr "نهاد/سازمان"
+
+msgctxt "field:sale.subscription,payment_term:"
+msgid "Payment Term"
+msgstr "مدت پرداخت"
+
+#, fuzzy
+msgctxt "field:sale.subscription,quoted_by:"
+msgid "Quoted By"
+msgstr "Quote"
+
+msgctxt "field:sale.subscription,reference:"
+msgid "Reference"
+msgstr "مرجع"
+
+msgctxt "field:sale.subscription,run_by:"
+msgid "Run By"
+msgstr ""
+
+msgctxt "field:sale.subscription,start_date:"
+msgid "Start Date"
+msgstr "تاریخ شروع"
+
+msgctxt "field:sale.subscription,state:"
+msgid "State"
+msgstr "وضعیت"
+
+msgctxt "field:sale.subscription.create_invoice.start,date:"
+msgid "Date"
+msgstr "تاریخ"
+
+#, fuzzy
+msgctxt "field:sale.subscription.line,company:"
+msgid "Company"
+msgstr "شرکت"
+
+#, fuzzy
+msgctxt "field:sale.subscription.line,consumed_until:"
+msgid "Consumed until"
+msgstr "مصرف شده"
+
+msgctxt "field:sale.subscription.line,consumption_delay:"
+msgid "Consumption Delay"
+msgstr "تاخیر مصرف"
+
+msgctxt "field:sale.subscription.line,consumption_recurrence:"
+msgid "Consumption Recurrence"
+msgstr "باز تکرار مصرف"
+
+#, fuzzy
+msgctxt "field:sale.subscription.line,currency:"
+msgid "Currency"
+msgstr "واحد پول"
+
+msgctxt "field:sale.subscription.line,description:"
+msgid "Description"
+msgstr "شرح"
+
+msgctxt "field:sale.subscription.line,end_date:"
+msgid "End Date"
+msgstr "تاریخ پایان"
+
+msgctxt "field:sale.subscription.line,next_consumption_date:"
+msgid "Next Consumption Date"
+msgstr "تاریخ مصرف بعدی"
+
+msgctxt "field:sale.subscription.line,next_consumption_date_delayed:"
+msgid "Next Consumption Delayed"
+msgstr "مصرف بعدی به تاخیر افتاده"
+
+msgctxt "field:sale.subscription.line,quantity:"
+msgid "Quantity"
+msgstr "مقدار/تعداد"
+
+msgctxt "field:sale.subscription.line,service:"
+msgid "Service"
+msgstr "خدمات"
+
+msgctxt "field:sale.subscription.line,service_unit_category:"
+msgid "Service Unit Category"
+msgstr "دسته بندی واحد خدمات"
+
+msgctxt "field:sale.subscription.line,start_date:"
+msgid "Start Date"
+msgstr "تاریخ شروع"
+
+msgctxt "field:sale.subscription.line,subscription:"
+msgid "Subscription"
+msgstr "اشتراک"
+
+msgctxt "field:sale.subscription.line,subscription_end_date:"
+msgid "Subscription End Date"
+msgstr "تاریخ پایان اشتراک"
+
+msgctxt "field:sale.subscription.line,subscription_start_date:"
+msgid "Subscription Start Date"
+msgstr "تاریخ شروع اشتراک"
+
+msgctxt "field:sale.subscription.line,subscription_state:"
+msgid "Subscription State"
+msgstr "وضعیت اشتراک"
+
+msgctxt "field:sale.subscription.line,unit:"
+msgid "Unit"
+msgstr "واحد"
+
+msgctxt "field:sale.subscription.line,unit_digits:"
+msgid "Unit Digits"
+msgstr "ارقام واحد"
+
+msgctxt "field:sale.subscription.line,unit_price:"
+msgid "Unit Price"
+msgstr "قیمت واحد"
+
+msgctxt "field:sale.subscription.line.consumption,date:"
+msgid "Date"
+msgstr "تاریخ"
+
+msgctxt "field:sale.subscription.line.consumption,invoice_line:"
+msgid "Invoice Line"
+msgstr "سطر صورتحساب"
+
+msgctxt "field:sale.subscription.line.consumption,line:"
+msgid "Line"
+msgstr "سطر"
+
+msgctxt "field:sale.subscription.line.consumption,quantity:"
+msgid "Quantity"
+msgstr "مقدار/تعداد"
+
+msgctxt "field:sale.subscription.line.consumption,unit_digits:"
+msgid "Unit Digits"
+msgstr "ارقام واحد"
+
+msgctxt "field:sale.subscription.line.consumption.create.start,date:"
+msgid "Date"
+msgstr "تاریخ"
+
+msgctxt "field:sale.subscription.recurrence.rule,bymonth:"
+msgid "By Month"
+msgstr "بر اساس ماه"
+
+msgctxt "field:sale.subscription.recurrence.rule,bymonthday:"
+msgid "By Month Day"
+msgstr "بر اساس روزهای ماه"
+
+msgctxt "field:sale.subscription.recurrence.rule,bysetpos:"
+msgid "By Position"
+msgstr "بر اساس موقعیت"
+
+msgctxt "field:sale.subscription.recurrence.rule,byweekday:"
+msgid "By Week Day"
+msgstr "براساس روزهای هفته"
+
+msgctxt "field:sale.subscription.recurrence.rule,byweekno:"
+msgid "By Week Number"
+msgstr "بر اساس شماره هفته"
+
+msgctxt "field:sale.subscription.recurrence.rule,byyearday:"
+msgid "By Year Day"
+msgstr "براساس روزهای سال"
+
+msgctxt "field:sale.subscription.recurrence.rule,exclusive:"
+msgid "Exclusive"
+msgstr "انحصاری"
+
+msgctxt "field:sale.subscription.recurrence.rule,freq:"
+msgid "Frequency"
+msgstr "فرکانس"
+
+msgctxt "field:sale.subscription.recurrence.rule,interval:"
+msgid "Interval"
+msgstr "وقفه"
+
+msgctxt "field:sale.subscription.recurrence.rule,set_:"
+msgid "Set"
+msgstr "مجموعه"
+
+#, fuzzy
+msgctxt "field:sale.subscription.recurrence.rule,week_start_day:"
+msgid "Week Start Day"
+msgstr "روز شروع هفته"
+
+msgctxt "field:sale.subscription.recurrence.rule.set,name:"
+msgid "Name"
+msgstr "نام"
+
+msgctxt "field:sale.subscription.recurrence.rule.set,rules:"
+msgid "Rules"
+msgstr "قوانین"
+
+msgctxt "field:sale.subscription.service,consumption_delay:"
+msgid "Consumption Delay"
+msgstr "تاخیر مصرف"
+
+msgctxt "field:sale.subscription.service,consumption_recurrence:"
+msgid "Consumption Recurrence"
+msgstr "باز تکرار مصرف"
+
+msgctxt "field:sale.subscription.service,product:"
+msgid "Product"
+msgstr "محصول"
+
+msgctxt "help:sale.subscription,company:"
+msgid "Make the subscription belong to the company."
+msgstr "اشتراک متعلق به شرکت را بسازید."
+
+msgctxt "help:sale.subscription,number:"
+msgid "The main identification of the subscription."
+msgstr "کد شناسه اصلی اشتراک."
+
+msgctxt "help:sale.subscription,party:"
+msgid "The party who subscribes."
+msgstr "نهاد/سازمانی که مشترک شده است."
+
+msgctxt "help:sale.subscription,reference:"
+msgid "The identification of an external origin."
+msgstr "شناسایی منشاء خارجی."
+
+msgctxt "help:sale.subscription,state:"
+msgid "The current state of the subscription."
+msgstr "وضعیت جاری اشتراک."
+
+msgctxt "help:sale.subscription.line,subscription:"
+msgid "Add the line below the subscription."
+msgstr "اضافه کردن سطر در زیر اشتراک."
+
+msgctxt "help:sale.subscription.recurrence.rule,bymonth:"
+msgid "A comma separated list of integers."
+msgstr "یک لیست اعداد صحیح جداشده با ویرگول."
+
+msgctxt "help:sale.subscription.recurrence.rule,bymonthday:"
+msgid "A comma separated list of integers."
+msgstr "یک لیست اعداد صحیح جداشده با ویرگول."
+
+msgctxt "help:sale.subscription.recurrence.rule,bysetpos:"
+msgid "A comma separated list of integers."
+msgstr "یک لیست اعداد صحیح جداشده با ویرگول."
+
+msgctxt "help:sale.subscription.recurrence.rule,byweekday:"
+msgid "A comma separated list of integers or weekday (MO, TU etc)."
+msgstr "یک لیست اعداد صحیح جداشده با ویرگول یا روزهای هفته (MO, TU , etc) ."
+
+msgctxt "help:sale.subscription.recurrence.rule,byweekno:"
+msgid "A comma separated list of integers (ISO8601)."
+msgstr "یک لیست اعداد صحیح جداشده با ویرگول (ISO8601)."
+
+msgctxt "help:sale.subscription.recurrence.rule,byyearday:"
+msgid "A comma separated list of integers."
+msgstr "یک لیست اعداد صحیح جداشده با ویرگول."
+
+msgctxt "help:sale.subscription.recurrence.rule,set_:"
+msgid "Add the rule below the set."
+msgstr "اضافه کردن قانون در زیرمجموعه"
+
+msgctxt "help:sale.subscription.recurrence.rule.set,name:"
+msgid "The main identifier of the rule set."
+msgstr "شناسه اصلی مجموعه قانون"
+
+msgctxt "model:ir.action,name:act_create_invoice"
+msgid "Create Subscription Invoices"
+msgstr "ایجاد صورتحساب اشتراک"
+
+msgctxt "model:ir.action,name:act_line_consumption_create"
+msgid "Create Line Consumptions"
+msgstr "ایجاد سطر اشتراک"
+
+msgctxt "model:ir.action,name:act_recurrence_rule_set_form"
+msgid "Subscription Recurrence Rule Sets"
+msgstr "مجموعه های قانون بازتکرار اشتراک"
+
+msgctxt "model:ir.action,name:act_service_form"
+msgid "Subscription Services"
+msgstr "سرویس اشتراک"
+
+msgctxt "model:ir.action,name:act_subscription_form"
+msgid "Subscriptions"
+msgstr "اشتراک ها"
+
+msgctxt "model:ir.action,name:act_subscription_invoice_relate"
+msgid "Invoices"
+msgstr "صورتحساب ها"
+
+msgctxt "model:ir.action,name:act_subscription_line_consumption_form"
+msgid "Consumptions"
+msgstr "مصرفی"
+
+msgctxt ""
+"model:ir.action,name:act_subscription_line_consumption_subscription_line_relate"
+msgid "Consumptions"
+msgstr "مصرفی"
+
+msgctxt ""
+"model:ir.action,name:act_subscription_line_consumption_subscription_relate"
+msgid "Consumptions"
+msgstr "مصرفی ها"
+
+msgctxt "model:ir.action,name:act_subscription_party_relate"
+msgid "Subscriptions"
+msgstr "اشتراک ها"
+
+msgctxt ""
+"model:ir.action.act_window.domain,name:act_subscription_form_domain_all"
+msgid "All"
+msgstr "همه"
+
+msgctxt ""
+"model:ir.action.act_window.domain,name:act_subscription_form_domain_draft"
+msgid "Draft"
+msgstr "پیشنویس"
+
+msgctxt ""
+"model:ir.action.act_window.domain,name:act_subscription_form_domain_quotation"
+msgid "Quotation"
+msgstr "نقل قول"
+
+msgctxt ""
+"model:ir.action.act_window.domain,name:act_subscription_form_domain_running"
+msgid "Running"
+msgstr "در حال اجرا"
+
+msgctxt "model:ir.message,text:msg_consumption_delete_invoiced"
+msgid "You cannot delete invoiced consumption \"%(consumption)s\"."
+msgstr "شما نمی توانید صورتحساب کالای مصرفی :\"%(consumption)s\" را حذف کنید."
+
+msgctxt ""
+"model:ir.message,text:msg_consumption_invoice_missing_account_revenue"
+msgid ""
+"To invoice consumptions you must define an account revenue for product "
+"\"%(product)s\"."
+msgstr ""
+"برای صورتحساب کالای مصرفی شما باید یک حساب درآمد برای محصول :\"%(product)s\""
+" تعریف کنید."
+
+msgctxt "model:ir.message,text:msg_consumption_modify_invoiced"
+msgid "You cannot modify invoiced consumption \"%(consumption)s\"."
+msgstr "شما نمی توانید صورتحساب کالای مصرفی :\"%(consumption)s\"را اصلاح کنید."
+
+msgctxt "model:ir.message,text:msg_consumption_recurrence_invalid"
+msgid ""
+"The consumption recurrence of line \"%(line)s\" of subscription "
+"\"%(subscription)s\" does not generate any occurrence."
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_erase_party_pending_subscription"
+msgid ""
+"You cannot erase party \"%(party)s\" while they have pending subscriptions "
+"with company \"%(company)s\"."
+msgstr ""
+"شما نمیتوانید نهاد/سازمان :\"%(party)s\"را که مشترکین در انتظار با شرکت "
+":\"%(company)s\" دارد را حذف کنید."
+
+msgctxt "model:ir.message,text:msg_invoice_recurrence_invalid"
+msgid ""
+"The invoice recurrence of subscription \"%(subscription)s\" does not "
+"generate any occurrence."
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_recurrence_rule_invalid_by"
+msgid ""
+"Invalid \"%(field)s\" \"%(value)s\" in recurence rule "
+"\"%(recurrence_rule)s\" with exception \"%(exception)s\"."
+msgstr ""
+"\"%(value)s\"در \"%(field)s\" در قانون عودت :\"%(recurrence_rule)s\" با "
+"شرایط :\"%(exception)s\" نامعتبر است."
+
+msgctxt "model:ir.model.button,string:subscription_cancel_button"
+msgid "Cancel"
+msgstr "Cancel"
+
+msgctxt "model:ir.model.button,string:subscription_draft_button"
+msgid "Draft"
+msgstr "Draft"
+
+msgctxt "model:ir.model.button,string:subscription_quote_button"
+msgid "Quote"
+msgstr "Quote"
+
+msgctxt "model:ir.model.button,string:subscription_run_button"
+msgid "Run"
+msgstr "Run"
+
+msgctxt "model:ir.rule.group,name:rule_group_subscription_companies"
+msgid "User in companies"
+msgstr ""
+
+msgctxt "model:ir.sequence,name:sequence_subscription"
+msgid "Subscription"
+msgstr "اشتراک"
+
+msgctxt "model:ir.sequence.type,name:sequence_type_subscription"
+msgid "Subscription"
+msgstr "اشتراک"
+
+#, fuzzy
+msgctxt "model:ir.ui.menu,name:menu_configuration"
+msgid "Subscription"
+msgstr "اشتراک"
+
+msgctxt "model:ir.ui.menu,name:menu_create_invoice"
+msgid "Create Subscription Invoices"
+msgstr "ایجاد صورتحساب های اشتراک"
+
+msgctxt "model:ir.ui.menu,name:menu_line_consumption_create"
+msgid "Create Line Consumptions"
+msgstr "ایجاد سطر مصرفی ها"
+
+msgctxt "model:ir.ui.menu,name:menu_recurrence_rule_set_form"
+msgid "Subscription Recurrence Rule Sets"
+msgstr "مجموعه های قانون بازتکرار اشتراک"
+
+msgctxt "model:ir.ui.menu,name:menu_service_form"
+msgid "Subscription Services"
+msgstr "سرویس اشتراک"
+
+msgctxt "model:ir.ui.menu,name:menu_subscription_form"
+msgid "Subscriptions"
+msgstr "اشتراک ها"
+
+msgctxt "model:sale.subscription,name:"
+msgid "Subscription"
+msgstr "اشتراک"
+
+msgctxt "model:sale.subscription.create_invoice.start,name:"
+msgid "Create Subscription Invoice"
+msgstr "ایجاد صورتحساب اشتراک"
+
+msgctxt "model:sale.subscription.line,name:"
+msgid "Subscription Line"
+msgstr "سطر اشتراک"
+
+msgctxt "model:sale.subscription.line.consumption,name:"
+msgid "Subscription Line Consumption"
+msgstr "سطر مصرفی در اشتراک"
+
+msgctxt "model:sale.subscription.line.consumption.create.start,name:"
+msgid "Create Subscription Line Consumption"
+msgstr "ایجاد سطر مصرفی اشتراک"
+
+msgctxt "model:sale.subscription.recurrence.rule,name:"
+msgid "Subscription Recurrence Rule"
+msgstr "قانون بازتکرار اشتراک"
+
+msgctxt "model:sale.subscription.recurrence.rule.set,name:"
+msgid "Subscription Recurrence Rule Set"
+msgstr "مجموعه قانون بازتکرار اشتراک"
+
+msgctxt "model:sale.subscription.service,name:"
+msgid "Subscription Service"
+msgstr "سرویس اشتراک"
+
+#, fuzzy
+msgctxt "selection:ir.cron,method:"
+msgid "Generate Subscription Invoices"
+msgstr "تولید صورتحساب اشتراک"
+
+#, fuzzy
+msgctxt "selection:ir.cron,method:"
+msgid "Generate Subscription Line Consumptions"
+msgstr "تولید سطر مصرفی ها در اشتراک"
+
+#, fuzzy
+msgctxt "selection:sale.subscription,state:"
+msgid "Cancelled"
+msgstr "لغو شده"
+
+msgctxt "selection:sale.subscription,state:"
+msgid "Closed"
+msgstr "بسته شده"
+
+msgctxt "selection:sale.subscription,state:"
+msgid "Draft"
+msgstr "پیشنویس"
+
+msgctxt "selection:sale.subscription,state:"
+msgid "Quotation"
+msgstr "نقل قول"
+
+msgctxt "selection:sale.subscription,state:"
+msgid "Running"
+msgstr "در حال اجرا"
+
+msgctxt "selection:sale.subscription.recurrence.rule,freq:"
+msgid "Daily"
+msgstr "روزانه"
+
+msgctxt "selection:sale.subscription.recurrence.rule,freq:"
+msgid "Monthly"
+msgstr "ماهانه"
+
+msgctxt "selection:sale.subscription.recurrence.rule,freq:"
+msgid "Weekly"
+msgstr "هفتگی"
+
+msgctxt "selection:sale.subscription.recurrence.rule,freq:"
+msgid "Yearly"
+msgstr "سالانه"
+
+msgctxt "view:sale.subscription.create_invoice.start:"
+msgid "Create Subscription Invoices for date"
+msgstr "ایجاد صورتحساب های اشتراک برای تاریخ"
+
+msgctxt "view:sale.subscription.line.consumption.create.start:"
+msgid "Create Subscription Line Consumptions for date"
+msgstr "ایجاد سطر مصرفی اشتراک برای تاریخ"
+
+msgctxt "view:sale.subscription.line:"
+msgid "General"
+msgstr "عمومی"
+
+msgctxt "view:sale.subscription:"
+msgid "Other Info"
+msgstr "سایر اطلاعات"
+
+msgctxt "view:sale.subscription:"
+msgid "Subscription"
+msgstr "اشتراک"
+
+msgctxt "wizard_button:sale.subscription.create_invoice,start,create_:"
+msgid "Create"
+msgstr "ایجاد"
+
+msgctxt "wizard_button:sale.subscription.create_invoice,start,end:"
+msgid "Cancel"
+msgstr "انصراف"
+
+msgctxt ""
+"wizard_button:sale.subscription.line.consumption.create,start,create_:"
+msgid "Create"
+msgstr "ایجاد"
+
+msgctxt "wizard_button:sale.subscription.line.consumption.create,start,end:"
+msgid "Cancel"
+msgstr "انصراف"
diff --git a/modules/sale_subscription/locale/fi.po b/modules/sale_subscription/locale/fi.po
new file mode 100644
index 0000000000..4e46c4f6c0
--- /dev/null
+++ b/modules/sale_subscription/locale/fi.po
@@ -0,0 +1,611 @@
+#
+msgid ""
+msgstr "Content-Type: text/plain; charset=utf-8\n"
+
+#, fuzzy
+msgctxt "field:sale.configuration,subscription_sequence:"
+msgid "Subscription Sequence"
+msgstr "Subscription Services"
+
+#, fuzzy
+msgctxt "field:sale.configuration.sequence,subscription_sequence:"
+msgid "Subscription Sequence"
+msgstr "Subscription Services"
+
+msgctxt "field:sale.subscription,company:"
+msgid "Company"
+msgstr ""
+
+msgctxt "field:sale.subscription,contact:"
+msgid "Contact"
+msgstr ""
+
+msgctxt "field:sale.subscription,currency:"
+msgid "Currency"
+msgstr ""
+
+#, fuzzy
+msgctxt "field:sale.subscription,description:"
+msgid "Description"
+msgstr "Subscription"
+
+msgctxt "field:sale.subscription,end_date:"
+msgid "End Date"
+msgstr ""
+
+msgctxt "field:sale.subscription,invoice_address:"
+msgid "Invoice Address"
+msgstr ""
+
+msgctxt "field:sale.subscription,invoice_party:"
+msgid "Invoice Party"
+msgstr ""
+
+msgctxt "field:sale.subscription,invoice_recurrence:"
+msgid "Invoice Recurrence"
+msgstr ""
+
+msgctxt "field:sale.subscription,invoice_start_date:"
+msgid "Invoice Start Date"
+msgstr ""
+
+msgctxt "field:sale.subscription,lines:"
+msgid "Lines"
+msgstr ""
+
+msgctxt "field:sale.subscription,next_invoice_date:"
+msgid "Next Invoice Date"
+msgstr ""
+
+msgctxt "field:sale.subscription,number:"
+msgid "Number"
+msgstr ""
+
+msgctxt "field:sale.subscription,party:"
+msgid "Party"
+msgstr ""
+
+msgctxt "field:sale.subscription,payment_term:"
+msgid "Payment Term"
+msgstr ""
+
+#, fuzzy
+msgctxt "field:sale.subscription,quoted_by:"
+msgid "Quoted By"
+msgstr "Quote"
+
+msgctxt "field:sale.subscription,reference:"
+msgid "Reference"
+msgstr ""
+
+msgctxt "field:sale.subscription,run_by:"
+msgid "Run By"
+msgstr ""
+
+msgctxt "field:sale.subscription,start_date:"
+msgid "Start Date"
+msgstr ""
+
+msgctxt "field:sale.subscription,state:"
+msgid "State"
+msgstr ""
+
+msgctxt "field:sale.subscription.create_invoice.start,date:"
+msgid "Date"
+msgstr ""
+
+msgctxt "field:sale.subscription.line,company:"
+msgid "Company"
+msgstr ""
+
+#, fuzzy
+msgctxt "field:sale.subscription.line,consumed_until:"
+msgid "Consumed until"
+msgstr "Consumptions"
+
+msgctxt "field:sale.subscription.line,consumption_delay:"
+msgid "Consumption Delay"
+msgstr ""
+
+msgctxt "field:sale.subscription.line,consumption_recurrence:"
+msgid "Consumption Recurrence"
+msgstr ""
+
+msgctxt "field:sale.subscription.line,currency:"
+msgid "Currency"
+msgstr ""
+
+#, fuzzy
+msgctxt "field:sale.subscription.line,description:"
+msgid "Description"
+msgstr "Subscription"
+
+msgctxt "field:sale.subscription.line,end_date:"
+msgid "End Date"
+msgstr ""
+
+msgctxt "field:sale.subscription.line,next_consumption_date:"
+msgid "Next Consumption Date"
+msgstr ""
+
+msgctxt "field:sale.subscription.line,next_consumption_date_delayed:"
+msgid "Next Consumption Delayed"
+msgstr ""
+
+msgctxt "field:sale.subscription.line,quantity:"
+msgid "Quantity"
+msgstr ""
+
+msgctxt "field:sale.subscription.line,service:"
+msgid "Service"
+msgstr ""
+
+msgctxt "field:sale.subscription.line,service_unit_category:"
+msgid "Service Unit Category"
+msgstr ""
+
+msgctxt "field:sale.subscription.line,start_date:"
+msgid "Start Date"
+msgstr ""
+
+#, fuzzy
+msgctxt "field:sale.subscription.line,subscription:"
+msgid "Subscription"
+msgstr "Subscription"
+
+#, fuzzy
+msgctxt "field:sale.subscription.line,subscription_end_date:"
+msgid "Subscription End Date"
+msgstr "Subscription Services"
+
+#, fuzzy
+msgctxt "field:sale.subscription.line,subscription_start_date:"
+msgid "Subscription Start Date"
+msgstr "Subscription Services"
+
+#, fuzzy
+msgctxt "field:sale.subscription.line,subscription_state:"
+msgid "Subscription State"
+msgstr "Subscription Services"
+
+msgctxt "field:sale.subscription.line,unit:"
+msgid "Unit"
+msgstr ""
+
+msgctxt "field:sale.subscription.line,unit_digits:"
+msgid "Unit Digits"
+msgstr ""
+
+msgctxt "field:sale.subscription.line,unit_price:"
+msgid "Unit Price"
+msgstr ""
+
+msgctxt "field:sale.subscription.line.consumption,date:"
+msgid "Date"
+msgstr ""
+
+msgctxt "field:sale.subscription.line.consumption,invoice_line:"
+msgid "Invoice Line"
+msgstr ""
+
+msgctxt "field:sale.subscription.line.consumption,line:"
+msgid "Line"
+msgstr ""
+
+msgctxt "field:sale.subscription.line.consumption,quantity:"
+msgid "Quantity"
+msgstr ""
+
+msgctxt "field:sale.subscription.line.consumption,unit_digits:"
+msgid "Unit Digits"
+msgstr ""
+
+msgctxt "field:sale.subscription.line.consumption.create.start,date:"
+msgid "Date"
+msgstr ""
+
+msgctxt "field:sale.subscription.recurrence.rule,bymonth:"
+msgid "By Month"
+msgstr ""
+
+msgctxt "field:sale.subscription.recurrence.rule,bymonthday:"
+msgid "By Month Day"
+msgstr ""
+
+msgctxt "field:sale.subscription.recurrence.rule,bysetpos:"
+msgid "By Position"
+msgstr ""
+
+msgctxt "field:sale.subscription.recurrence.rule,byweekday:"
+msgid "By Week Day"
+msgstr ""
+
+msgctxt "field:sale.subscription.recurrence.rule,byweekno:"
+msgid "By Week Number"
+msgstr ""
+
+msgctxt "field:sale.subscription.recurrence.rule,byyearday:"
+msgid "By Year Day"
+msgstr ""
+
+msgctxt "field:sale.subscription.recurrence.rule,exclusive:"
+msgid "Exclusive"
+msgstr ""
+
+msgctxt "field:sale.subscription.recurrence.rule,freq:"
+msgid "Frequency"
+msgstr ""
+
+msgctxt "field:sale.subscription.recurrence.rule,interval:"
+msgid "Interval"
+msgstr ""
+
+msgctxt "field:sale.subscription.recurrence.rule,set_:"
+msgid "Set"
+msgstr ""
+
+msgctxt "field:sale.subscription.recurrence.rule,week_start_day:"
+msgid "Week Start Day"
+msgstr ""
+
+msgctxt "field:sale.subscription.recurrence.rule.set,name:"
+msgid "Name"
+msgstr ""
+
+msgctxt "field:sale.subscription.recurrence.rule.set,rules:"
+msgid "Rules"
+msgstr ""
+
+msgctxt "field:sale.subscription.service,consumption_delay:"
+msgid "Consumption Delay"
+msgstr ""
+
+msgctxt "field:sale.subscription.service,consumption_recurrence:"
+msgid "Consumption Recurrence"
+msgstr ""
+
+msgctxt "field:sale.subscription.service,product:"
+msgid "Product"
+msgstr ""
+
+msgctxt "help:sale.subscription,company:"
+msgid "Make the subscription belong to the company."
+msgstr ""
+
+msgctxt "help:sale.subscription,number:"
+msgid "The main identification of the subscription."
+msgstr ""
+
+msgctxt "help:sale.subscription,party:"
+msgid "The party who subscribes."
+msgstr ""
+
+msgctxt "help:sale.subscription,reference:"
+msgid "The identification of an external origin."
+msgstr ""
+
+msgctxt "help:sale.subscription,state:"
+msgid "The current state of the subscription."
+msgstr ""
+
+msgctxt "help:sale.subscription.line,subscription:"
+msgid "Add the line below the subscription."
+msgstr ""
+
+msgctxt "help:sale.subscription.recurrence.rule,bymonth:"
+msgid "A comma separated list of integers."
+msgstr ""
+
+msgctxt "help:sale.subscription.recurrence.rule,bymonthday:"
+msgid "A comma separated list of integers."
+msgstr ""
+
+msgctxt "help:sale.subscription.recurrence.rule,bysetpos:"
+msgid "A comma separated list of integers."
+msgstr ""
+
+msgctxt "help:sale.subscription.recurrence.rule,byweekday:"
+msgid "A comma separated list of integers or weekday (MO, TU etc)."
+msgstr ""
+
+msgctxt "help:sale.subscription.recurrence.rule,byweekno:"
+msgid "A comma separated list of integers (ISO8601)."
+msgstr ""
+
+msgctxt "help:sale.subscription.recurrence.rule,byyearday:"
+msgid "A comma separated list of integers."
+msgstr ""
+
+msgctxt "help:sale.subscription.recurrence.rule,set_:"
+msgid "Add the rule below the set."
+msgstr ""
+
+msgctxt "help:sale.subscription.recurrence.rule.set,name:"
+msgid "The main identifier of the rule set."
+msgstr ""
+
+msgctxt "model:ir.action,name:act_create_invoice"
+msgid "Create Subscription Invoices"
+msgstr "Create Subscription Invoices"
+
+msgctxt "model:ir.action,name:act_line_consumption_create"
+msgid "Create Line Consumptions"
+msgstr "Create Line Consumptions"
+
+msgctxt "model:ir.action,name:act_recurrence_rule_set_form"
+msgid "Subscription Recurrence Rule Sets"
+msgstr "Subscription Recurrence Rule Sets"
+
+msgctxt "model:ir.action,name:act_service_form"
+msgid "Subscription Services"
+msgstr "Subscription Services"
+
+msgctxt "model:ir.action,name:act_subscription_form"
+msgid "Subscriptions"
+msgstr "Subscriptions"
+
+msgctxt "model:ir.action,name:act_subscription_invoice_relate"
+msgid "Invoices"
+msgstr ""
+
+msgctxt "model:ir.action,name:act_subscription_line_consumption_form"
+msgid "Consumptions"
+msgstr "Consumptions"
+
+msgctxt ""
+"model:ir.action,name:act_subscription_line_consumption_subscription_line_relate"
+msgid "Consumptions"
+msgstr "Consumptions"
+
+msgctxt ""
+"model:ir.action,name:act_subscription_line_consumption_subscription_relate"
+msgid "Consumptions"
+msgstr "Consumptions"
+
+msgctxt "model:ir.action,name:act_subscription_party_relate"
+msgid "Subscriptions"
+msgstr "Subscriptions"
+
+msgctxt ""
+"model:ir.action.act_window.domain,name:act_subscription_form_domain_all"
+msgid "All"
+msgstr "All"
+
+msgctxt ""
+"model:ir.action.act_window.domain,name:act_subscription_form_domain_draft"
+msgid "Draft"
+msgstr "Draft"
+
+msgctxt ""
+"model:ir.action.act_window.domain,name:act_subscription_form_domain_quotation"
+msgid "Quotation"
+msgstr "Quotation"
+
+msgctxt ""
+"model:ir.action.act_window.domain,name:act_subscription_form_domain_running"
+msgid "Running"
+msgstr "Running"
+
+msgctxt "model:ir.message,text:msg_consumption_delete_invoiced"
+msgid "You cannot delete invoiced consumption \"%(consumption)s\"."
+msgstr ""
+
+msgctxt ""
+"model:ir.message,text:msg_consumption_invoice_missing_account_revenue"
+msgid ""
+"To invoice consumptions you must define an account revenue for product "
+"\"%(product)s\"."
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_consumption_modify_invoiced"
+msgid "You cannot modify invoiced consumption \"%(consumption)s\"."
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_consumption_recurrence_invalid"
+msgid ""
+"The consumption recurrence of line \"%(line)s\" of subscription "
+"\"%(subscription)s\" does not generate any occurrence."
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_erase_party_pending_subscription"
+msgid ""
+"You cannot erase party \"%(party)s\" while they have pending subscriptions "
+"with company \"%(company)s\"."
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_invoice_recurrence_invalid"
+msgid ""
+"The invoice recurrence of subscription \"%(subscription)s\" does not "
+"generate any occurrence."
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_recurrence_rule_invalid_by"
+msgid ""
+"Invalid \"%(field)s\" \"%(value)s\" in recurence rule "
+"\"%(recurrence_rule)s\" with exception \"%(exception)s\"."
+msgstr ""
+
+msgctxt "model:ir.model.button,string:subscription_cancel_button"
+msgid "Cancel"
+msgstr "Cancel"
+
+msgctxt "model:ir.model.button,string:subscription_draft_button"
+msgid "Draft"
+msgstr "Draft"
+
+msgctxt "model:ir.model.button,string:subscription_quote_button"
+msgid "Quote"
+msgstr "Quote"
+
+msgctxt "model:ir.model.button,string:subscription_run_button"
+msgid "Run"
+msgstr "Run"
+
+msgctxt "model:ir.rule.group,name:rule_group_subscription_companies"
+msgid "User in companies"
+msgstr ""
+
+msgctxt "model:ir.sequence,name:sequence_subscription"
+msgid "Subscription"
+msgstr "Subscription"
+
+msgctxt "model:ir.sequence.type,name:sequence_type_subscription"
+msgid "Subscription"
+msgstr "Subscription"
+
+#, fuzzy
+msgctxt "model:ir.ui.menu,name:menu_configuration"
+msgid "Subscription"
+msgstr "Subscription"
+
+msgctxt "model:ir.ui.menu,name:menu_create_invoice"
+msgid "Create Subscription Invoices"
+msgstr "Create Subscription Invoices"
+
+msgctxt "model:ir.ui.menu,name:menu_line_consumption_create"
+msgid "Create Line Consumptions"
+msgstr "Create Line Consumptions"
+
+msgctxt "model:ir.ui.menu,name:menu_recurrence_rule_set_form"
+msgid "Subscription Recurrence Rule Sets"
+msgstr "Subscription Recurrence Rule Sets"
+
+msgctxt "model:ir.ui.menu,name:menu_service_form"
+msgid "Subscription Services"
+msgstr "Subscription Services"
+
+msgctxt "model:ir.ui.menu,name:menu_subscription_form"
+msgid "Subscriptions"
+msgstr "Subscriptions"
+
+#, fuzzy
+msgctxt "model:sale.subscription,name:"
+msgid "Subscription"
+msgstr "Subscription"
+
+#, fuzzy
+msgctxt "model:sale.subscription.create_invoice.start,name:"
+msgid "Create Subscription Invoice"
+msgstr "Create Subscription Invoices"
+
+#, fuzzy
+msgctxt "model:sale.subscription.line,name:"
+msgid "Subscription Line"
+msgstr "Subscription Services"
+
+#, fuzzy
+msgctxt "model:sale.subscription.line.consumption,name:"
+msgid "Subscription Line Consumption"
+msgstr "Generate Subscription Line Consumptions"
+
+#, fuzzy
+msgctxt "model:sale.subscription.line.consumption.create.start,name:"
+msgid "Create Subscription Line Consumption"
+msgstr "Generate Subscription Line Consumptions"
+
+#, fuzzy
+msgctxt "model:sale.subscription.recurrence.rule,name:"
+msgid "Subscription Recurrence Rule"
+msgstr "Subscription Recurrence Rule Sets"
+
+#, fuzzy
+msgctxt "model:sale.subscription.recurrence.rule.set,name:"
+msgid "Subscription Recurrence Rule Set"
+msgstr "Subscription Recurrence Rule Sets"
+
+#, fuzzy
+msgctxt "model:sale.subscription.service,name:"
+msgid "Subscription Service"
+msgstr "Subscription Services"
+
+#, fuzzy
+msgctxt "selection:ir.cron,method:"
+msgid "Generate Subscription Invoices"
+msgstr "Generate Subscription Invoices"
+
+#, fuzzy
+msgctxt "selection:ir.cron,method:"
+msgid "Generate Subscription Line Consumptions"
+msgstr "Generate Subscription Line Consumptions"
+
+#, fuzzy
+msgctxt "selection:sale.subscription,state:"
+msgid "Cancelled"
+msgstr "Cancel"
+
+msgctxt "selection:sale.subscription,state:"
+msgid "Closed"
+msgstr ""
+
+#, fuzzy
+msgctxt "selection:sale.subscription,state:"
+msgid "Draft"
+msgstr "Draft"
+
+#, fuzzy
+msgctxt "selection:sale.subscription,state:"
+msgid "Quotation"
+msgstr "Quotation"
+
+#, fuzzy
+msgctxt "selection:sale.subscription,state:"
+msgid "Running"
+msgstr "Running"
+
+msgctxt "selection:sale.subscription.recurrence.rule,freq:"
+msgid "Daily"
+msgstr ""
+
+msgctxt "selection:sale.subscription.recurrence.rule,freq:"
+msgid "Monthly"
+msgstr ""
+
+msgctxt "selection:sale.subscription.recurrence.rule,freq:"
+msgid "Weekly"
+msgstr ""
+
+msgctxt "selection:sale.subscription.recurrence.rule,freq:"
+msgid "Yearly"
+msgstr ""
+
+#, fuzzy
+msgctxt "view:sale.subscription.create_invoice.start:"
+msgid "Create Subscription Invoices for date"
+msgstr "Create Subscription Invoices"
+
+#, fuzzy
+msgctxt "view:sale.subscription.line.consumption.create.start:"
+msgid "Create Subscription Line Consumptions for date"
+msgstr "Generate Subscription Line Consumptions"
+
+msgctxt "view:sale.subscription.line:"
+msgid "General"
+msgstr ""
+
+msgctxt "view:sale.subscription:"
+msgid "Other Info"
+msgstr ""
+
+#, fuzzy
+msgctxt "view:sale.subscription:"
+msgid "Subscription"
+msgstr "Subscription"
+
+msgctxt "wizard_button:sale.subscription.create_invoice,start,create_:"
+msgid "Create"
+msgstr ""
+
+#, fuzzy
+msgctxt "wizard_button:sale.subscription.create_invoice,start,end:"
+msgid "Cancel"
+msgstr "Cancel"
+
+msgctxt ""
+"wizard_button:sale.subscription.line.consumption.create,start,create_:"
+msgid "Create"
+msgstr ""
+
+#, fuzzy
+msgctxt "wizard_button:sale.subscription.line.consumption.create,start,end:"
+msgid "Cancel"
+msgstr "Cancel"
diff --git a/modules/sale_subscription/locale/fr.po b/modules/sale_subscription/locale/fr.po
new file mode 100644
index 0000000000..7f9422cf4d
--- /dev/null
+++ b/modules/sale_subscription/locale/fr.po
@@ -0,0 +1,595 @@
+#
+msgid ""
+msgstr "Content-Type: text/plain; charset=utf-8\n"
+
+msgctxt "field:sale.configuration,subscription_sequence:"
+msgid "Subscription Sequence"
+msgstr "Séquence d'abonnement"
+
+msgctxt "field:sale.configuration.sequence,subscription_sequence:"
+msgid "Subscription Sequence"
+msgstr "Séquence d'abonnement"
+
+msgctxt "field:sale.subscription,company:"
+msgid "Company"
+msgstr "Société"
+
+msgctxt "field:sale.subscription,contact:"
+msgid "Contact"
+msgstr "Contact"
+
+msgctxt "field:sale.subscription,currency:"
+msgid "Currency"
+msgstr "Devise"
+
+msgctxt "field:sale.subscription,description:"
+msgid "Description"
+msgstr "Description"
+
+msgctxt "field:sale.subscription,end_date:"
+msgid "End Date"
+msgstr "Date de fin"
+
+msgctxt "field:sale.subscription,invoice_address:"
+msgid "Invoice Address"
+msgstr "Adresse de facturation"
+
+msgctxt "field:sale.subscription,invoice_party:"
+msgid "Invoice Party"
+msgstr "Tiers de facturation"
+
+msgctxt "field:sale.subscription,invoice_recurrence:"
+msgid "Invoice Recurrence"
+msgstr "Récurrence de facturation"
+
+msgctxt "field:sale.subscription,invoice_start_date:"
+msgid "Invoice Start Date"
+msgstr "Date de début de facturation"
+
+msgctxt "field:sale.subscription,lines:"
+msgid "Lines"
+msgstr "Lignes"
+
+msgctxt "field:sale.subscription,next_invoice_date:"
+msgid "Next Invoice Date"
+msgstr "Prochaine date de facturation"
+
+msgctxt "field:sale.subscription,number:"
+msgid "Number"
+msgstr "Numéro"
+
+msgctxt "field:sale.subscription,party:"
+msgid "Party"
+msgstr "Tiers"
+
+msgctxt "field:sale.subscription,payment_term:"
+msgid "Payment Term"
+msgstr "Conditions de paiement"
+
+msgctxt "field:sale.subscription,quoted_by:"
+msgid "Quoted By"
+msgstr "Devis fait par"
+
+msgctxt "field:sale.subscription,reference:"
+msgid "Reference"
+msgstr "Référence"
+
+msgctxt "field:sale.subscription,run_by:"
+msgid "Run By"
+msgstr "Exécuté par"
+
+msgctxt "field:sale.subscription,start_date:"
+msgid "Start Date"
+msgstr "Date de début"
+
+msgctxt "field:sale.subscription,state:"
+msgid "State"
+msgstr "État"
+
+msgctxt "field:sale.subscription.create_invoice.start,date:"
+msgid "Date"
+msgstr "Date"
+
+msgctxt "field:sale.subscription.line,company:"
+msgid "Company"
+msgstr "Société"
+
+msgctxt "field:sale.subscription.line,consumed_until:"
+msgid "Consumed until"
+msgstr "Consommée jusqu'à"
+
+msgctxt "field:sale.subscription.line,consumption_delay:"
+msgid "Consumption Delay"
+msgstr "Délai de consommation"
+
+msgctxt "field:sale.subscription.line,consumption_recurrence:"
+msgid "Consumption Recurrence"
+msgstr "Récurrence de consommation"
+
+msgctxt "field:sale.subscription.line,currency:"
+msgid "Currency"
+msgstr "Devise"
+
+msgctxt "field:sale.subscription.line,description:"
+msgid "Description"
+msgstr "Description"
+
+msgctxt "field:sale.subscription.line,end_date:"
+msgid "End Date"
+msgstr "Date de fin"
+
+msgctxt "field:sale.subscription.line,next_consumption_date:"
+msgid "Next Consumption Date"
+msgstr "Prochaine date de consommation"
+
+msgctxt "field:sale.subscription.line,next_consumption_date_delayed:"
+msgid "Next Consumption Delayed"
+msgstr "Prochaine consommation retardée"
+
+msgctxt "field:sale.subscription.line,quantity:"
+msgid "Quantity"
+msgstr "Quantité"
+
+msgctxt "field:sale.subscription.line,service:"
+msgid "Service"
+msgstr "Service"
+
+msgctxt "field:sale.subscription.line,service_unit_category:"
+msgid "Service Unit Category"
+msgstr "Catégorie d'unité du service"
+
+msgctxt "field:sale.subscription.line,start_date:"
+msgid "Start Date"
+msgstr "Date de début"
+
+msgctxt "field:sale.subscription.line,subscription:"
+msgid "Subscription"
+msgstr "Abonnement"
+
+msgctxt "field:sale.subscription.line,subscription_end_date:"
+msgid "Subscription End Date"
+msgstr "Date de fin de l'abonnement"
+
+msgctxt "field:sale.subscription.line,subscription_start_date:"
+msgid "Subscription Start Date"
+msgstr "Date de début de l'abonnement"
+
+msgctxt "field:sale.subscription.line,subscription_state:"
+msgid "Subscription State"
+msgstr "État de l'abonnement"
+
+msgctxt "field:sale.subscription.line,unit:"
+msgid "Unit"
+msgstr "Unité"
+
+msgctxt "field:sale.subscription.line,unit_digits:"
+msgid "Unit Digits"
+msgstr "Décimales de l'unité"
+
+msgctxt "field:sale.subscription.line,unit_price:"
+msgid "Unit Price"
+msgstr "Prix unitaire"
+
+msgctxt "field:sale.subscription.line.consumption,date:"
+msgid "Date"
+msgstr "Date"
+
+msgctxt "field:sale.subscription.line.consumption,invoice_line:"
+msgid "Invoice Line"
+msgstr "Ligne de facture"
+
+msgctxt "field:sale.subscription.line.consumption,line:"
+msgid "Line"
+msgstr "Ligne"
+
+msgctxt "field:sale.subscription.line.consumption,quantity:"
+msgid "Quantity"
+msgstr "Quantité"
+
+msgctxt "field:sale.subscription.line.consumption,unit_digits:"
+msgid "Unit Digits"
+msgstr "Décimales de l'unité"
+
+msgctxt "field:sale.subscription.line.consumption.create.start,date:"
+msgid "Date"
+msgstr "Date"
+
+msgctxt "field:sale.subscription.recurrence.rule,bymonth:"
+msgid "By Month"
+msgstr "Par mois"
+
+msgctxt "field:sale.subscription.recurrence.rule,bymonthday:"
+msgid "By Month Day"
+msgstr "Par jour du mois"
+
+msgctxt "field:sale.subscription.recurrence.rule,bysetpos:"
+msgid "By Position"
+msgstr "Par position"
+
+msgctxt "field:sale.subscription.recurrence.rule,byweekday:"
+msgid "By Week Day"
+msgstr "Par jour de semaine"
+
+msgctxt "field:sale.subscription.recurrence.rule,byweekno:"
+msgid "By Week Number"
+msgstr "Par numéro de semaine"
+
+msgctxt "field:sale.subscription.recurrence.rule,byyearday:"
+msgid "By Year Day"
+msgstr "Par jour d'année"
+
+msgctxt "field:sale.subscription.recurrence.rule,exclusive:"
+msgid "Exclusive"
+msgstr "Exclusive"
+
+msgctxt "field:sale.subscription.recurrence.rule,freq:"
+msgid "Frequency"
+msgstr "Fréquence"
+
+msgctxt "field:sale.subscription.recurrence.rule,interval:"
+msgid "Interval"
+msgstr "Intervalle"
+
+msgctxt "field:sale.subscription.recurrence.rule,set_:"
+msgid "Set"
+msgstr "Ensemble"
+
+msgctxt "field:sale.subscription.recurrence.rule,week_start_day:"
+msgid "Week Start Day"
+msgstr "Jour de début de semaine"
+
+msgctxt "field:sale.subscription.recurrence.rule.set,name:"
+msgid "Name"
+msgstr "Nom"
+
+msgctxt "field:sale.subscription.recurrence.rule.set,rules:"
+msgid "Rules"
+msgstr "Règles"
+
+msgctxt "field:sale.subscription.service,consumption_delay:"
+msgid "Consumption Delay"
+msgstr "Délai de consommation"
+
+msgctxt "field:sale.subscription.service,consumption_recurrence:"
+msgid "Consumption Recurrence"
+msgstr "Récurrence de consommation"
+
+msgctxt "field:sale.subscription.service,product:"
+msgid "Product"
+msgstr "Produit"
+
+msgctxt "help:sale.subscription,company:"
+msgid "Make the subscription belong to the company."
+msgstr "Faire appartenir l’abonnement à la société."
+
+msgctxt "help:sale.subscription,number:"
+msgid "The main identification of the subscription."
+msgstr "L'identifiant principal de l'abonnement."
+
+msgctxt "help:sale.subscription,party:"
+msgid "The party who subscribes."
+msgstr "Le tiers qui souscrit."
+
+msgctxt "help:sale.subscription,reference:"
+msgid "The identification of an external origin."
+msgstr "L'identifiant de l'origine externe."
+
+msgctxt "help:sale.subscription,state:"
+msgid "The current state of the subscription."
+msgstr "L'état actuel de l'abonnement."
+
+msgctxt "help:sale.subscription.line,subscription:"
+msgid "Add the line below the subscription."
+msgstr "Ajouter la ligne sous l'abonnement."
+
+msgctxt "help:sale.subscription.recurrence.rule,bymonth:"
+msgid "A comma separated list of integers."
+msgstr "Une liste d'entiers séparés par des virgules."
+
+msgctxt "help:sale.subscription.recurrence.rule,bymonthday:"
+msgid "A comma separated list of integers."
+msgstr "Une liste d'entiers séparés par des virgules."
+
+msgctxt "help:sale.subscription.recurrence.rule,bysetpos:"
+msgid "A comma separated list of integers."
+msgstr "Une liste d'entiers séparés par des virgules."
+
+msgctxt "help:sale.subscription.recurrence.rule,byweekday:"
+msgid "A comma separated list of integers or weekday (MO, TU etc)."
+msgstr ""
+"Une liste d'entiers ou de jour de semaine (MO, TU etc.) séparés par des "
+"virgules."
+
+msgctxt "help:sale.subscription.recurrence.rule,byweekno:"
+msgid "A comma separated list of integers (ISO8601)."
+msgstr "Une liste d'entiers (ISO8601) séparés par des virgules."
+
+msgctxt "help:sale.subscription.recurrence.rule,byyearday:"
+msgid "A comma separated list of integers."
+msgstr "Une liste d'entiers séparés par des virgules."
+
+msgctxt "help:sale.subscription.recurrence.rule,set_:"
+msgid "Add the rule below the set."
+msgstr "Ajouter la règle dans l'ensemble."
+
+msgctxt "help:sale.subscription.recurrence.rule.set,name:"
+msgid "The main identifier of the rule set."
+msgstr "L'identifiant principal de l'ensemble de règles."
+
+msgctxt "model:ir.action,name:act_create_invoice"
+msgid "Create Subscription Invoices"
+msgstr "Créer les factures d'abonnements"
+
+msgctxt "model:ir.action,name:act_line_consumption_create"
+msgid "Create Line Consumptions"
+msgstr "Créer les lignes de consommations"
+
+msgctxt "model:ir.action,name:act_recurrence_rule_set_form"
+msgid "Subscription Recurrence Rule Sets"
+msgstr "Ensemble de règles de récurrence d'abonnement"
+
+msgctxt "model:ir.action,name:act_service_form"
+msgid "Subscription Services"
+msgstr "Services d'abonnement"
+
+msgctxt "model:ir.action,name:act_subscription_form"
+msgid "Subscriptions"
+msgstr "Abonnements"
+
+msgctxt "model:ir.action,name:act_subscription_invoice_relate"
+msgid "Invoices"
+msgstr "Factures"
+
+msgctxt "model:ir.action,name:act_subscription_line_consumption_form"
+msgid "Consumptions"
+msgstr "Consommations"
+
+msgctxt ""
+"model:ir.action,name:act_subscription_line_consumption_subscription_line_relate"
+msgid "Consumptions"
+msgstr "Consommations"
+
+msgctxt ""
+"model:ir.action,name:act_subscription_line_consumption_subscription_relate"
+msgid "Consumptions"
+msgstr "Consommations"
+
+msgctxt "model:ir.action,name:act_subscription_party_relate"
+msgid "Subscriptions"
+msgstr "Abonnements"
+
+msgctxt ""
+"model:ir.action.act_window.domain,name:act_subscription_form_domain_all"
+msgid "All"
+msgstr "Tous"
+
+msgctxt ""
+"model:ir.action.act_window.domain,name:act_subscription_form_domain_draft"
+msgid "Draft"
+msgstr "Brouillons"
+
+msgctxt ""
+"model:ir.action.act_window.domain,name:act_subscription_form_domain_quotation"
+msgid "Quotation"
+msgstr "Devis"
+
+msgctxt ""
+"model:ir.action.act_window.domain,name:act_subscription_form_domain_running"
+msgid "Running"
+msgstr "En cours"
+
+msgctxt "model:ir.message,text:msg_consumption_delete_invoiced"
+msgid "You cannot delete invoiced consumption \"%(consumption)s\"."
+msgstr ""
+"Vous ne pouvez pas supprimer la consommation facturée « %(consumption)s »."
+
+msgctxt ""
+"model:ir.message,text:msg_consumption_invoice_missing_account_revenue"
+msgid ""
+"To invoice consumptions you must define an account revenue for product "
+"\"%(product)s\"."
+msgstr ""
+"Pour facture les consommations, vous devez définir un compte de produits "
+"pour le produit « %(product)s »."
+
+msgctxt "model:ir.message,text:msg_consumption_modify_invoiced"
+msgid "You cannot modify invoiced consumption \"%(consumption)s\"."
+msgstr ""
+"Vous ne pouvez pas modifier la consommation facturée « %(consumption)s »."
+
+msgctxt "model:ir.message,text:msg_consumption_recurrence_invalid"
+msgid ""
+"The consumption recurrence of line \"%(line)s\" of subscription "
+"\"%(subscription)s\" does not generate any occurrence."
+msgstr ""
+"La récurrence de consommation de la ligne « %(line)s » de l'abonnement "
+"« %(subscription)s » ne génère aucune occurrence."
+
+msgctxt "model:ir.message,text:msg_erase_party_pending_subscription"
+msgid ""
+"You cannot erase party \"%(party)s\" while they have pending subscriptions "
+"with company \"%(company)s\"."
+msgstr ""
+"Vous ne pouvez pas effacer le tiers « %(party)s » tant qu'il a des "
+"abonnements en cours pour la société « %(company)s »."
+
+msgctxt "model:ir.message,text:msg_invoice_recurrence_invalid"
+msgid ""
+"The invoice recurrence of subscription \"%(subscription)s\" does not "
+"generate any occurrence."
+msgstr ""
+"La récurrence de facturation de l'abonnement « %(subscription)s » ne génère"
+" aucune occurrence."
+
+msgctxt "model:ir.message,text:msg_recurrence_rule_invalid_by"
+msgid ""
+"Invalid \"%(field)s\" \"%(value)s\" in recurence rule "
+"\"%(recurrence_rule)s\" with exception \"%(exception)s\"."
+msgstr ""
+"« %(field)s » « %(value)s » sur la règle de récurrence "
+"« %(recurrence_rule)s » est invalide avec l'exception « %(exception)s »."
+
+msgctxt "model:ir.model.button,string:subscription_cancel_button"
+msgid "Cancel"
+msgstr "Annuler"
+
+msgctxt "model:ir.model.button,string:subscription_draft_button"
+msgid "Draft"
+msgstr "Brouillon"
+
+msgctxt "model:ir.model.button,string:subscription_quote_button"
+msgid "Quote"
+msgstr "Devis"
+
+msgctxt "model:ir.model.button,string:subscription_run_button"
+msgid "Run"
+msgstr "Lancer"
+
+msgctxt "model:ir.rule.group,name:rule_group_subscription_companies"
+msgid "User in companies"
+msgstr "Utilisateur dans les sociétés"
+
+msgctxt "model:ir.sequence,name:sequence_subscription"
+msgid "Subscription"
+msgstr "Abonnement"
+
+msgctxt "model:ir.sequence.type,name:sequence_type_subscription"
+msgid "Subscription"
+msgstr "Abonnement"
+
+msgctxt "model:ir.ui.menu,name:menu_configuration"
+msgid "Subscription"
+msgstr "Abonnement"
+
+msgctxt "model:ir.ui.menu,name:menu_create_invoice"
+msgid "Create Subscription Invoices"
+msgstr "Créer les factures d'abonnements"
+
+msgctxt "model:ir.ui.menu,name:menu_line_consumption_create"
+msgid "Create Line Consumptions"
+msgstr "Créer les lignes de consommations"
+
+msgctxt "model:ir.ui.menu,name:menu_recurrence_rule_set_form"
+msgid "Subscription Recurrence Rule Sets"
+msgstr "Ensemble de règles de récurrence d'abonnement"
+
+msgctxt "model:ir.ui.menu,name:menu_service_form"
+msgid "Subscription Services"
+msgstr "Services d'abonnement"
+
+msgctxt "model:ir.ui.menu,name:menu_subscription_form"
+msgid "Subscriptions"
+msgstr "Abonnements"
+
+msgctxt "model:sale.subscription,name:"
+msgid "Subscription"
+msgstr "Abonnement"
+
+msgctxt "model:sale.subscription.create_invoice.start,name:"
+msgid "Create Subscription Invoice"
+msgstr "Créer la facture d'abonnement"
+
+msgctxt "model:sale.subscription.line,name:"
+msgid "Subscription Line"
+msgstr "Ligne d'abonnement"
+
+msgctxt "model:sale.subscription.line.consumption,name:"
+msgid "Subscription Line Consumption"
+msgstr "Consommation de ligne d'abonnement"
+
+msgctxt "model:sale.subscription.line.consumption.create.start,name:"
+msgid "Create Subscription Line Consumption"
+msgstr "Créer la consommation de la ligne d'abonnement"
+
+msgctxt "model:sale.subscription.recurrence.rule,name:"
+msgid "Subscription Recurrence Rule"
+msgstr "Règle de récurrence d'abonnement"
+
+msgctxt "model:sale.subscription.recurrence.rule.set,name:"
+msgid "Subscription Recurrence Rule Set"
+msgstr "Ensemble de règles de récurrence d'abonnement"
+
+msgctxt "model:sale.subscription.service,name:"
+msgid "Subscription Service"
+msgstr "Service d'abonnement"
+
+msgctxt "selection:ir.cron,method:"
+msgid "Generate Subscription Invoices"
+msgstr "Générer les factures d'abonnements"
+
+msgctxt "selection:ir.cron,method:"
+msgid "Generate Subscription Line Consumptions"
+msgstr "Générer les lignes de consommation d'abonnements"
+
+msgctxt "selection:sale.subscription,state:"
+msgid "Cancelled"
+msgstr "Annulée"
+
+msgctxt "selection:sale.subscription,state:"
+msgid "Closed"
+msgstr "Clôturé"
+
+msgctxt "selection:sale.subscription,state:"
+msgid "Draft"
+msgstr "Brouillon"
+
+msgctxt "selection:sale.subscription,state:"
+msgid "Quotation"
+msgstr "Devis"
+
+msgctxt "selection:sale.subscription,state:"
+msgid "Running"
+msgstr "En cours"
+
+msgctxt "selection:sale.subscription.recurrence.rule,freq:"
+msgid "Daily"
+msgstr "Quotidien"
+
+msgctxt "selection:sale.subscription.recurrence.rule,freq:"
+msgid "Monthly"
+msgstr "Mensuel"
+
+msgctxt "selection:sale.subscription.recurrence.rule,freq:"
+msgid "Weekly"
+msgstr "Hebdomadaire"
+
+msgctxt "selection:sale.subscription.recurrence.rule,freq:"
+msgid "Yearly"
+msgstr "Annuel"
+
+msgctxt "view:sale.subscription.create_invoice.start:"
+msgid "Create Subscription Invoices for date"
+msgstr "Créer les factures d'abonnement pour la date"
+
+msgctxt "view:sale.subscription.line.consumption.create.start:"
+msgid "Create Subscription Line Consumptions for date"
+msgstr "Créer les lignes de consommation d'abonnement pour la date"
+
+msgctxt "view:sale.subscription.line:"
+msgid "General"
+msgstr "Général"
+
+msgctxt "view:sale.subscription:"
+msgid "Other Info"
+msgstr "Autre information"
+
+msgctxt "view:sale.subscription:"
+msgid "Subscription"
+msgstr "Abonnement"
+
+msgctxt "wizard_button:sale.subscription.create_invoice,start,create_:"
+msgid "Create"
+msgstr "Créer"
+
+msgctxt "wizard_button:sale.subscription.create_invoice,start,end:"
+msgid "Cancel"
+msgstr "Annuler"
+
+msgctxt ""
+"wizard_button:sale.subscription.line.consumption.create,start,create_:"
+msgid "Create"
+msgstr "Créer"
+
+msgctxt "wizard_button:sale.subscription.line.consumption.create,start,end:"
+msgid "Cancel"
+msgstr "Annuler"
diff --git a/modules/sale_subscription/locale/hu.po b/modules/sale_subscription/locale/hu.po
new file mode 100644
index 0000000000..4e46c4f6c0
--- /dev/null
+++ b/modules/sale_subscription/locale/hu.po
@@ -0,0 +1,611 @@
+#
+msgid ""
+msgstr "Content-Type: text/plain; charset=utf-8\n"
+
+#, fuzzy
+msgctxt "field:sale.configuration,subscription_sequence:"
+msgid "Subscription Sequence"
+msgstr "Subscription Services"
+
+#, fuzzy
+msgctxt "field:sale.configuration.sequence,subscription_sequence:"
+msgid "Subscription Sequence"
+msgstr "Subscription Services"
+
+msgctxt "field:sale.subscription,company:"
+msgid "Company"
+msgstr ""
+
+msgctxt "field:sale.subscription,contact:"
+msgid "Contact"
+msgstr ""
+
+msgctxt "field:sale.subscription,currency:"
+msgid "Currency"
+msgstr ""
+
+#, fuzzy
+msgctxt "field:sale.subscription,description:"
+msgid "Description"
+msgstr "Subscription"
+
+msgctxt "field:sale.subscription,end_date:"
+msgid "End Date"
+msgstr ""
+
+msgctxt "field:sale.subscription,invoice_address:"
+msgid "Invoice Address"
+msgstr ""
+
+msgctxt "field:sale.subscription,invoice_party:"
+msgid "Invoice Party"
+msgstr ""
+
+msgctxt "field:sale.subscription,invoice_recurrence:"
+msgid "Invoice Recurrence"
+msgstr ""
+
+msgctxt "field:sale.subscription,invoice_start_date:"
+msgid "Invoice Start Date"
+msgstr ""
+
+msgctxt "field:sale.subscription,lines:"
+msgid "Lines"
+msgstr ""
+
+msgctxt "field:sale.subscription,next_invoice_date:"
+msgid "Next Invoice Date"
+msgstr ""
+
+msgctxt "field:sale.subscription,number:"
+msgid "Number"
+msgstr ""
+
+msgctxt "field:sale.subscription,party:"
+msgid "Party"
+msgstr ""
+
+msgctxt "field:sale.subscription,payment_term:"
+msgid "Payment Term"
+msgstr ""
+
+#, fuzzy
+msgctxt "field:sale.subscription,quoted_by:"
+msgid "Quoted By"
+msgstr "Quote"
+
+msgctxt "field:sale.subscription,reference:"
+msgid "Reference"
+msgstr ""
+
+msgctxt "field:sale.subscription,run_by:"
+msgid "Run By"
+msgstr ""
+
+msgctxt "field:sale.subscription,start_date:"
+msgid "Start Date"
+msgstr ""
+
+msgctxt "field:sale.subscription,state:"
+msgid "State"
+msgstr ""
+
+msgctxt "field:sale.subscription.create_invoice.start,date:"
+msgid "Date"
+msgstr ""
+
+msgctxt "field:sale.subscription.line,company:"
+msgid "Company"
+msgstr ""
+
+#, fuzzy
+msgctxt "field:sale.subscription.line,consumed_until:"
+msgid "Consumed until"
+msgstr "Consumptions"
+
+msgctxt "field:sale.subscription.line,consumption_delay:"
+msgid "Consumption Delay"
+msgstr ""
+
+msgctxt "field:sale.subscription.line,consumption_recurrence:"
+msgid "Consumption Recurrence"
+msgstr ""
+
+msgctxt "field:sale.subscription.line,currency:"
+msgid "Currency"
+msgstr ""
+
+#, fuzzy
+msgctxt "field:sale.subscription.line,description:"
+msgid "Description"
+msgstr "Subscription"
+
+msgctxt "field:sale.subscription.line,end_date:"
+msgid "End Date"
+msgstr ""
+
+msgctxt "field:sale.subscription.line,next_consumption_date:"
+msgid "Next Consumption Date"
+msgstr ""
+
+msgctxt "field:sale.subscription.line,next_consumption_date_delayed:"
+msgid "Next Consumption Delayed"
+msgstr ""
+
+msgctxt "field:sale.subscription.line,quantity:"
+msgid "Quantity"
+msgstr ""
+
+msgctxt "field:sale.subscription.line,service:"
+msgid "Service"
+msgstr ""
+
+msgctxt "field:sale.subscription.line,service_unit_category:"
+msgid "Service Unit Category"
+msgstr ""
+
+msgctxt "field:sale.subscription.line,start_date:"
+msgid "Start Date"
+msgstr ""
+
+#, fuzzy
+msgctxt "field:sale.subscription.line,subscription:"
+msgid "Subscription"
+msgstr "Subscription"
+
+#, fuzzy
+msgctxt "field:sale.subscription.line,subscription_end_date:"
+msgid "Subscription End Date"
+msgstr "Subscription Services"
+
+#, fuzzy
+msgctxt "field:sale.subscription.line,subscription_start_date:"
+msgid "Subscription Start Date"
+msgstr "Subscription Services"
+
+#, fuzzy
+msgctxt "field:sale.subscription.line,subscription_state:"
+msgid "Subscription State"
+msgstr "Subscription Services"
+
+msgctxt "field:sale.subscription.line,unit:"
+msgid "Unit"
+msgstr ""
+
+msgctxt "field:sale.subscription.line,unit_digits:"
+msgid "Unit Digits"
+msgstr ""
+
+msgctxt "field:sale.subscription.line,unit_price:"
+msgid "Unit Price"
+msgstr ""
+
+msgctxt "field:sale.subscription.line.consumption,date:"
+msgid "Date"
+msgstr ""
+
+msgctxt "field:sale.subscription.line.consumption,invoice_line:"
+msgid "Invoice Line"
+msgstr ""
+
+msgctxt "field:sale.subscription.line.consumption,line:"
+msgid "Line"
+msgstr ""
+
+msgctxt "field:sale.subscription.line.consumption,quantity:"
+msgid "Quantity"
+msgstr ""
+
+msgctxt "field:sale.subscription.line.consumption,unit_digits:"
+msgid "Unit Digits"
+msgstr ""
+
+msgctxt "field:sale.subscription.line.consumption.create.start,date:"
+msgid "Date"
+msgstr ""
+
+msgctxt "field:sale.subscription.recurrence.rule,bymonth:"
+msgid "By Month"
+msgstr ""
+
+msgctxt "field:sale.subscription.recurrence.rule,bymonthday:"
+msgid "By Month Day"
+msgstr ""
+
+msgctxt "field:sale.subscription.recurrence.rule,bysetpos:"
+msgid "By Position"
+msgstr ""
+
+msgctxt "field:sale.subscription.recurrence.rule,byweekday:"
+msgid "By Week Day"
+msgstr ""
+
+msgctxt "field:sale.subscription.recurrence.rule,byweekno:"
+msgid "By Week Number"
+msgstr ""
+
+msgctxt "field:sale.subscription.recurrence.rule,byyearday:"
+msgid "By Year Day"
+msgstr ""
+
+msgctxt "field:sale.subscription.recurrence.rule,exclusive:"
+msgid "Exclusive"
+msgstr ""
+
+msgctxt "field:sale.subscription.recurrence.rule,freq:"
+msgid "Frequency"
+msgstr ""
+
+msgctxt "field:sale.subscription.recurrence.rule,interval:"
+msgid "Interval"
+msgstr ""
+
+msgctxt "field:sale.subscription.recurrence.rule,set_:"
+msgid "Set"
+msgstr ""
+
+msgctxt "field:sale.subscription.recurrence.rule,week_start_day:"
+msgid "Week Start Day"
+msgstr ""
+
+msgctxt "field:sale.subscription.recurrence.rule.set,name:"
+msgid "Name"
+msgstr ""
+
+msgctxt "field:sale.subscription.recurrence.rule.set,rules:"
+msgid "Rules"
+msgstr ""
+
+msgctxt "field:sale.subscription.service,consumption_delay:"
+msgid "Consumption Delay"
+msgstr ""
+
+msgctxt "field:sale.subscription.service,consumption_recurrence:"
+msgid "Consumption Recurrence"
+msgstr ""
+
+msgctxt "field:sale.subscription.service,product:"
+msgid "Product"
+msgstr ""
+
+msgctxt "help:sale.subscription,company:"
+msgid "Make the subscription belong to the company."
+msgstr ""
+
+msgctxt "help:sale.subscription,number:"
+msgid "The main identification of the subscription."
+msgstr ""
+
+msgctxt "help:sale.subscription,party:"
+msgid "The party who subscribes."
+msgstr ""
+
+msgctxt "help:sale.subscription,reference:"
+msgid "The identification of an external origin."
+msgstr ""
+
+msgctxt "help:sale.subscription,state:"
+msgid "The current state of the subscription."
+msgstr ""
+
+msgctxt "help:sale.subscription.line,subscription:"
+msgid "Add the line below the subscription."
+msgstr ""
+
+msgctxt "help:sale.subscription.recurrence.rule,bymonth:"
+msgid "A comma separated list of integers."
+msgstr ""
+
+msgctxt "help:sale.subscription.recurrence.rule,bymonthday:"
+msgid "A comma separated list of integers."
+msgstr ""
+
+msgctxt "help:sale.subscription.recurrence.rule,bysetpos:"
+msgid "A comma separated list of integers."
+msgstr ""
+
+msgctxt "help:sale.subscription.recurrence.rule,byweekday:"
+msgid "A comma separated list of integers or weekday (MO, TU etc)."
+msgstr ""
+
+msgctxt "help:sale.subscription.recurrence.rule,byweekno:"
+msgid "A comma separated list of integers (ISO8601)."
+msgstr ""
+
+msgctxt "help:sale.subscription.recurrence.rule,byyearday:"
+msgid "A comma separated list of integers."
+msgstr ""
+
+msgctxt "help:sale.subscription.recurrence.rule,set_:"
+msgid "Add the rule below the set."
+msgstr ""
+
+msgctxt "help:sale.subscription.recurrence.rule.set,name:"
+msgid "The main identifier of the rule set."
+msgstr ""
+
+msgctxt "model:ir.action,name:act_create_invoice"
+msgid "Create Subscription Invoices"
+msgstr "Create Subscription Invoices"
+
+msgctxt "model:ir.action,name:act_line_consumption_create"
+msgid "Create Line Consumptions"
+msgstr "Create Line Consumptions"
+
+msgctxt "model:ir.action,name:act_recurrence_rule_set_form"
+msgid "Subscription Recurrence Rule Sets"
+msgstr "Subscription Recurrence Rule Sets"
+
+msgctxt "model:ir.action,name:act_service_form"
+msgid "Subscription Services"
+msgstr "Subscription Services"
+
+msgctxt "model:ir.action,name:act_subscription_form"
+msgid "Subscriptions"
+msgstr "Subscriptions"
+
+msgctxt "model:ir.action,name:act_subscription_invoice_relate"
+msgid "Invoices"
+msgstr ""
+
+msgctxt "model:ir.action,name:act_subscription_line_consumption_form"
+msgid "Consumptions"
+msgstr "Consumptions"
+
+msgctxt ""
+"model:ir.action,name:act_subscription_line_consumption_subscription_line_relate"
+msgid "Consumptions"
+msgstr "Consumptions"
+
+msgctxt ""
+"model:ir.action,name:act_subscription_line_consumption_subscription_relate"
+msgid "Consumptions"
+msgstr "Consumptions"
+
+msgctxt "model:ir.action,name:act_subscription_party_relate"
+msgid "Subscriptions"
+msgstr "Subscriptions"
+
+msgctxt ""
+"model:ir.action.act_window.domain,name:act_subscription_form_domain_all"
+msgid "All"
+msgstr "All"
+
+msgctxt ""
+"model:ir.action.act_window.domain,name:act_subscription_form_domain_draft"
+msgid "Draft"
+msgstr "Draft"
+
+msgctxt ""
+"model:ir.action.act_window.domain,name:act_subscription_form_domain_quotation"
+msgid "Quotation"
+msgstr "Quotation"
+
+msgctxt ""
+"model:ir.action.act_window.domain,name:act_subscription_form_domain_running"
+msgid "Running"
+msgstr "Running"
+
+msgctxt "model:ir.message,text:msg_consumption_delete_invoiced"
+msgid "You cannot delete invoiced consumption \"%(consumption)s\"."
+msgstr ""
+
+msgctxt ""
+"model:ir.message,text:msg_consumption_invoice_missing_account_revenue"
+msgid ""
+"To invoice consumptions you must define an account revenue for product "
+"\"%(product)s\"."
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_consumption_modify_invoiced"
+msgid "You cannot modify invoiced consumption \"%(consumption)s\"."
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_consumption_recurrence_invalid"
+msgid ""
+"The consumption recurrence of line \"%(line)s\" of subscription "
+"\"%(subscription)s\" does not generate any occurrence."
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_erase_party_pending_subscription"
+msgid ""
+"You cannot erase party \"%(party)s\" while they have pending subscriptions "
+"with company \"%(company)s\"."
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_invoice_recurrence_invalid"
+msgid ""
+"The invoice recurrence of subscription \"%(subscription)s\" does not "
+"generate any occurrence."
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_recurrence_rule_invalid_by"
+msgid ""
+"Invalid \"%(field)s\" \"%(value)s\" in recurence rule "
+"\"%(recurrence_rule)s\" with exception \"%(exception)s\"."
+msgstr ""
+
+msgctxt "model:ir.model.button,string:subscription_cancel_button"
+msgid "Cancel"
+msgstr "Cancel"
+
+msgctxt "model:ir.model.button,string:subscription_draft_button"
+msgid "Draft"
+msgstr "Draft"
+
+msgctxt "model:ir.model.button,string:subscription_quote_button"
+msgid "Quote"
+msgstr "Quote"
+
+msgctxt "model:ir.model.button,string:subscription_run_button"
+msgid "Run"
+msgstr "Run"
+
+msgctxt "model:ir.rule.group,name:rule_group_subscription_companies"
+msgid "User in companies"
+msgstr ""
+
+msgctxt "model:ir.sequence,name:sequence_subscription"
+msgid "Subscription"
+msgstr "Subscription"
+
+msgctxt "model:ir.sequence.type,name:sequence_type_subscription"
+msgid "Subscription"
+msgstr "Subscription"
+
+#, fuzzy
+msgctxt "model:ir.ui.menu,name:menu_configuration"
+msgid "Subscription"
+msgstr "Subscription"
+
+msgctxt "model:ir.ui.menu,name:menu_create_invoice"
+msgid "Create Subscription Invoices"
+msgstr "Create Subscription Invoices"
+
+msgctxt "model:ir.ui.menu,name:menu_line_consumption_create"
+msgid "Create Line Consumptions"
+msgstr "Create Line Consumptions"
+
+msgctxt "model:ir.ui.menu,name:menu_recurrence_rule_set_form"
+msgid "Subscription Recurrence Rule Sets"
+msgstr "Subscription Recurrence Rule Sets"
+
+msgctxt "model:ir.ui.menu,name:menu_service_form"
+msgid "Subscription Services"
+msgstr "Subscription Services"
+
+msgctxt "model:ir.ui.menu,name:menu_subscription_form"
+msgid "Subscriptions"
+msgstr "Subscriptions"
+
+#, fuzzy
+msgctxt "model:sale.subscription,name:"
+msgid "Subscription"
+msgstr "Subscription"
+
+#, fuzzy
+msgctxt "model:sale.subscription.create_invoice.start,name:"
+msgid "Create Subscription Invoice"
+msgstr "Create Subscription Invoices"
+
+#, fuzzy
+msgctxt "model:sale.subscription.line,name:"
+msgid "Subscription Line"
+msgstr "Subscription Services"
+
+#, fuzzy
+msgctxt "model:sale.subscription.line.consumption,name:"
+msgid "Subscription Line Consumption"
+msgstr "Generate Subscription Line Consumptions"
+
+#, fuzzy
+msgctxt "model:sale.subscription.line.consumption.create.start,name:"
+msgid "Create Subscription Line Consumption"
+msgstr "Generate Subscription Line Consumptions"
+
+#, fuzzy
+msgctxt "model:sale.subscription.recurrence.rule,name:"
+msgid "Subscription Recurrence Rule"
+msgstr "Subscription Recurrence Rule Sets"
+
+#, fuzzy
+msgctxt "model:sale.subscription.recurrence.rule.set,name:"
+msgid "Subscription Recurrence Rule Set"
+msgstr "Subscription Recurrence Rule Sets"
+
+#, fuzzy
+msgctxt "model:sale.subscription.service,name:"
+msgid "Subscription Service"
+msgstr "Subscription Services"
+
+#, fuzzy
+msgctxt "selection:ir.cron,method:"
+msgid "Generate Subscription Invoices"
+msgstr "Generate Subscription Invoices"
+
+#, fuzzy
+msgctxt "selection:ir.cron,method:"
+msgid "Generate Subscription Line Consumptions"
+msgstr "Generate Subscription Line Consumptions"
+
+#, fuzzy
+msgctxt "selection:sale.subscription,state:"
+msgid "Cancelled"
+msgstr "Cancel"
+
+msgctxt "selection:sale.subscription,state:"
+msgid "Closed"
+msgstr ""
+
+#, fuzzy
+msgctxt "selection:sale.subscription,state:"
+msgid "Draft"
+msgstr "Draft"
+
+#, fuzzy
+msgctxt "selection:sale.subscription,state:"
+msgid "Quotation"
+msgstr "Quotation"
+
+#, fuzzy
+msgctxt "selection:sale.subscription,state:"
+msgid "Running"
+msgstr "Running"
+
+msgctxt "selection:sale.subscription.recurrence.rule,freq:"
+msgid "Daily"
+msgstr ""
+
+msgctxt "selection:sale.subscription.recurrence.rule,freq:"
+msgid "Monthly"
+msgstr ""
+
+msgctxt "selection:sale.subscription.recurrence.rule,freq:"
+msgid "Weekly"
+msgstr ""
+
+msgctxt "selection:sale.subscription.recurrence.rule,freq:"
+msgid "Yearly"
+msgstr ""
+
+#, fuzzy
+msgctxt "view:sale.subscription.create_invoice.start:"
+msgid "Create Subscription Invoices for date"
+msgstr "Create Subscription Invoices"
+
+#, fuzzy
+msgctxt "view:sale.subscription.line.consumption.create.start:"
+msgid "Create Subscription Line Consumptions for date"
+msgstr "Generate Subscription Line Consumptions"
+
+msgctxt "view:sale.subscription.line:"
+msgid "General"
+msgstr ""
+
+msgctxt "view:sale.subscription:"
+msgid "Other Info"
+msgstr ""
+
+#, fuzzy
+msgctxt "view:sale.subscription:"
+msgid "Subscription"
+msgstr "Subscription"
+
+msgctxt "wizard_button:sale.subscription.create_invoice,start,create_:"
+msgid "Create"
+msgstr ""
+
+#, fuzzy
+msgctxt "wizard_button:sale.subscription.create_invoice,start,end:"
+msgid "Cancel"
+msgstr "Cancel"
+
+msgctxt ""
+"wizard_button:sale.subscription.line.consumption.create,start,create_:"
+msgid "Create"
+msgstr ""
+
+#, fuzzy
+msgctxt "wizard_button:sale.subscription.line.consumption.create,start,end:"
+msgid "Cancel"
+msgstr "Cancel"
diff --git a/modules/sale_subscription/locale/id.po b/modules/sale_subscription/locale/id.po
new file mode 100644
index 0000000000..291e819502
--- /dev/null
+++ b/modules/sale_subscription/locale/id.po
@@ -0,0 +1,584 @@
+#
+msgid ""
+msgstr "Content-Type: text/plain; charset=utf-8\n"
+
+msgctxt "field:sale.configuration,subscription_sequence:"
+msgid "Subscription Sequence"
+msgstr ""
+
+msgctxt "field:sale.configuration.sequence,subscription_sequence:"
+msgid "Subscription Sequence"
+msgstr ""
+
+msgctxt "field:sale.subscription,company:"
+msgid "Company"
+msgstr "Perusahaan"
+
+msgctxt "field:sale.subscription,contact:"
+msgid "Contact"
+msgstr ""
+
+msgctxt "field:sale.subscription,currency:"
+msgid "Currency"
+msgstr "Mata uang"
+
+msgctxt "field:sale.subscription,description:"
+msgid "Description"
+msgstr "Deskripsi"
+
+msgctxt "field:sale.subscription,end_date:"
+msgid "End Date"
+msgstr "Tanggal Akhir"
+
+msgctxt "field:sale.subscription,invoice_address:"
+msgid "Invoice Address"
+msgstr "Alamat Faktur"
+
+#, fuzzy
+msgctxt "field:sale.subscription,invoice_party:"
+msgid "Invoice Party"
+msgstr "Tanggal Faktur Berikutnya"
+
+msgctxt "field:sale.subscription,invoice_recurrence:"
+msgid "Invoice Recurrence"
+msgstr ""
+
+msgctxt "field:sale.subscription,invoice_start_date:"
+msgid "Invoice Start Date"
+msgstr ""
+
+msgctxt "field:sale.subscription,lines:"
+msgid "Lines"
+msgstr "Baris"
+
+msgctxt "field:sale.subscription,next_invoice_date:"
+msgid "Next Invoice Date"
+msgstr "Tanggal Faktur Berikutnya"
+
+msgctxt "field:sale.subscription,number:"
+msgid "Number"
+msgstr "Nomor"
+
+msgctxt "field:sale.subscription,party:"
+msgid "Party"
+msgstr "Pihak"
+
+msgctxt "field:sale.subscription,payment_term:"
+msgid "Payment Term"
+msgstr "Masa Pembayaran"
+
+msgctxt "field:sale.subscription,quoted_by:"
+msgid "Quoted By"
+msgstr "Dikutip Oleh"
+
+msgctxt "field:sale.subscription,reference:"
+msgid "Reference"
+msgstr "Referensi"
+
+msgctxt "field:sale.subscription,run_by:"
+msgid "Run By"
+msgstr ""
+
+msgctxt "field:sale.subscription,start_date:"
+msgid "Start Date"
+msgstr "Tanggal Awal"
+
+msgctxt "field:sale.subscription,state:"
+msgid "State"
+msgstr "Status"
+
+msgctxt "field:sale.subscription.create_invoice.start,date:"
+msgid "Date"
+msgstr "Tanggal"
+
+msgctxt "field:sale.subscription.line,company:"
+msgid "Company"
+msgstr "Perusahaan"
+
+msgctxt "field:sale.subscription.line,consumed_until:"
+msgid "Consumed until"
+msgstr ""
+
+msgctxt "field:sale.subscription.line,consumption_delay:"
+msgid "Consumption Delay"
+msgstr ""
+
+msgctxt "field:sale.subscription.line,consumption_recurrence:"
+msgid "Consumption Recurrence"
+msgstr ""
+
+#, fuzzy
+msgctxt "field:sale.subscription.line,currency:"
+msgid "Currency"
+msgstr "Mata uang"
+
+msgctxt "field:sale.subscription.line,description:"
+msgid "Description"
+msgstr "Deskripsi"
+
+msgctxt "field:sale.subscription.line,end_date:"
+msgid "End Date"
+msgstr "Tanggal Akhir"
+
+msgctxt "field:sale.subscription.line,next_consumption_date:"
+msgid "Next Consumption Date"
+msgstr ""
+
+msgctxt "field:sale.subscription.line,next_consumption_date_delayed:"
+msgid "Next Consumption Delayed"
+msgstr ""
+
+msgctxt "field:sale.subscription.line,quantity:"
+msgid "Quantity"
+msgstr ""
+
+msgctxt "field:sale.subscription.line,service:"
+msgid "Service"
+msgstr "Jasa"
+
+msgctxt "field:sale.subscription.line,service_unit_category:"
+msgid "Service Unit Category"
+msgstr ""
+
+msgctxt "field:sale.subscription.line,start_date:"
+msgid "Start Date"
+msgstr "Tanggal Awal"
+
+msgctxt "field:sale.subscription.line,subscription:"
+msgid "Subscription"
+msgstr ""
+
+msgctxt "field:sale.subscription.line,subscription_end_date:"
+msgid "Subscription End Date"
+msgstr ""
+
+msgctxt "field:sale.subscription.line,subscription_start_date:"
+msgid "Subscription Start Date"
+msgstr ""
+
+msgctxt "field:sale.subscription.line,subscription_state:"
+msgid "Subscription State"
+msgstr ""
+
+msgctxt "field:sale.subscription.line,unit:"
+msgid "Unit"
+msgstr ""
+
+msgctxt "field:sale.subscription.line,unit_digits:"
+msgid "Unit Digits"
+msgstr ""
+
+msgctxt "field:sale.subscription.line,unit_price:"
+msgid "Unit Price"
+msgstr ""
+
+msgctxt "field:sale.subscription.line.consumption,date:"
+msgid "Date"
+msgstr "Tanggal"
+
+msgctxt "field:sale.subscription.line.consumption,invoice_line:"
+msgid "Invoice Line"
+msgstr "Baris Faktur"
+
+msgctxt "field:sale.subscription.line.consumption,line:"
+msgid "Line"
+msgstr "Baris"
+
+msgctxt "field:sale.subscription.line.consumption,quantity:"
+msgid "Quantity"
+msgstr ""
+
+msgctxt "field:sale.subscription.line.consumption,unit_digits:"
+msgid "Unit Digits"
+msgstr ""
+
+msgctxt "field:sale.subscription.line.consumption.create.start,date:"
+msgid "Date"
+msgstr "Tanggal"
+
+msgctxt "field:sale.subscription.recurrence.rule,bymonth:"
+msgid "By Month"
+msgstr ""
+
+msgctxt "field:sale.subscription.recurrence.rule,bymonthday:"
+msgid "By Month Day"
+msgstr ""
+
+msgctxt "field:sale.subscription.recurrence.rule,bysetpos:"
+msgid "By Position"
+msgstr ""
+
+msgctxt "field:sale.subscription.recurrence.rule,byweekday:"
+msgid "By Week Day"
+msgstr ""
+
+msgctxt "field:sale.subscription.recurrence.rule,byweekno:"
+msgid "By Week Number"
+msgstr ""
+
+msgctxt "field:sale.subscription.recurrence.rule,byyearday:"
+msgid "By Year Day"
+msgstr ""
+
+msgctxt "field:sale.subscription.recurrence.rule,exclusive:"
+msgid "Exclusive"
+msgstr ""
+
+msgctxt "field:sale.subscription.recurrence.rule,freq:"
+msgid "Frequency"
+msgstr "Frekuensi"
+
+msgctxt "field:sale.subscription.recurrence.rule,interval:"
+msgid "Interval"
+msgstr ""
+
+msgctxt "field:sale.subscription.recurrence.rule,set_:"
+msgid "Set"
+msgstr ""
+
+msgctxt "field:sale.subscription.recurrence.rule,week_start_day:"
+msgid "Week Start Day"
+msgstr ""
+
+msgctxt "field:sale.subscription.recurrence.rule.set,name:"
+msgid "Name"
+msgstr "Nama"
+
+msgctxt "field:sale.subscription.recurrence.rule.set,rules:"
+msgid "Rules"
+msgstr ""
+
+msgctxt "field:sale.subscription.service,consumption_delay:"
+msgid "Consumption Delay"
+msgstr ""
+
+msgctxt "field:sale.subscription.service,consumption_recurrence:"
+msgid "Consumption Recurrence"
+msgstr ""
+
+msgctxt "field:sale.subscription.service,product:"
+msgid "Product"
+msgstr "Produk"
+
+msgctxt "help:sale.subscription,company:"
+msgid "Make the subscription belong to the company."
+msgstr ""
+
+msgctxt "help:sale.subscription,number:"
+msgid "The main identification of the subscription."
+msgstr ""
+
+msgctxt "help:sale.subscription,party:"
+msgid "The party who subscribes."
+msgstr ""
+
+msgctxt "help:sale.subscription,reference:"
+msgid "The identification of an external origin."
+msgstr ""
+
+msgctxt "help:sale.subscription,state:"
+msgid "The current state of the subscription."
+msgstr ""
+
+msgctxt "help:sale.subscription.line,subscription:"
+msgid "Add the line below the subscription."
+msgstr ""
+
+msgctxt "help:sale.subscription.recurrence.rule,bymonth:"
+msgid "A comma separated list of integers."
+msgstr ""
+
+msgctxt "help:sale.subscription.recurrence.rule,bymonthday:"
+msgid "A comma separated list of integers."
+msgstr ""
+
+msgctxt "help:sale.subscription.recurrence.rule,bysetpos:"
+msgid "A comma separated list of integers."
+msgstr ""
+
+msgctxt "help:sale.subscription.recurrence.rule,byweekday:"
+msgid "A comma separated list of integers or weekday (MO, TU etc)."
+msgstr ""
+
+msgctxt "help:sale.subscription.recurrence.rule,byweekno:"
+msgid "A comma separated list of integers (ISO8601)."
+msgstr ""
+
+msgctxt "help:sale.subscription.recurrence.rule,byyearday:"
+msgid "A comma separated list of integers."
+msgstr ""
+
+msgctxt "help:sale.subscription.recurrence.rule,set_:"
+msgid "Add the rule below the set."
+msgstr ""
+
+msgctxt "help:sale.subscription.recurrence.rule.set,name:"
+msgid "The main identifier of the rule set."
+msgstr ""
+
+msgctxt "model:ir.action,name:act_create_invoice"
+msgid "Create Subscription Invoices"
+msgstr ""
+
+msgctxt "model:ir.action,name:act_line_consumption_create"
+msgid "Create Line Consumptions"
+msgstr ""
+
+msgctxt "model:ir.action,name:act_recurrence_rule_set_form"
+msgid "Subscription Recurrence Rule Sets"
+msgstr ""
+
+msgctxt "model:ir.action,name:act_service_form"
+msgid "Subscription Services"
+msgstr ""
+
+msgctxt "model:ir.action,name:act_subscription_form"
+msgid "Subscriptions"
+msgstr ""
+
+msgctxt "model:ir.action,name:act_subscription_invoice_relate"
+msgid "Invoices"
+msgstr "Faktur-faktur"
+
+msgctxt "model:ir.action,name:act_subscription_line_consumption_form"
+msgid "Consumptions"
+msgstr ""
+
+msgctxt ""
+"model:ir.action,name:act_subscription_line_consumption_subscription_line_relate"
+msgid "Consumptions"
+msgstr ""
+
+msgctxt ""
+"model:ir.action,name:act_subscription_line_consumption_subscription_relate"
+msgid "Consumptions"
+msgstr ""
+
+msgctxt "model:ir.action,name:act_subscription_party_relate"
+msgid "Subscriptions"
+msgstr ""
+
+msgctxt ""
+"model:ir.action.act_window.domain,name:act_subscription_form_domain_all"
+msgid "All"
+msgstr ""
+
+msgctxt ""
+"model:ir.action.act_window.domain,name:act_subscription_form_domain_draft"
+msgid "Draft"
+msgstr ""
+
+msgctxt ""
+"model:ir.action.act_window.domain,name:act_subscription_form_domain_quotation"
+msgid "Quotation"
+msgstr ""
+
+msgctxt ""
+"model:ir.action.act_window.domain,name:act_subscription_form_domain_running"
+msgid "Running"
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_consumption_delete_invoiced"
+msgid "You cannot delete invoiced consumption \"%(consumption)s\"."
+msgstr ""
+
+msgctxt ""
+"model:ir.message,text:msg_consumption_invoice_missing_account_revenue"
+msgid ""
+"To invoice consumptions you must define an account revenue for product "
+"\"%(product)s\"."
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_consumption_modify_invoiced"
+msgid "You cannot modify invoiced consumption \"%(consumption)s\"."
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_consumption_recurrence_invalid"
+msgid ""
+"The consumption recurrence of line \"%(line)s\" of subscription "
+"\"%(subscription)s\" does not generate any occurrence."
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_erase_party_pending_subscription"
+msgid ""
+"You cannot erase party \"%(party)s\" while they have pending subscriptions "
+"with company \"%(company)s\"."
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_invoice_recurrence_invalid"
+msgid ""
+"The invoice recurrence of subscription \"%(subscription)s\" does not "
+"generate any occurrence."
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_recurrence_rule_invalid_by"
+msgid ""
+"Invalid \"%(field)s\" \"%(value)s\" in recurence rule "
+"\"%(recurrence_rule)s\" with exception \"%(exception)s\"."
+msgstr ""
+
+msgctxt "model:ir.model.button,string:subscription_cancel_button"
+msgid "Cancel"
+msgstr "Batal"
+
+msgctxt "model:ir.model.button,string:subscription_draft_button"
+msgid "Draft"
+msgstr "Rancangan"
+
+msgctxt "model:ir.model.button,string:subscription_quote_button"
+msgid "Quote"
+msgstr ""
+
+msgctxt "model:ir.model.button,string:subscription_run_button"
+msgid "Run"
+msgstr ""
+
+msgctxt "model:ir.rule.group,name:rule_group_subscription_companies"
+msgid "User in companies"
+msgstr ""
+
+msgctxt "model:ir.sequence,name:sequence_subscription"
+msgid "Subscription"
+msgstr ""
+
+msgctxt "model:ir.sequence.type,name:sequence_type_subscription"
+msgid "Subscription"
+msgstr ""
+
+#, fuzzy
+msgctxt "model:ir.ui.menu,name:menu_configuration"
+msgid "Subscription"
+msgstr "Deskripsi"
+
+msgctxt "model:ir.ui.menu,name:menu_create_invoice"
+msgid "Create Subscription Invoices"
+msgstr ""
+
+msgctxt "model:ir.ui.menu,name:menu_line_consumption_create"
+msgid "Create Line Consumptions"
+msgstr ""
+
+msgctxt "model:ir.ui.menu,name:menu_recurrence_rule_set_form"
+msgid "Subscription Recurrence Rule Sets"
+msgstr ""
+
+msgctxt "model:ir.ui.menu,name:menu_service_form"
+msgid "Subscription Services"
+msgstr ""
+
+msgctxt "model:ir.ui.menu,name:menu_subscription_form"
+msgid "Subscriptions"
+msgstr ""
+
+msgctxt "model:sale.subscription,name:"
+msgid "Subscription"
+msgstr ""
+
+msgctxt "model:sale.subscription.create_invoice.start,name:"
+msgid "Create Subscription Invoice"
+msgstr ""
+
+msgctxt "model:sale.subscription.line,name:"
+msgid "Subscription Line"
+msgstr ""
+
+msgctxt "model:sale.subscription.line.consumption,name:"
+msgid "Subscription Line Consumption"
+msgstr ""
+
+msgctxt "model:sale.subscription.line.consumption.create.start,name:"
+msgid "Create Subscription Line Consumption"
+msgstr ""
+
+msgctxt "model:sale.subscription.recurrence.rule,name:"
+msgid "Subscription Recurrence Rule"
+msgstr ""
+
+msgctxt "model:sale.subscription.recurrence.rule.set,name:"
+msgid "Subscription Recurrence Rule Set"
+msgstr ""
+
+msgctxt "model:sale.subscription.service,name:"
+msgid "Subscription Service"
+msgstr ""
+
+msgctxt "selection:ir.cron,method:"
+msgid "Generate Subscription Invoices"
+msgstr ""
+
+msgctxt "selection:ir.cron,method:"
+msgid "Generate Subscription Line Consumptions"
+msgstr ""
+
+msgctxt "selection:sale.subscription,state:"
+msgid "Cancelled"
+msgstr "Dibatalkan"
+
+msgctxt "selection:sale.subscription,state:"
+msgid "Closed"
+msgstr ""
+
+msgctxt "selection:sale.subscription,state:"
+msgid "Draft"
+msgstr ""
+
+msgctxt "selection:sale.subscription,state:"
+msgid "Quotation"
+msgstr ""
+
+msgctxt "selection:sale.subscription,state:"
+msgid "Running"
+msgstr ""
+
+msgctxt "selection:sale.subscription.recurrence.rule,freq:"
+msgid "Daily"
+msgstr "Harian"
+
+msgctxt "selection:sale.subscription.recurrence.rule,freq:"
+msgid "Monthly"
+msgstr "Bulanan"
+
+msgctxt "selection:sale.subscription.recurrence.rule,freq:"
+msgid "Weekly"
+msgstr "Mingguan"
+
+msgctxt "selection:sale.subscription.recurrence.rule,freq:"
+msgid "Yearly"
+msgstr "Tahunan"
+
+msgctxt "view:sale.subscription.create_invoice.start:"
+msgid "Create Subscription Invoices for date"
+msgstr ""
+
+msgctxt "view:sale.subscription.line.consumption.create.start:"
+msgid "Create Subscription Line Consumptions for date"
+msgstr ""
+
+msgctxt "view:sale.subscription.line:"
+msgid "General"
+msgstr "Umum"
+
+msgctxt "view:sale.subscription:"
+msgid "Other Info"
+msgstr "Info Lain"
+
+msgctxt "view:sale.subscription:"
+msgid "Subscription"
+msgstr ""
+
+msgctxt "wizard_button:sale.subscription.create_invoice,start,create_:"
+msgid "Create"
+msgstr "Buat"
+
+msgctxt "wizard_button:sale.subscription.create_invoice,start,end:"
+msgid "Cancel"
+msgstr "Batal"
+
+msgctxt ""
+"wizard_button:sale.subscription.line.consumption.create,start,create_:"
+msgid "Create"
+msgstr "Buat"
+
+msgctxt "wizard_button:sale.subscription.line.consumption.create,start,end:"
+msgid "Cancel"
+msgstr "Batal"
diff --git a/modules/sale_subscription/locale/it.po b/modules/sale_subscription/locale/it.po
new file mode 100644
index 0000000000..9c9513fceb
--- /dev/null
+++ b/modules/sale_subscription/locale/it.po
@@ -0,0 +1,609 @@
+#
+msgid ""
+msgstr "Content-Type: text/plain; charset=utf-8\n"
+
+#, fuzzy
+msgctxt "field:sale.configuration,subscription_sequence:"
+msgid "Subscription Sequence"
+msgstr "Subscription Services"
+
+#, fuzzy
+msgctxt "field:sale.configuration.sequence,subscription_sequence:"
+msgid "Subscription Sequence"
+msgstr "Subscription Services"
+
+msgctxt "field:sale.subscription,company:"
+msgid "Company"
+msgstr "Azienda"
+
+msgctxt "field:sale.subscription,contact:"
+msgid "Contact"
+msgstr "Contatto"
+
+msgctxt "field:sale.subscription,currency:"
+msgid "Currency"
+msgstr "Valuta"
+
+msgctxt "field:sale.subscription,description:"
+msgid "Description"
+msgstr "Descrizione"
+
+msgctxt "field:sale.subscription,end_date:"
+msgid "End Date"
+msgstr "Data fine"
+
+msgctxt "field:sale.subscription,invoice_address:"
+msgid "Invoice Address"
+msgstr "Indirizzo di fatturazione"
+
+msgctxt "field:sale.subscription,invoice_party:"
+msgid "Invoice Party"
+msgstr ""
+
+msgctxt "field:sale.subscription,invoice_recurrence:"
+msgid "Invoice Recurrence"
+msgstr "Ricorrenza della fattura"
+
+msgctxt "field:sale.subscription,invoice_start_date:"
+msgid "Invoice Start Date"
+msgstr "Data inizio fatturazione"
+
+msgctxt "field:sale.subscription,lines:"
+msgid "Lines"
+msgstr "Righe"
+
+msgctxt "field:sale.subscription,next_invoice_date:"
+msgid "Next Invoice Date"
+msgstr "Data fatturazione successiva"
+
+msgctxt "field:sale.subscription,number:"
+msgid "Number"
+msgstr "Numero"
+
+msgctxt "field:sale.subscription,party:"
+msgid "Party"
+msgstr "Controparte"
+
+msgctxt "field:sale.subscription,payment_term:"
+msgid "Payment Term"
+msgstr "Termine di pagamento"
+
+#, fuzzy
+msgctxt "field:sale.subscription,quoted_by:"
+msgid "Quoted By"
+msgstr "Quote"
+
+msgctxt "field:sale.subscription,reference:"
+msgid "Reference"
+msgstr "Riferimento"
+
+msgctxt "field:sale.subscription,run_by:"
+msgid "Run By"
+msgstr ""
+
+msgctxt "field:sale.subscription,start_date:"
+msgid "Start Date"
+msgstr "Data inizio"
+
+msgctxt "field:sale.subscription,state:"
+msgid "State"
+msgstr "Stato"
+
+msgctxt "field:sale.subscription.create_invoice.start,date:"
+msgid "Date"
+msgstr "Data"
+
+#, fuzzy
+msgctxt "field:sale.subscription.line,company:"
+msgid "Company"
+msgstr "Azienda"
+
+#, fuzzy
+msgctxt "field:sale.subscription.line,consumed_until:"
+msgid "Consumed until"
+msgstr "Consumato fino"
+
+msgctxt "field:sale.subscription.line,consumption_delay:"
+msgid "Consumption Delay"
+msgstr ""
+
+msgctxt "field:sale.subscription.line,consumption_recurrence:"
+msgid "Consumption Recurrence"
+msgstr ""
+
+#, fuzzy
+msgctxt "field:sale.subscription.line,currency:"
+msgid "Currency"
+msgstr "Valuta"
+
+msgctxt "field:sale.subscription.line,description:"
+msgid "Description"
+msgstr "Descrizione"
+
+msgctxt "field:sale.subscription.line,end_date:"
+msgid "End Date"
+msgstr "Data fine"
+
+msgctxt "field:sale.subscription.line,next_consumption_date:"
+msgid "Next Consumption Date"
+msgstr ""
+
+msgctxt "field:sale.subscription.line,next_consumption_date_delayed:"
+msgid "Next Consumption Delayed"
+msgstr ""
+
+msgctxt "field:sale.subscription.line,quantity:"
+msgid "Quantity"
+msgstr "Quantità"
+
+msgctxt "field:sale.subscription.line,service:"
+msgid "Service"
+msgstr "Servizio"
+
+msgctxt "field:sale.subscription.line,service_unit_category:"
+msgid "Service Unit Category"
+msgstr ""
+
+msgctxt "field:sale.subscription.line,start_date:"
+msgid "Start Date"
+msgstr "Data inizio"
+
+#, fuzzy
+msgctxt "field:sale.subscription.line,subscription:"
+msgid "Subscription"
+msgstr "Subscription"
+
+#, fuzzy
+msgctxt "field:sale.subscription.line,subscription_end_date:"
+msgid "Subscription End Date"
+msgstr "Subscription Services"
+
+#, fuzzy
+msgctxt "field:sale.subscription.line,subscription_start_date:"
+msgid "Subscription Start Date"
+msgstr "Subscription Services"
+
+#, fuzzy
+msgctxt "field:sale.subscription.line,subscription_state:"
+msgid "Subscription State"
+msgstr "Subscription Services"
+
+msgctxt "field:sale.subscription.line,unit:"
+msgid "Unit"
+msgstr "Unità"
+
+msgctxt "field:sale.subscription.line,unit_digits:"
+msgid "Unit Digits"
+msgstr ""
+
+msgctxt "field:sale.subscription.line,unit_price:"
+msgid "Unit Price"
+msgstr ""
+
+msgctxt "field:sale.subscription.line.consumption,date:"
+msgid "Date"
+msgstr ""
+
+msgctxt "field:sale.subscription.line.consumption,invoice_line:"
+msgid "Invoice Line"
+msgstr ""
+
+msgctxt "field:sale.subscription.line.consumption,line:"
+msgid "Line"
+msgstr "Riga"
+
+msgctxt "field:sale.subscription.line.consumption,quantity:"
+msgid "Quantity"
+msgstr "Quantità"
+
+msgctxt "field:sale.subscription.line.consumption,unit_digits:"
+msgid "Unit Digits"
+msgstr ""
+
+msgctxt "field:sale.subscription.line.consumption.create.start,date:"
+msgid "Date"
+msgstr ""
+
+msgctxt "field:sale.subscription.recurrence.rule,bymonth:"
+msgid "By Month"
+msgstr ""
+
+msgctxt "field:sale.subscription.recurrence.rule,bymonthday:"
+msgid "By Month Day"
+msgstr ""
+
+msgctxt "field:sale.subscription.recurrence.rule,bysetpos:"
+msgid "By Position"
+msgstr ""
+
+msgctxt "field:sale.subscription.recurrence.rule,byweekday:"
+msgid "By Week Day"
+msgstr ""
+
+msgctxt "field:sale.subscription.recurrence.rule,byweekno:"
+msgid "By Week Number"
+msgstr ""
+
+msgctxt "field:sale.subscription.recurrence.rule,byyearday:"
+msgid "By Year Day"
+msgstr ""
+
+msgctxt "field:sale.subscription.recurrence.rule,exclusive:"
+msgid "Exclusive"
+msgstr ""
+
+msgctxt "field:sale.subscription.recurrence.rule,freq:"
+msgid "Frequency"
+msgstr ""
+
+msgctxt "field:sale.subscription.recurrence.rule,interval:"
+msgid "Interval"
+msgstr ""
+
+msgctxt "field:sale.subscription.recurrence.rule,set_:"
+msgid "Set"
+msgstr ""
+
+msgctxt "field:sale.subscription.recurrence.rule,week_start_day:"
+msgid "Week Start Day"
+msgstr ""
+
+msgctxt "field:sale.subscription.recurrence.rule.set,name:"
+msgid "Name"
+msgstr "Nome"
+
+msgctxt "field:sale.subscription.recurrence.rule.set,rules:"
+msgid "Rules"
+msgstr ""
+
+msgctxt "field:sale.subscription.service,consumption_delay:"
+msgid "Consumption Delay"
+msgstr ""
+
+msgctxt "field:sale.subscription.service,consumption_recurrence:"
+msgid "Consumption Recurrence"
+msgstr ""
+
+msgctxt "field:sale.subscription.service,product:"
+msgid "Product"
+msgstr "Prodotto"
+
+msgctxt "help:sale.subscription,company:"
+msgid "Make the subscription belong to the company."
+msgstr ""
+
+msgctxt "help:sale.subscription,number:"
+msgid "The main identification of the subscription."
+msgstr ""
+
+msgctxt "help:sale.subscription,party:"
+msgid "The party who subscribes."
+msgstr ""
+
+msgctxt "help:sale.subscription,reference:"
+msgid "The identification of an external origin."
+msgstr ""
+
+msgctxt "help:sale.subscription,state:"
+msgid "The current state of the subscription."
+msgstr ""
+
+msgctxt "help:sale.subscription.line,subscription:"
+msgid "Add the line below the subscription."
+msgstr ""
+
+msgctxt "help:sale.subscription.recurrence.rule,bymonth:"
+msgid "A comma separated list of integers."
+msgstr ""
+
+msgctxt "help:sale.subscription.recurrence.rule,bymonthday:"
+msgid "A comma separated list of integers."
+msgstr ""
+
+msgctxt "help:sale.subscription.recurrence.rule,bysetpos:"
+msgid "A comma separated list of integers."
+msgstr ""
+
+msgctxt "help:sale.subscription.recurrence.rule,byweekday:"
+msgid "A comma separated list of integers or weekday (MO, TU etc)."
+msgstr ""
+
+msgctxt "help:sale.subscription.recurrence.rule,byweekno:"
+msgid "A comma separated list of integers (ISO8601)."
+msgstr ""
+
+msgctxt "help:sale.subscription.recurrence.rule,byyearday:"
+msgid "A comma separated list of integers."
+msgstr ""
+
+msgctxt "help:sale.subscription.recurrence.rule,set_:"
+msgid "Add the rule below the set."
+msgstr ""
+
+msgctxt "help:sale.subscription.recurrence.rule.set,name:"
+msgid "The main identifier of the rule set."
+msgstr ""
+
+msgctxt "model:ir.action,name:act_create_invoice"
+msgid "Create Subscription Invoices"
+msgstr "Create Subscription Invoices"
+
+msgctxt "model:ir.action,name:act_line_consumption_create"
+msgid "Create Line Consumptions"
+msgstr "Create Line Consumptions"
+
+msgctxt "model:ir.action,name:act_recurrence_rule_set_form"
+msgid "Subscription Recurrence Rule Sets"
+msgstr "Subscription Recurrence Rule Sets"
+
+msgctxt "model:ir.action,name:act_service_form"
+msgid "Subscription Services"
+msgstr "Subscription Services"
+
+msgctxt "model:ir.action,name:act_subscription_form"
+msgid "Subscriptions"
+msgstr "Subscriptions"
+
+msgctxt "model:ir.action,name:act_subscription_invoice_relate"
+msgid "Invoices"
+msgstr ""
+
+msgctxt "model:ir.action,name:act_subscription_line_consumption_form"
+msgid "Consumptions"
+msgstr "Consumptions"
+
+msgctxt ""
+"model:ir.action,name:act_subscription_line_consumption_subscription_line_relate"
+msgid "Consumptions"
+msgstr "Consumptions"
+
+msgctxt ""
+"model:ir.action,name:act_subscription_line_consumption_subscription_relate"
+msgid "Consumptions"
+msgstr "Consumptions"
+
+msgctxt "model:ir.action,name:act_subscription_party_relate"
+msgid "Subscriptions"
+msgstr "Subscriptions"
+
+msgctxt ""
+"model:ir.action.act_window.domain,name:act_subscription_form_domain_all"
+msgid "All"
+msgstr "All"
+
+msgctxt ""
+"model:ir.action.act_window.domain,name:act_subscription_form_domain_draft"
+msgid "Draft"
+msgstr "Draft"
+
+msgctxt ""
+"model:ir.action.act_window.domain,name:act_subscription_form_domain_quotation"
+msgid "Quotation"
+msgstr "Preventivo"
+
+msgctxt ""
+"model:ir.action.act_window.domain,name:act_subscription_form_domain_running"
+msgid "Running"
+msgstr "Running"
+
+msgctxt "model:ir.message,text:msg_consumption_delete_invoiced"
+msgid "You cannot delete invoiced consumption \"%(consumption)s\"."
+msgstr ""
+
+msgctxt ""
+"model:ir.message,text:msg_consumption_invoice_missing_account_revenue"
+msgid ""
+"To invoice consumptions you must define an account revenue for product "
+"\"%(product)s\"."
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_consumption_modify_invoiced"
+msgid "You cannot modify invoiced consumption \"%(consumption)s\"."
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_consumption_recurrence_invalid"
+msgid ""
+"The consumption recurrence of line \"%(line)s\" of subscription "
+"\"%(subscription)s\" does not generate any occurrence."
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_erase_party_pending_subscription"
+msgid ""
+"You cannot erase party \"%(party)s\" while they have pending subscriptions "
+"with company \"%(company)s\"."
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_invoice_recurrence_invalid"
+msgid ""
+"The invoice recurrence of subscription \"%(subscription)s\" does not "
+"generate any occurrence."
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_recurrence_rule_invalid_by"
+msgid ""
+"Invalid \"%(field)s\" \"%(value)s\" in recurence rule "
+"\"%(recurrence_rule)s\" with exception \"%(exception)s\"."
+msgstr ""
+
+msgctxt "model:ir.model.button,string:subscription_cancel_button"
+msgid "Cancel"
+msgstr "Annulla"
+
+msgctxt "model:ir.model.button,string:subscription_draft_button"
+msgid "Draft"
+msgstr "Draft"
+
+msgctxt "model:ir.model.button,string:subscription_quote_button"
+msgid "Quote"
+msgstr "Quote"
+
+msgctxt "model:ir.model.button,string:subscription_run_button"
+msgid "Run"
+msgstr "Run"
+
+msgctxt "model:ir.rule.group,name:rule_group_subscription_companies"
+msgid "User in companies"
+msgstr ""
+
+msgctxt "model:ir.sequence,name:sequence_subscription"
+msgid "Subscription"
+msgstr "Subscription"
+
+msgctxt "model:ir.sequence.type,name:sequence_type_subscription"
+msgid "Subscription"
+msgstr "Subscription"
+
+#, fuzzy
+msgctxt "model:ir.ui.menu,name:menu_configuration"
+msgid "Subscription"
+msgstr "Subscription"
+
+msgctxt "model:ir.ui.menu,name:menu_create_invoice"
+msgid "Create Subscription Invoices"
+msgstr "Create Subscription Invoices"
+
+msgctxt "model:ir.ui.menu,name:menu_line_consumption_create"
+msgid "Create Line Consumptions"
+msgstr "Create Line Consumptions"
+
+msgctxt "model:ir.ui.menu,name:menu_recurrence_rule_set_form"
+msgid "Subscription Recurrence Rule Sets"
+msgstr "Subscription Recurrence Rule Sets"
+
+msgctxt "model:ir.ui.menu,name:menu_service_form"
+msgid "Subscription Services"
+msgstr "Subscription Services"
+
+msgctxt "model:ir.ui.menu,name:menu_subscription_form"
+msgid "Subscriptions"
+msgstr "Subscriptions"
+
+#, fuzzy
+msgctxt "model:sale.subscription,name:"
+msgid "Subscription"
+msgstr "Subscription"
+
+#, fuzzy
+msgctxt "model:sale.subscription.create_invoice.start,name:"
+msgid "Create Subscription Invoice"
+msgstr "Create Subscription Invoices"
+
+#, fuzzy
+msgctxt "model:sale.subscription.line,name:"
+msgid "Subscription Line"
+msgstr "Subscription Services"
+
+#, fuzzy
+msgctxt "model:sale.subscription.line.consumption,name:"
+msgid "Subscription Line Consumption"
+msgstr "Generate Subscription Line Consumptions"
+
+#, fuzzy
+msgctxt "model:sale.subscription.line.consumption.create.start,name:"
+msgid "Create Subscription Line Consumption"
+msgstr "Generate Subscription Line Consumptions"
+
+#, fuzzy
+msgctxt "model:sale.subscription.recurrence.rule,name:"
+msgid "Subscription Recurrence Rule"
+msgstr "Subscription Recurrence Rule Sets"
+
+#, fuzzy
+msgctxt "model:sale.subscription.recurrence.rule.set,name:"
+msgid "Subscription Recurrence Rule Set"
+msgstr "Subscription Recurrence Rule Sets"
+
+#, fuzzy
+msgctxt "model:sale.subscription.service,name:"
+msgid "Subscription Service"
+msgstr "Subscription Services"
+
+#, fuzzy
+msgctxt "selection:ir.cron,method:"
+msgid "Generate Subscription Invoices"
+msgstr "Generate Subscription Invoices"
+
+#, fuzzy
+msgctxt "selection:ir.cron,method:"
+msgid "Generate Subscription Line Consumptions"
+msgstr "Generate Subscription Line Consumptions"
+
+#, fuzzy
+msgctxt "selection:sale.subscription,state:"
+msgid "Cancelled"
+msgstr "Cancel"
+
+msgctxt "selection:sale.subscription,state:"
+msgid "Closed"
+msgstr ""
+
+#, fuzzy
+msgctxt "selection:sale.subscription,state:"
+msgid "Draft"
+msgstr "Draft"
+
+#, fuzzy
+msgctxt "selection:sale.subscription,state:"
+msgid "Quotation"
+msgstr "Quotation"
+
+#, fuzzy
+msgctxt "selection:sale.subscription,state:"
+msgid "Running"
+msgstr "Running"
+
+msgctxt "selection:sale.subscription.recurrence.rule,freq:"
+msgid "Daily"
+msgstr ""
+
+msgctxt "selection:sale.subscription.recurrence.rule,freq:"
+msgid "Monthly"
+msgstr ""
+
+msgctxt "selection:sale.subscription.recurrence.rule,freq:"
+msgid "Weekly"
+msgstr ""
+
+msgctxt "selection:sale.subscription.recurrence.rule,freq:"
+msgid "Yearly"
+msgstr ""
+
+#, fuzzy
+msgctxt "view:sale.subscription.create_invoice.start:"
+msgid "Create Subscription Invoices for date"
+msgstr "Create Subscription Invoices"
+
+#, fuzzy
+msgctxt "view:sale.subscription.line.consumption.create.start:"
+msgid "Create Subscription Line Consumptions for date"
+msgstr "Generate Subscription Line Consumptions"
+
+msgctxt "view:sale.subscription.line:"
+msgid "General"
+msgstr ""
+
+msgctxt "view:sale.subscription:"
+msgid "Other Info"
+msgstr ""
+
+#, fuzzy
+msgctxt "view:sale.subscription:"
+msgid "Subscription"
+msgstr "Subscription"
+
+msgctxt "wizard_button:sale.subscription.create_invoice,start,create_:"
+msgid "Create"
+msgstr ""
+
+msgctxt "wizard_button:sale.subscription.create_invoice,start,end:"
+msgid "Cancel"
+msgstr "Annulla"
+
+msgctxt ""
+"wizard_button:sale.subscription.line.consumption.create,start,create_:"
+msgid "Create"
+msgstr ""
+
+msgctxt "wizard_button:sale.subscription.line.consumption.create,start,end:"
+msgid "Cancel"
+msgstr "Annulla"
diff --git a/modules/sale_subscription/locale/lo.po b/modules/sale_subscription/locale/lo.po
new file mode 100644
index 0000000000..4e46c4f6c0
--- /dev/null
+++ b/modules/sale_subscription/locale/lo.po
@@ -0,0 +1,611 @@
+#
+msgid ""
+msgstr "Content-Type: text/plain; charset=utf-8\n"
+
+#, fuzzy
+msgctxt "field:sale.configuration,subscription_sequence:"
+msgid "Subscription Sequence"
+msgstr "Subscription Services"
+
+#, fuzzy
+msgctxt "field:sale.configuration.sequence,subscription_sequence:"
+msgid "Subscription Sequence"
+msgstr "Subscription Services"
+
+msgctxt "field:sale.subscription,company:"
+msgid "Company"
+msgstr ""
+
+msgctxt "field:sale.subscription,contact:"
+msgid "Contact"
+msgstr ""
+
+msgctxt "field:sale.subscription,currency:"
+msgid "Currency"
+msgstr ""
+
+#, fuzzy
+msgctxt "field:sale.subscription,description:"
+msgid "Description"
+msgstr "Subscription"
+
+msgctxt "field:sale.subscription,end_date:"
+msgid "End Date"
+msgstr ""
+
+msgctxt "field:sale.subscription,invoice_address:"
+msgid "Invoice Address"
+msgstr ""
+
+msgctxt "field:sale.subscription,invoice_party:"
+msgid "Invoice Party"
+msgstr ""
+
+msgctxt "field:sale.subscription,invoice_recurrence:"
+msgid "Invoice Recurrence"
+msgstr ""
+
+msgctxt "field:sale.subscription,invoice_start_date:"
+msgid "Invoice Start Date"
+msgstr ""
+
+msgctxt "field:sale.subscription,lines:"
+msgid "Lines"
+msgstr ""
+
+msgctxt "field:sale.subscription,next_invoice_date:"
+msgid "Next Invoice Date"
+msgstr ""
+
+msgctxt "field:sale.subscription,number:"
+msgid "Number"
+msgstr ""
+
+msgctxt "field:sale.subscription,party:"
+msgid "Party"
+msgstr ""
+
+msgctxt "field:sale.subscription,payment_term:"
+msgid "Payment Term"
+msgstr ""
+
+#, fuzzy
+msgctxt "field:sale.subscription,quoted_by:"
+msgid "Quoted By"
+msgstr "Quote"
+
+msgctxt "field:sale.subscription,reference:"
+msgid "Reference"
+msgstr ""
+
+msgctxt "field:sale.subscription,run_by:"
+msgid "Run By"
+msgstr ""
+
+msgctxt "field:sale.subscription,start_date:"
+msgid "Start Date"
+msgstr ""
+
+msgctxt "field:sale.subscription,state:"
+msgid "State"
+msgstr ""
+
+msgctxt "field:sale.subscription.create_invoice.start,date:"
+msgid "Date"
+msgstr ""
+
+msgctxt "field:sale.subscription.line,company:"
+msgid "Company"
+msgstr ""
+
+#, fuzzy
+msgctxt "field:sale.subscription.line,consumed_until:"
+msgid "Consumed until"
+msgstr "Consumptions"
+
+msgctxt "field:sale.subscription.line,consumption_delay:"
+msgid "Consumption Delay"
+msgstr ""
+
+msgctxt "field:sale.subscription.line,consumption_recurrence:"
+msgid "Consumption Recurrence"
+msgstr ""
+
+msgctxt "field:sale.subscription.line,currency:"
+msgid "Currency"
+msgstr ""
+
+#, fuzzy
+msgctxt "field:sale.subscription.line,description:"
+msgid "Description"
+msgstr "Subscription"
+
+msgctxt "field:sale.subscription.line,end_date:"
+msgid "End Date"
+msgstr ""
+
+msgctxt "field:sale.subscription.line,next_consumption_date:"
+msgid "Next Consumption Date"
+msgstr ""
+
+msgctxt "field:sale.subscription.line,next_consumption_date_delayed:"
+msgid "Next Consumption Delayed"
+msgstr ""
+
+msgctxt "field:sale.subscription.line,quantity:"
+msgid "Quantity"
+msgstr ""
+
+msgctxt "field:sale.subscription.line,service:"
+msgid "Service"
+msgstr ""
+
+msgctxt "field:sale.subscription.line,service_unit_category:"
+msgid "Service Unit Category"
+msgstr ""
+
+msgctxt "field:sale.subscription.line,start_date:"
+msgid "Start Date"
+msgstr ""
+
+#, fuzzy
+msgctxt "field:sale.subscription.line,subscription:"
+msgid "Subscription"
+msgstr "Subscription"
+
+#, fuzzy
+msgctxt "field:sale.subscription.line,subscription_end_date:"
+msgid "Subscription End Date"
+msgstr "Subscription Services"
+
+#, fuzzy
+msgctxt "field:sale.subscription.line,subscription_start_date:"
+msgid "Subscription Start Date"
+msgstr "Subscription Services"
+
+#, fuzzy
+msgctxt "field:sale.subscription.line,subscription_state:"
+msgid "Subscription State"
+msgstr "Subscription Services"
+
+msgctxt "field:sale.subscription.line,unit:"
+msgid "Unit"
+msgstr ""
+
+msgctxt "field:sale.subscription.line,unit_digits:"
+msgid "Unit Digits"
+msgstr ""
+
+msgctxt "field:sale.subscription.line,unit_price:"
+msgid "Unit Price"
+msgstr ""
+
+msgctxt "field:sale.subscription.line.consumption,date:"
+msgid "Date"
+msgstr ""
+
+msgctxt "field:sale.subscription.line.consumption,invoice_line:"
+msgid "Invoice Line"
+msgstr ""
+
+msgctxt "field:sale.subscription.line.consumption,line:"
+msgid "Line"
+msgstr ""
+
+msgctxt "field:sale.subscription.line.consumption,quantity:"
+msgid "Quantity"
+msgstr ""
+
+msgctxt "field:sale.subscription.line.consumption,unit_digits:"
+msgid "Unit Digits"
+msgstr ""
+
+msgctxt "field:sale.subscription.line.consumption.create.start,date:"
+msgid "Date"
+msgstr ""
+
+msgctxt "field:sale.subscription.recurrence.rule,bymonth:"
+msgid "By Month"
+msgstr ""
+
+msgctxt "field:sale.subscription.recurrence.rule,bymonthday:"
+msgid "By Month Day"
+msgstr ""
+
+msgctxt "field:sale.subscription.recurrence.rule,bysetpos:"
+msgid "By Position"
+msgstr ""
+
+msgctxt "field:sale.subscription.recurrence.rule,byweekday:"
+msgid "By Week Day"
+msgstr ""
+
+msgctxt "field:sale.subscription.recurrence.rule,byweekno:"
+msgid "By Week Number"
+msgstr ""
+
+msgctxt "field:sale.subscription.recurrence.rule,byyearday:"
+msgid "By Year Day"
+msgstr ""
+
+msgctxt "field:sale.subscription.recurrence.rule,exclusive:"
+msgid "Exclusive"
+msgstr ""
+
+msgctxt "field:sale.subscription.recurrence.rule,freq:"
+msgid "Frequency"
+msgstr ""
+
+msgctxt "field:sale.subscription.recurrence.rule,interval:"
+msgid "Interval"
+msgstr ""
+
+msgctxt "field:sale.subscription.recurrence.rule,set_:"
+msgid "Set"
+msgstr ""
+
+msgctxt "field:sale.subscription.recurrence.rule,week_start_day:"
+msgid "Week Start Day"
+msgstr ""
+
+msgctxt "field:sale.subscription.recurrence.rule.set,name:"
+msgid "Name"
+msgstr ""
+
+msgctxt "field:sale.subscription.recurrence.rule.set,rules:"
+msgid "Rules"
+msgstr ""
+
+msgctxt "field:sale.subscription.service,consumption_delay:"
+msgid "Consumption Delay"
+msgstr ""
+
+msgctxt "field:sale.subscription.service,consumption_recurrence:"
+msgid "Consumption Recurrence"
+msgstr ""
+
+msgctxt "field:sale.subscription.service,product:"
+msgid "Product"
+msgstr ""
+
+msgctxt "help:sale.subscription,company:"
+msgid "Make the subscription belong to the company."
+msgstr ""
+
+msgctxt "help:sale.subscription,number:"
+msgid "The main identification of the subscription."
+msgstr ""
+
+msgctxt "help:sale.subscription,party:"
+msgid "The party who subscribes."
+msgstr ""
+
+msgctxt "help:sale.subscription,reference:"
+msgid "The identification of an external origin."
+msgstr ""
+
+msgctxt "help:sale.subscription,state:"
+msgid "The current state of the subscription."
+msgstr ""
+
+msgctxt "help:sale.subscription.line,subscription:"
+msgid "Add the line below the subscription."
+msgstr ""
+
+msgctxt "help:sale.subscription.recurrence.rule,bymonth:"
+msgid "A comma separated list of integers."
+msgstr ""
+
+msgctxt "help:sale.subscription.recurrence.rule,bymonthday:"
+msgid "A comma separated list of integers."
+msgstr ""
+
+msgctxt "help:sale.subscription.recurrence.rule,bysetpos:"
+msgid "A comma separated list of integers."
+msgstr ""
+
+msgctxt "help:sale.subscription.recurrence.rule,byweekday:"
+msgid "A comma separated list of integers or weekday (MO, TU etc)."
+msgstr ""
+
+msgctxt "help:sale.subscription.recurrence.rule,byweekno:"
+msgid "A comma separated list of integers (ISO8601)."
+msgstr ""
+
+msgctxt "help:sale.subscription.recurrence.rule,byyearday:"
+msgid "A comma separated list of integers."
+msgstr ""
+
+msgctxt "help:sale.subscription.recurrence.rule,set_:"
+msgid "Add the rule below the set."
+msgstr ""
+
+msgctxt "help:sale.subscription.recurrence.rule.set,name:"
+msgid "The main identifier of the rule set."
+msgstr ""
+
+msgctxt "model:ir.action,name:act_create_invoice"
+msgid "Create Subscription Invoices"
+msgstr "Create Subscription Invoices"
+
+msgctxt "model:ir.action,name:act_line_consumption_create"
+msgid "Create Line Consumptions"
+msgstr "Create Line Consumptions"
+
+msgctxt "model:ir.action,name:act_recurrence_rule_set_form"
+msgid "Subscription Recurrence Rule Sets"
+msgstr "Subscription Recurrence Rule Sets"
+
+msgctxt "model:ir.action,name:act_service_form"
+msgid "Subscription Services"
+msgstr "Subscription Services"
+
+msgctxt "model:ir.action,name:act_subscription_form"
+msgid "Subscriptions"
+msgstr "Subscriptions"
+
+msgctxt "model:ir.action,name:act_subscription_invoice_relate"
+msgid "Invoices"
+msgstr ""
+
+msgctxt "model:ir.action,name:act_subscription_line_consumption_form"
+msgid "Consumptions"
+msgstr "Consumptions"
+
+msgctxt ""
+"model:ir.action,name:act_subscription_line_consumption_subscription_line_relate"
+msgid "Consumptions"
+msgstr "Consumptions"
+
+msgctxt ""
+"model:ir.action,name:act_subscription_line_consumption_subscription_relate"
+msgid "Consumptions"
+msgstr "Consumptions"
+
+msgctxt "model:ir.action,name:act_subscription_party_relate"
+msgid "Subscriptions"
+msgstr "Subscriptions"
+
+msgctxt ""
+"model:ir.action.act_window.domain,name:act_subscription_form_domain_all"
+msgid "All"
+msgstr "All"
+
+msgctxt ""
+"model:ir.action.act_window.domain,name:act_subscription_form_domain_draft"
+msgid "Draft"
+msgstr "Draft"
+
+msgctxt ""
+"model:ir.action.act_window.domain,name:act_subscription_form_domain_quotation"
+msgid "Quotation"
+msgstr "Quotation"
+
+msgctxt ""
+"model:ir.action.act_window.domain,name:act_subscription_form_domain_running"
+msgid "Running"
+msgstr "Running"
+
+msgctxt "model:ir.message,text:msg_consumption_delete_invoiced"
+msgid "You cannot delete invoiced consumption \"%(consumption)s\"."
+msgstr ""
+
+msgctxt ""
+"model:ir.message,text:msg_consumption_invoice_missing_account_revenue"
+msgid ""
+"To invoice consumptions you must define an account revenue for product "
+"\"%(product)s\"."
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_consumption_modify_invoiced"
+msgid "You cannot modify invoiced consumption \"%(consumption)s\"."
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_consumption_recurrence_invalid"
+msgid ""
+"The consumption recurrence of line \"%(line)s\" of subscription "
+"\"%(subscription)s\" does not generate any occurrence."
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_erase_party_pending_subscription"
+msgid ""
+"You cannot erase party \"%(party)s\" while they have pending subscriptions "
+"with company \"%(company)s\"."
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_invoice_recurrence_invalid"
+msgid ""
+"The invoice recurrence of subscription \"%(subscription)s\" does not "
+"generate any occurrence."
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_recurrence_rule_invalid_by"
+msgid ""
+"Invalid \"%(field)s\" \"%(value)s\" in recurence rule "
+"\"%(recurrence_rule)s\" with exception \"%(exception)s\"."
+msgstr ""
+
+msgctxt "model:ir.model.button,string:subscription_cancel_button"
+msgid "Cancel"
+msgstr "Cancel"
+
+msgctxt "model:ir.model.button,string:subscription_draft_button"
+msgid "Draft"
+msgstr "Draft"
+
+msgctxt "model:ir.model.button,string:subscription_quote_button"
+msgid "Quote"
+msgstr "Quote"
+
+msgctxt "model:ir.model.button,string:subscription_run_button"
+msgid "Run"
+msgstr "Run"
+
+msgctxt "model:ir.rule.group,name:rule_group_subscription_companies"
+msgid "User in companies"
+msgstr ""
+
+msgctxt "model:ir.sequence,name:sequence_subscription"
+msgid "Subscription"
+msgstr "Subscription"
+
+msgctxt "model:ir.sequence.type,name:sequence_type_subscription"
+msgid "Subscription"
+msgstr "Subscription"
+
+#, fuzzy
+msgctxt "model:ir.ui.menu,name:menu_configuration"
+msgid "Subscription"
+msgstr "Subscription"
+
+msgctxt "model:ir.ui.menu,name:menu_create_invoice"
+msgid "Create Subscription Invoices"
+msgstr "Create Subscription Invoices"
+
+msgctxt "model:ir.ui.menu,name:menu_line_consumption_create"
+msgid "Create Line Consumptions"
+msgstr "Create Line Consumptions"
+
+msgctxt "model:ir.ui.menu,name:menu_recurrence_rule_set_form"
+msgid "Subscription Recurrence Rule Sets"
+msgstr "Subscription Recurrence Rule Sets"
+
+msgctxt "model:ir.ui.menu,name:menu_service_form"
+msgid "Subscription Services"
+msgstr "Subscription Services"
+
+msgctxt "model:ir.ui.menu,name:menu_subscription_form"
+msgid "Subscriptions"
+msgstr "Subscriptions"
+
+#, fuzzy
+msgctxt "model:sale.subscription,name:"
+msgid "Subscription"
+msgstr "Subscription"
+
+#, fuzzy
+msgctxt "model:sale.subscription.create_invoice.start,name:"
+msgid "Create Subscription Invoice"
+msgstr "Create Subscription Invoices"
+
+#, fuzzy
+msgctxt "model:sale.subscription.line,name:"
+msgid "Subscription Line"
+msgstr "Subscription Services"
+
+#, fuzzy
+msgctxt "model:sale.subscription.line.consumption,name:"
+msgid "Subscription Line Consumption"
+msgstr "Generate Subscription Line Consumptions"
+
+#, fuzzy
+msgctxt "model:sale.subscription.line.consumption.create.start,name:"
+msgid "Create Subscription Line Consumption"
+msgstr "Generate Subscription Line Consumptions"
+
+#, fuzzy
+msgctxt "model:sale.subscription.recurrence.rule,name:"
+msgid "Subscription Recurrence Rule"
+msgstr "Subscription Recurrence Rule Sets"
+
+#, fuzzy
+msgctxt "model:sale.subscription.recurrence.rule.set,name:"
+msgid "Subscription Recurrence Rule Set"
+msgstr "Subscription Recurrence Rule Sets"
+
+#, fuzzy
+msgctxt "model:sale.subscription.service,name:"
+msgid "Subscription Service"
+msgstr "Subscription Services"
+
+#, fuzzy
+msgctxt "selection:ir.cron,method:"
+msgid "Generate Subscription Invoices"
+msgstr "Generate Subscription Invoices"
+
+#, fuzzy
+msgctxt "selection:ir.cron,method:"
+msgid "Generate Subscription Line Consumptions"
+msgstr "Generate Subscription Line Consumptions"
+
+#, fuzzy
+msgctxt "selection:sale.subscription,state:"
+msgid "Cancelled"
+msgstr "Cancel"
+
+msgctxt "selection:sale.subscription,state:"
+msgid "Closed"
+msgstr ""
+
+#, fuzzy
+msgctxt "selection:sale.subscription,state:"
+msgid "Draft"
+msgstr "Draft"
+
+#, fuzzy
+msgctxt "selection:sale.subscription,state:"
+msgid "Quotation"
+msgstr "Quotation"
+
+#, fuzzy
+msgctxt "selection:sale.subscription,state:"
+msgid "Running"
+msgstr "Running"
+
+msgctxt "selection:sale.subscription.recurrence.rule,freq:"
+msgid "Daily"
+msgstr ""
+
+msgctxt "selection:sale.subscription.recurrence.rule,freq:"
+msgid "Monthly"
+msgstr ""
+
+msgctxt "selection:sale.subscription.recurrence.rule,freq:"
+msgid "Weekly"
+msgstr ""
+
+msgctxt "selection:sale.subscription.recurrence.rule,freq:"
+msgid "Yearly"
+msgstr ""
+
+#, fuzzy
+msgctxt "view:sale.subscription.create_invoice.start:"
+msgid "Create Subscription Invoices for date"
+msgstr "Create Subscription Invoices"
+
+#, fuzzy
+msgctxt "view:sale.subscription.line.consumption.create.start:"
+msgid "Create Subscription Line Consumptions for date"
+msgstr "Generate Subscription Line Consumptions"
+
+msgctxt "view:sale.subscription.line:"
+msgid "General"
+msgstr ""
+
+msgctxt "view:sale.subscription:"
+msgid "Other Info"
+msgstr ""
+
+#, fuzzy
+msgctxt "view:sale.subscription:"
+msgid "Subscription"
+msgstr "Subscription"
+
+msgctxt "wizard_button:sale.subscription.create_invoice,start,create_:"
+msgid "Create"
+msgstr ""
+
+#, fuzzy
+msgctxt "wizard_button:sale.subscription.create_invoice,start,end:"
+msgid "Cancel"
+msgstr "Cancel"
+
+msgctxt ""
+"wizard_button:sale.subscription.line.consumption.create,start,create_:"
+msgid "Create"
+msgstr ""
+
+#, fuzzy
+msgctxt "wizard_button:sale.subscription.line.consumption.create,start,end:"
+msgid "Cancel"
+msgstr "Cancel"
diff --git a/modules/sale_subscription/locale/lt.po b/modules/sale_subscription/locale/lt.po
new file mode 100644
index 0000000000..89aeafa3e7
--- /dev/null
+++ b/modules/sale_subscription/locale/lt.po
@@ -0,0 +1,613 @@
+#
+msgid ""
+msgstr "Content-Type: text/plain; charset=utf-8\n"
+
+#, fuzzy
+msgctxt "field:sale.configuration,subscription_sequence:"
+msgid "Subscription Sequence"
+msgstr "Subscription Services"
+
+#, fuzzy
+msgctxt "field:sale.configuration.sequence,subscription_sequence:"
+msgid "Subscription Sequence"
+msgstr "Subscription Services"
+
+msgctxt "field:sale.subscription,company:"
+msgid "Company"
+msgstr "Organizacija"
+
+msgctxt "field:sale.subscription,contact:"
+msgid "Contact"
+msgstr ""
+
+msgctxt "field:sale.subscription,currency:"
+msgid "Currency"
+msgstr "Valiuta"
+
+#, fuzzy
+msgctxt "field:sale.subscription,description:"
+msgid "Description"
+msgstr "Subscription"
+
+msgctxt "field:sale.subscription,end_date:"
+msgid "End Date"
+msgstr "Pabaigos data"
+
+msgctxt "field:sale.subscription,invoice_address:"
+msgid "Invoice Address"
+msgstr "Juridinis adresas"
+
+#, fuzzy
+msgctxt "field:sale.subscription,invoice_party:"
+msgid "Invoice Party"
+msgstr "Sąskaitos faktūros"
+
+msgctxt "field:sale.subscription,invoice_recurrence:"
+msgid "Invoice Recurrence"
+msgstr "Pasikartojanti sąskaita faktūra"
+
+msgctxt "field:sale.subscription,invoice_start_date:"
+msgid "Invoice Start Date"
+msgstr ""
+
+msgctxt "field:sale.subscription,lines:"
+msgid "Lines"
+msgstr ""
+
+msgctxt "field:sale.subscription,next_invoice_date:"
+msgid "Next Invoice Date"
+msgstr ""
+
+msgctxt "field:sale.subscription,number:"
+msgid "Number"
+msgstr ""
+
+msgctxt "field:sale.subscription,party:"
+msgid "Party"
+msgstr "Kontrahentas"
+
+msgctxt "field:sale.subscription,payment_term:"
+msgid "Payment Term"
+msgstr ""
+
+#, fuzzy
+msgctxt "field:sale.subscription,quoted_by:"
+msgid "Quoted By"
+msgstr "Quote"
+
+msgctxt "field:sale.subscription,reference:"
+msgid "Reference"
+msgstr ""
+
+msgctxt "field:sale.subscription,run_by:"
+msgid "Run By"
+msgstr ""
+
+msgctxt "field:sale.subscription,start_date:"
+msgid "Start Date"
+msgstr "Pradžios data"
+
+msgctxt "field:sale.subscription,state:"
+msgid "State"
+msgstr ""
+
+msgctxt "field:sale.subscription.create_invoice.start,date:"
+msgid "Date"
+msgstr ""
+
+#, fuzzy
+msgctxt "field:sale.subscription.line,company:"
+msgid "Company"
+msgstr "Organizacija"
+
+#, fuzzy
+msgctxt "field:sale.subscription.line,consumed_until:"
+msgid "Consumed until"
+msgstr "Consumptions"
+
+msgctxt "field:sale.subscription.line,consumption_delay:"
+msgid "Consumption Delay"
+msgstr ""
+
+msgctxt "field:sale.subscription.line,consumption_recurrence:"
+msgid "Consumption Recurrence"
+msgstr ""
+
+#, fuzzy
+msgctxt "field:sale.subscription.line,currency:"
+msgid "Currency"
+msgstr "Valiuta"
+
+#, fuzzy
+msgctxt "field:sale.subscription.line,description:"
+msgid "Description"
+msgstr "Subscription"
+
+msgctxt "field:sale.subscription.line,end_date:"
+msgid "End Date"
+msgstr "Pabaigos data"
+
+msgctxt "field:sale.subscription.line,next_consumption_date:"
+msgid "Next Consumption Date"
+msgstr ""
+
+msgctxt "field:sale.subscription.line,next_consumption_date_delayed:"
+msgid "Next Consumption Delayed"
+msgstr ""
+
+msgctxt "field:sale.subscription.line,quantity:"
+msgid "Quantity"
+msgstr ""
+
+msgctxt "field:sale.subscription.line,service:"
+msgid "Service"
+msgstr ""
+
+msgctxt "field:sale.subscription.line,service_unit_category:"
+msgid "Service Unit Category"
+msgstr ""
+
+msgctxt "field:sale.subscription.line,start_date:"
+msgid "Start Date"
+msgstr "Pradžios data"
+
+#, fuzzy
+msgctxt "field:sale.subscription.line,subscription:"
+msgid "Subscription"
+msgstr "Subscription"
+
+#, fuzzy
+msgctxt "field:sale.subscription.line,subscription_end_date:"
+msgid "Subscription End Date"
+msgstr "Subscription Services"
+
+msgctxt "field:sale.subscription.line,subscription_start_date:"
+msgid "Subscription Start Date"
+msgstr "Prenumeratos pradžios data"
+
+#, fuzzy
+msgctxt "field:sale.subscription.line,subscription_state:"
+msgid "Subscription State"
+msgstr "Subscription Services"
+
+msgctxt "field:sale.subscription.line,unit:"
+msgid "Unit"
+msgstr ""
+
+msgctxt "field:sale.subscription.line,unit_digits:"
+msgid "Unit Digits"
+msgstr ""
+
+msgctxt "field:sale.subscription.line,unit_price:"
+msgid "Unit Price"
+msgstr ""
+
+msgctxt "field:sale.subscription.line.consumption,date:"
+msgid "Date"
+msgstr ""
+
+msgctxt "field:sale.subscription.line.consumption,invoice_line:"
+msgid "Invoice Line"
+msgstr "Sąskaitos faktūros eilutė"
+
+msgctxt "field:sale.subscription.line.consumption,line:"
+msgid "Line"
+msgstr ""
+
+msgctxt "field:sale.subscription.line.consumption,quantity:"
+msgid "Quantity"
+msgstr ""
+
+msgctxt "field:sale.subscription.line.consumption,unit_digits:"
+msgid "Unit Digits"
+msgstr ""
+
+msgctxt "field:sale.subscription.line.consumption.create.start,date:"
+msgid "Date"
+msgstr ""
+
+msgctxt "field:sale.subscription.recurrence.rule,bymonth:"
+msgid "By Month"
+msgstr ""
+
+msgctxt "field:sale.subscription.recurrence.rule,bymonthday:"
+msgid "By Month Day"
+msgstr ""
+
+msgctxt "field:sale.subscription.recurrence.rule,bysetpos:"
+msgid "By Position"
+msgstr ""
+
+msgctxt "field:sale.subscription.recurrence.rule,byweekday:"
+msgid "By Week Day"
+msgstr ""
+
+msgctxt "field:sale.subscription.recurrence.rule,byweekno:"
+msgid "By Week Number"
+msgstr ""
+
+msgctxt "field:sale.subscription.recurrence.rule,byyearday:"
+msgid "By Year Day"
+msgstr ""
+
+msgctxt "field:sale.subscription.recurrence.rule,exclusive:"
+msgid "Exclusive"
+msgstr ""
+
+msgctxt "field:sale.subscription.recurrence.rule,freq:"
+msgid "Frequency"
+msgstr ""
+
+msgctxt "field:sale.subscription.recurrence.rule,interval:"
+msgid "Interval"
+msgstr ""
+
+msgctxt "field:sale.subscription.recurrence.rule,set_:"
+msgid "Set"
+msgstr ""
+
+msgctxt "field:sale.subscription.recurrence.rule,week_start_day:"
+msgid "Week Start Day"
+msgstr ""
+
+msgctxt "field:sale.subscription.recurrence.rule.set,name:"
+msgid "Name"
+msgstr ""
+
+msgctxt "field:sale.subscription.recurrence.rule.set,rules:"
+msgid "Rules"
+msgstr ""
+
+msgctxt "field:sale.subscription.service,consumption_delay:"
+msgid "Consumption Delay"
+msgstr ""
+
+msgctxt "field:sale.subscription.service,consumption_recurrence:"
+msgid "Consumption Recurrence"
+msgstr ""
+
+msgctxt "field:sale.subscription.service,product:"
+msgid "Product"
+msgstr ""
+
+msgctxt "help:sale.subscription,company:"
+msgid "Make the subscription belong to the company."
+msgstr ""
+
+msgctxt "help:sale.subscription,number:"
+msgid "The main identification of the subscription."
+msgstr ""
+
+msgctxt "help:sale.subscription,party:"
+msgid "The party who subscribes."
+msgstr ""
+
+msgctxt "help:sale.subscription,reference:"
+msgid "The identification of an external origin."
+msgstr ""
+
+msgctxt "help:sale.subscription,state:"
+msgid "The current state of the subscription."
+msgstr ""
+
+msgctxt "help:sale.subscription.line,subscription:"
+msgid "Add the line below the subscription."
+msgstr ""
+
+msgctxt "help:sale.subscription.recurrence.rule,bymonth:"
+msgid "A comma separated list of integers."
+msgstr ""
+
+msgctxt "help:sale.subscription.recurrence.rule,bymonthday:"
+msgid "A comma separated list of integers."
+msgstr ""
+
+msgctxt "help:sale.subscription.recurrence.rule,bysetpos:"
+msgid "A comma separated list of integers."
+msgstr ""
+
+msgctxt "help:sale.subscription.recurrence.rule,byweekday:"
+msgid "A comma separated list of integers or weekday (MO, TU etc)."
+msgstr ""
+
+msgctxt "help:sale.subscription.recurrence.rule,byweekno:"
+msgid "A comma separated list of integers (ISO8601)."
+msgstr ""
+
+msgctxt "help:sale.subscription.recurrence.rule,byyearday:"
+msgid "A comma separated list of integers."
+msgstr ""
+
+msgctxt "help:sale.subscription.recurrence.rule,set_:"
+msgid "Add the rule below the set."
+msgstr ""
+
+msgctxt "help:sale.subscription.recurrence.rule.set,name:"
+msgid "The main identifier of the rule set."
+msgstr ""
+
+msgctxt "model:ir.action,name:act_create_invoice"
+msgid "Create Subscription Invoices"
+msgstr "Create Subscription Invoices"
+
+msgctxt "model:ir.action,name:act_line_consumption_create"
+msgid "Create Line Consumptions"
+msgstr "Create Line Consumptions"
+
+msgctxt "model:ir.action,name:act_recurrence_rule_set_form"
+msgid "Subscription Recurrence Rule Sets"
+msgstr "Subscription Recurrence Rule Sets"
+
+msgctxt "model:ir.action,name:act_service_form"
+msgid "Subscription Services"
+msgstr "Subscription Services"
+
+msgctxt "model:ir.action,name:act_subscription_form"
+msgid "Subscriptions"
+msgstr "Subscriptions"
+
+msgctxt "model:ir.action,name:act_subscription_invoice_relate"
+msgid "Invoices"
+msgstr "Sąskaitos faktūros"
+
+msgctxt "model:ir.action,name:act_subscription_line_consumption_form"
+msgid "Consumptions"
+msgstr "Consumptions"
+
+msgctxt ""
+"model:ir.action,name:act_subscription_line_consumption_subscription_line_relate"
+msgid "Consumptions"
+msgstr "Consumptions"
+
+msgctxt ""
+"model:ir.action,name:act_subscription_line_consumption_subscription_relate"
+msgid "Consumptions"
+msgstr "Consumptions"
+
+msgctxt "model:ir.action,name:act_subscription_party_relate"
+msgid "Subscriptions"
+msgstr "Subscriptions"
+
+msgctxt ""
+"model:ir.action.act_window.domain,name:act_subscription_form_domain_all"
+msgid "All"
+msgstr "All"
+
+msgctxt ""
+"model:ir.action.act_window.domain,name:act_subscription_form_domain_draft"
+msgid "Draft"
+msgstr "Draft"
+
+msgctxt ""
+"model:ir.action.act_window.domain,name:act_subscription_form_domain_quotation"
+msgid "Quotation"
+msgstr "Quotation"
+
+msgctxt ""
+"model:ir.action.act_window.domain,name:act_subscription_form_domain_running"
+msgid "Running"
+msgstr "Running"
+
+msgctxt "model:ir.message,text:msg_consumption_delete_invoiced"
+msgid "You cannot delete invoiced consumption \"%(consumption)s\"."
+msgstr ""
+
+msgctxt ""
+"model:ir.message,text:msg_consumption_invoice_missing_account_revenue"
+msgid ""
+"To invoice consumptions you must define an account revenue for product "
+"\"%(product)s\"."
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_consumption_modify_invoiced"
+msgid "You cannot modify invoiced consumption \"%(consumption)s\"."
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_consumption_recurrence_invalid"
+msgid ""
+"The consumption recurrence of line \"%(line)s\" of subscription "
+"\"%(subscription)s\" does not generate any occurrence."
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_erase_party_pending_subscription"
+msgid ""
+"You cannot erase party \"%(party)s\" while they have pending subscriptions "
+"with company \"%(company)s\"."
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_invoice_recurrence_invalid"
+msgid ""
+"The invoice recurrence of subscription \"%(subscription)s\" does not "
+"generate any occurrence."
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_recurrence_rule_invalid_by"
+msgid ""
+"Invalid \"%(field)s\" \"%(value)s\" in recurence rule "
+"\"%(recurrence_rule)s\" with exception \"%(exception)s\"."
+msgstr ""
+
+msgctxt "model:ir.model.button,string:subscription_cancel_button"
+msgid "Cancel"
+msgstr "Cancel"
+
+msgctxt "model:ir.model.button,string:subscription_draft_button"
+msgid "Draft"
+msgstr "Draft"
+
+msgctxt "model:ir.model.button,string:subscription_quote_button"
+msgid "Quote"
+msgstr "Quote"
+
+msgctxt "model:ir.model.button,string:subscription_run_button"
+msgid "Run"
+msgstr "Run"
+
+msgctxt "model:ir.rule.group,name:rule_group_subscription_companies"
+msgid "User in companies"
+msgstr ""
+
+msgctxt "model:ir.sequence,name:sequence_subscription"
+msgid "Subscription"
+msgstr "Subscription"
+
+msgctxt "model:ir.sequence.type,name:sequence_type_subscription"
+msgid "Subscription"
+msgstr "Subscription"
+
+#, fuzzy
+msgctxt "model:ir.ui.menu,name:menu_configuration"
+msgid "Subscription"
+msgstr "Subscription"
+
+msgctxt "model:ir.ui.menu,name:menu_create_invoice"
+msgid "Create Subscription Invoices"
+msgstr "Create Subscription Invoices"
+
+msgctxt "model:ir.ui.menu,name:menu_line_consumption_create"
+msgid "Create Line Consumptions"
+msgstr "Create Line Consumptions"
+
+msgctxt "model:ir.ui.menu,name:menu_recurrence_rule_set_form"
+msgid "Subscription Recurrence Rule Sets"
+msgstr "Subscription Recurrence Rule Sets"
+
+msgctxt "model:ir.ui.menu,name:menu_service_form"
+msgid "Subscription Services"
+msgstr "Subscription Services"
+
+msgctxt "model:ir.ui.menu,name:menu_subscription_form"
+msgid "Subscriptions"
+msgstr "Subscriptions"
+
+#, fuzzy
+msgctxt "model:sale.subscription,name:"
+msgid "Subscription"
+msgstr "Subscription"
+
+#, fuzzy
+msgctxt "model:sale.subscription.create_invoice.start,name:"
+msgid "Create Subscription Invoice"
+msgstr "Create Subscription Invoices"
+
+#, fuzzy
+msgctxt "model:sale.subscription.line,name:"
+msgid "Subscription Line"
+msgstr "Subscription Services"
+
+#, fuzzy
+msgctxt "model:sale.subscription.line.consumption,name:"
+msgid "Subscription Line Consumption"
+msgstr "Generate Subscription Line Consumptions"
+
+#, fuzzy
+msgctxt "model:sale.subscription.line.consumption.create.start,name:"
+msgid "Create Subscription Line Consumption"
+msgstr "Generate Subscription Line Consumptions"
+
+#, fuzzy
+msgctxt "model:sale.subscription.recurrence.rule,name:"
+msgid "Subscription Recurrence Rule"
+msgstr "Subscription Recurrence Rule Sets"
+
+#, fuzzy
+msgctxt "model:sale.subscription.recurrence.rule.set,name:"
+msgid "Subscription Recurrence Rule Set"
+msgstr "Subscription Recurrence Rule Sets"
+
+#, fuzzy
+msgctxt "model:sale.subscription.service,name:"
+msgid "Subscription Service"
+msgstr "Subscription Services"
+
+#, fuzzy
+msgctxt "selection:ir.cron,method:"
+msgid "Generate Subscription Invoices"
+msgstr "Generate Subscription Invoices"
+
+#, fuzzy
+msgctxt "selection:ir.cron,method:"
+msgid "Generate Subscription Line Consumptions"
+msgstr "Generate Subscription Line Consumptions"
+
+#, fuzzy
+msgctxt "selection:sale.subscription,state:"
+msgid "Cancelled"
+msgstr "Cancel"
+
+msgctxt "selection:sale.subscription,state:"
+msgid "Closed"
+msgstr ""
+
+#, fuzzy
+msgctxt "selection:sale.subscription,state:"
+msgid "Draft"
+msgstr "Draft"
+
+#, fuzzy
+msgctxt "selection:sale.subscription,state:"
+msgid "Quotation"
+msgstr "Quotation"
+
+#, fuzzy
+msgctxt "selection:sale.subscription,state:"
+msgid "Running"
+msgstr "Running"
+
+msgctxt "selection:sale.subscription.recurrence.rule,freq:"
+msgid "Daily"
+msgstr ""
+
+msgctxt "selection:sale.subscription.recurrence.rule,freq:"
+msgid "Monthly"
+msgstr ""
+
+msgctxt "selection:sale.subscription.recurrence.rule,freq:"
+msgid "Weekly"
+msgstr ""
+
+msgctxt "selection:sale.subscription.recurrence.rule,freq:"
+msgid "Yearly"
+msgstr ""
+
+#, fuzzy
+msgctxt "view:sale.subscription.create_invoice.start:"
+msgid "Create Subscription Invoices for date"
+msgstr "Create Subscription Invoices"
+
+#, fuzzy
+msgctxt "view:sale.subscription.line.consumption.create.start:"
+msgid "Create Subscription Line Consumptions for date"
+msgstr "Generate Subscription Line Consumptions"
+
+msgctxt "view:sale.subscription.line:"
+msgid "General"
+msgstr ""
+
+msgctxt "view:sale.subscription:"
+msgid "Other Info"
+msgstr ""
+
+#, fuzzy
+msgctxt "view:sale.subscription:"
+msgid "Subscription"
+msgstr "Subscription"
+
+msgctxt "wizard_button:sale.subscription.create_invoice,start,create_:"
+msgid "Create"
+msgstr ""
+
+#, fuzzy
+msgctxt "wizard_button:sale.subscription.create_invoice,start,end:"
+msgid "Cancel"
+msgstr "Cancel"
+
+msgctxt ""
+"wizard_button:sale.subscription.line.consumption.create,start,create_:"
+msgid "Create"
+msgstr ""
+
+#, fuzzy
+msgctxt "wizard_button:sale.subscription.line.consumption.create,start,end:"
+msgid "Cancel"
+msgstr "Cancel"
diff --git a/modules/sale_subscription/locale/nl.po b/modules/sale_subscription/locale/nl.po
new file mode 100644
index 0000000000..3fed6acb94
--- /dev/null
+++ b/modules/sale_subscription/locale/nl.po
@@ -0,0 +1,590 @@
+#
+msgid ""
+msgstr "Content-Type: text/plain; charset=utf-8\n"
+
+msgctxt "field:sale.configuration,subscription_sequence:"
+msgid "Subscription Sequence"
+msgstr "Abonnementsvolgorde"
+
+msgctxt "field:sale.configuration.sequence,subscription_sequence:"
+msgid "Subscription Sequence"
+msgstr "Abonnementsvolgorde"
+
+msgctxt "field:sale.subscription,company:"
+msgid "Company"
+msgstr "Bedrijf"
+
+msgctxt "field:sale.subscription,contact:"
+msgid "Contact"
+msgstr "Contact"
+
+msgctxt "field:sale.subscription,currency:"
+msgid "Currency"
+msgstr "Valuta"
+
+msgctxt "field:sale.subscription,description:"
+msgid "Description"
+msgstr "Omschrijving"
+
+msgctxt "field:sale.subscription,end_date:"
+msgid "End Date"
+msgstr "Eind datum"
+
+msgctxt "field:sale.subscription,invoice_address:"
+msgid "Invoice Address"
+msgstr "Factuuradres"
+
+msgctxt "field:sale.subscription,invoice_party:"
+msgid "Invoice Party"
+msgstr "Factuur relatie (Invoice Party)"
+
+msgctxt "field:sale.subscription,invoice_recurrence:"
+msgid "Invoice Recurrence"
+msgstr "Factuurherhaling"
+
+msgctxt "field:sale.subscription,invoice_start_date:"
+msgid "Invoice Start Date"
+msgstr "startdatum facturatie"
+
+msgctxt "field:sale.subscription,lines:"
+msgid "Lines"
+msgstr "Regels"
+
+msgctxt "field:sale.subscription,next_invoice_date:"
+msgid "Next Invoice Date"
+msgstr "volgende facturatie datum"
+
+msgctxt "field:sale.subscription,number:"
+msgid "Number"
+msgstr "Nummer"
+
+msgctxt "field:sale.subscription,party:"
+msgid "Party"
+msgstr "Relaties"
+
+msgctxt "field:sale.subscription,payment_term:"
+msgid "Payment Term"
+msgstr "Betalingstermijn"
+
+msgctxt "field:sale.subscription,quoted_by:"
+msgid "Quoted By"
+msgstr "Offerte gemaakt door"
+
+msgctxt "field:sale.subscription,reference:"
+msgid "Reference"
+msgstr "Referentie"
+
+msgctxt "field:sale.subscription,run_by:"
+msgid "Run By"
+msgstr "Uitgevoerd door"
+
+msgctxt "field:sale.subscription,start_date:"
+msgid "Start Date"
+msgstr "Start datum"
+
+msgctxt "field:sale.subscription,state:"
+msgid "State"
+msgstr "Status"
+
+msgctxt "field:sale.subscription.create_invoice.start,date:"
+msgid "Date"
+msgstr "datum"
+
+msgctxt "field:sale.subscription.line,company:"
+msgid "Company"
+msgstr "Bedrijf"
+
+msgctxt "field:sale.subscription.line,consumed_until:"
+msgid "Consumed until"
+msgstr "Verbruikt tot"
+
+msgctxt "field:sale.subscription.line,consumption_delay:"
+msgid "Consumption Delay"
+msgstr "Houdbaarheid"
+
+msgctxt "field:sale.subscription.line,consumption_recurrence:"
+msgid "Consumption Recurrence"
+msgstr "wederkerend verbruik"
+
+msgctxt "field:sale.subscription.line,currency:"
+msgid "Currency"
+msgstr "Valuta"
+
+msgctxt "field:sale.subscription.line,description:"
+msgid "Description"
+msgstr "Omschrijving"
+
+msgctxt "field:sale.subscription.line,end_date:"
+msgid "End Date"
+msgstr "Eind datum"
+
+msgctxt "field:sale.subscription.line,next_consumption_date:"
+msgid "Next Consumption Date"
+msgstr "Volgende verbruiksdatum"
+
+msgctxt "field:sale.subscription.line,next_consumption_date_delayed:"
+msgid "Next Consumption Delayed"
+msgstr "Volgende uitgestelde verbruiksdatum"
+
+msgctxt "field:sale.subscription.line,quantity:"
+msgid "Quantity"
+msgstr "Hoeveelheid"
+
+msgctxt "field:sale.subscription.line,service:"
+msgid "Service"
+msgstr "Dienst"
+
+msgctxt "field:sale.subscription.line,service_unit_category:"
+msgid "Service Unit Category"
+msgstr "Dienst eenheid categorie"
+
+msgctxt "field:sale.subscription.line,start_date:"
+msgid "Start Date"
+msgstr "Start datum"
+
+msgctxt "field:sale.subscription.line,subscription:"
+msgid "Subscription"
+msgstr "Abonnement"
+
+msgctxt "field:sale.subscription.line,subscription_end_date:"
+msgid "Subscription End Date"
+msgstr "Einddatum abonnement"
+
+msgctxt "field:sale.subscription.line,subscription_start_date:"
+msgid "Subscription Start Date"
+msgstr "Begindatum abonnement"
+
+msgctxt "field:sale.subscription.line,subscription_state:"
+msgid "Subscription State"
+msgstr "Abonnementsstatus"
+
+msgctxt "field:sale.subscription.line,unit:"
+msgid "Unit"
+msgstr "Eenheid"
+
+msgctxt "field:sale.subscription.line,unit_digits:"
+msgid "Unit Digits"
+msgstr "Decimalen eenheid"
+
+msgctxt "field:sale.subscription.line,unit_price:"
+msgid "Unit Price"
+msgstr "Eenheids- prijs"
+
+msgctxt "field:sale.subscription.line.consumption,date:"
+msgid "Date"
+msgstr "Datum"
+
+msgctxt "field:sale.subscription.line.consumption,invoice_line:"
+msgid "Invoice Line"
+msgstr "Factuurregel"
+
+msgctxt "field:sale.subscription.line.consumption,line:"
+msgid "Line"
+msgstr "Regel"
+
+msgctxt "field:sale.subscription.line.consumption,quantity:"
+msgid "Quantity"
+msgstr "Hoeveelheid"
+
+msgctxt "field:sale.subscription.line.consumption,unit_digits:"
+msgid "Unit Digits"
+msgstr "Decimalen eenheid"
+
+msgctxt "field:sale.subscription.line.consumption.create.start,date:"
+msgid "Date"
+msgstr "Datum"
+
+msgctxt "field:sale.subscription.recurrence.rule,bymonth:"
+msgid "By Month"
+msgstr "per maand"
+
+msgctxt "field:sale.subscription.recurrence.rule,bymonthday:"
+msgid "By Month Day"
+msgstr "op dag van de maand"
+
+msgctxt "field:sale.subscription.recurrence.rule,bysetpos:"
+msgid "By Position"
+msgstr "Op positie"
+
+msgctxt "field:sale.subscription.recurrence.rule,byweekday:"
+msgid "By Week Day"
+msgstr "Per weekdag"
+
+msgctxt "field:sale.subscription.recurrence.rule,byweekno:"
+msgid "By Week Number"
+msgstr "Op weeknummer"
+
+msgctxt "field:sale.subscription.recurrence.rule,byyearday:"
+msgid "By Year Day"
+msgstr "Per dag van het jaar"
+
+msgctxt "field:sale.subscription.recurrence.rule,exclusive:"
+msgid "Exclusive"
+msgstr "exclusief"
+
+msgctxt "field:sale.subscription.recurrence.rule,freq:"
+msgid "Frequency"
+msgstr "Frequentie"
+
+msgctxt "field:sale.subscription.recurrence.rule,interval:"
+msgid "Interval"
+msgstr "Interval"
+
+msgctxt "field:sale.subscription.recurrence.rule,set_:"
+msgid "Set"
+msgstr "groep (set)"
+
+msgctxt "field:sale.subscription.recurrence.rule,week_start_day:"
+msgid "Week Start Day"
+msgstr "eerste dag van de week"
+
+msgctxt "field:sale.subscription.recurrence.rule.set,name:"
+msgid "Name"
+msgstr "Naam"
+
+msgctxt "field:sale.subscription.recurrence.rule.set,rules:"
+msgid "Rules"
+msgstr "Regels"
+
+msgctxt "field:sale.subscription.service,consumption_delay:"
+msgid "Consumption Delay"
+msgstr "Consumptievertraging"
+
+msgctxt "field:sale.subscription.service,consumption_recurrence:"
+msgid "Consumption Recurrence"
+msgstr "wederkerend verbruik"
+
+msgctxt "field:sale.subscription.service,product:"
+msgid "Product"
+msgstr "Product"
+
+msgctxt "help:sale.subscription,company:"
+msgid "Make the subscription belong to the company."
+msgstr "Maak het abonnement eigendom van het bedrijf."
+
+msgctxt "help:sale.subscription,number:"
+msgid "The main identification of the subscription."
+msgstr "De hoofdidentificatie van het abonnement."
+
+msgctxt "help:sale.subscription,party:"
+msgid "The party who subscribes."
+msgstr "De relatie die zich inschrijft."
+
+msgctxt "help:sale.subscription,reference:"
+msgid "The identification of an external origin."
+msgstr "De identificatie van een externe oorsprong."
+
+msgctxt "help:sale.subscription,state:"
+msgid "The current state of the subscription."
+msgstr "De huidige status van het abonnement."
+
+msgctxt "help:sale.subscription.line,subscription:"
+msgid "Add the line below the subscription."
+msgstr "Voeg de onderstaande regel toeaan het abonnement."
+
+msgctxt "help:sale.subscription.recurrence.rule,bymonth:"
+msgid "A comma separated list of integers."
+msgstr "Een door komma's gescheiden lijst met gehele getallen."
+
+msgctxt "help:sale.subscription.recurrence.rule,bymonthday:"
+msgid "A comma separated list of integers."
+msgstr "Een door komma's gescheiden lijst met gehele getallen."
+
+msgctxt "help:sale.subscription.recurrence.rule,bysetpos:"
+msgid "A comma separated list of integers."
+msgstr "Een door komma's gescheiden lijst met gehele getallen."
+
+msgctxt "help:sale.subscription.recurrence.rule,byweekday:"
+msgid "A comma separated list of integers or weekday (MO, TU etc)."
+msgstr ""
+"Een door komma's gescheiden lijst met gehele getallen of weekdagen (Ma, DI "
+"enz.)."
+
+msgctxt "help:sale.subscription.recurrence.rule,byweekno:"
+msgid "A comma separated list of integers (ISO8601)."
+msgstr "Een door komma's gescheiden lijst met gehele getallen (ISO8601)."
+
+msgctxt "help:sale.subscription.recurrence.rule,byyearday:"
+msgid "A comma separated list of integers."
+msgstr "Een door komma's gescheiden lijst met gehele getallen."
+
+msgctxt "help:sale.subscription.recurrence.rule,set_:"
+msgid "Add the rule below the set."
+msgstr "Voeg de regel toe onder het geheel(set)."
+
+msgctxt "help:sale.subscription.recurrence.rule.set,name:"
+msgid "The main identifier of the rule set."
+msgstr "De hoofdidentificatie van de regelset."
+
+msgctxt "model:ir.action,name:act_create_invoice"
+msgid "Create Subscription Invoices"
+msgstr "Maak een abonnementsfactuur aan"
+
+msgctxt "model:ir.action,name:act_line_consumption_create"
+msgid "Create Line Consumptions"
+msgstr "Maak een verbruiksartikkel"
+
+msgctxt "model:ir.action,name:act_recurrence_rule_set_form"
+msgid "Subscription Recurrence Rule Sets"
+msgstr "Herhalingsregels abonnement"
+
+msgctxt "model:ir.action,name:act_service_form"
+msgid "Subscription Services"
+msgstr "Abonnementsdiensten"
+
+msgctxt "model:ir.action,name:act_subscription_form"
+msgid "Subscriptions"
+msgstr "Abonnementen"
+
+msgctxt "model:ir.action,name:act_subscription_invoice_relate"
+msgid "Invoices"
+msgstr "Facturen"
+
+msgctxt "model:ir.action,name:act_subscription_line_consumption_form"
+msgid "Consumptions"
+msgstr "verbruiken"
+
+msgctxt ""
+"model:ir.action,name:act_subscription_line_consumption_subscription_line_relate"
+msgid "Consumptions"
+msgstr "verbruiken"
+
+msgctxt ""
+"model:ir.action,name:act_subscription_line_consumption_subscription_relate"
+msgid "Consumptions"
+msgstr "verbruiken"
+
+msgctxt "model:ir.action,name:act_subscription_party_relate"
+msgid "Subscriptions"
+msgstr "Abonnementen"
+
+msgctxt ""
+"model:ir.action.act_window.domain,name:act_subscription_form_domain_all"
+msgid "All"
+msgstr "Alles"
+
+msgctxt ""
+"model:ir.action.act_window.domain,name:act_subscription_form_domain_draft"
+msgid "Draft"
+msgstr "Concept"
+
+msgctxt ""
+"model:ir.action.act_window.domain,name:act_subscription_form_domain_quotation"
+msgid "Quotation"
+msgstr "Offerte"
+
+msgctxt ""
+"model:ir.action.act_window.domain,name:act_subscription_form_domain_running"
+msgid "Running"
+msgstr "in uitvoering"
+
+msgctxt "model:ir.message,text:msg_consumption_delete_invoiced"
+msgid "You cannot delete invoiced consumption \"%(consumption)s\"."
+msgstr "U kunt het gefactureerde verbruik \"%(consumption)s\" niet verwijderen."
+
+msgctxt ""
+"model:ir.message,text:msg_consumption_invoice_missing_account_revenue"
+msgid ""
+"To invoice consumptions you must define an account revenue for product "
+"\"%(product)s\"."
+msgstr ""
+"Om consumpties te factureren, moet u een omzetrekening definiëren voor "
+"product \"% (product) s\"."
+
+msgctxt "model:ir.message,text:msg_consumption_modify_invoiced"
+msgid "You cannot modify invoiced consumption \"%(consumption)s\"."
+msgstr "U kunt het gefactureerde verbruik \"%(consumption)s\" niet wijzigen."
+
+msgctxt "model:ir.message,text:msg_consumption_recurrence_invalid"
+msgid ""
+"The consumption recurrence of line \"%(line)s\" of subscription "
+"\"%(subscription)s\" does not generate any occurrence."
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_erase_party_pending_subscription"
+msgid ""
+"You cannot erase party \"%(party)s\" while they have pending subscriptions "
+"with company \"%(company)s\"."
+msgstr ""
+"U kunt de relatie \"%(party)s\" niet verwijderen terwijl ze aankopen in "
+"behandeling hebben bij bedrijf \"%(company)s\"."
+
+msgctxt "model:ir.message,text:msg_invoice_recurrence_invalid"
+msgid ""
+"The invoice recurrence of subscription \"%(subscription)s\" does not "
+"generate any occurrence."
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_recurrence_rule_invalid_by"
+msgid ""
+"Invalid \"%(field)s\" \"%(value)s\" in recurence rule "
+"\"%(recurrence_rule)s\" with exception \"%(exception)s\"."
+msgstr ""
+"\"%(field)s\" \"%(value)s\" in herhalingsregel \"%(recurrence_rule)s\" "
+"is/zijn ongeldig met fout \"%(exception)s\"."
+
+msgctxt "model:ir.model.button,string:subscription_cancel_button"
+msgid "Cancel"
+msgstr "Annuleer"
+
+msgctxt "model:ir.model.button,string:subscription_draft_button"
+msgid "Draft"
+msgstr "Concept"
+
+msgctxt "model:ir.model.button,string:subscription_quote_button"
+msgid "Quote"
+msgstr "offerte"
+
+msgctxt "model:ir.model.button,string:subscription_run_button"
+msgid "Run"
+msgstr "uitvoeren"
+
+msgctxt "model:ir.rule.group,name:rule_group_subscription_companies"
+msgid "User in companies"
+msgstr ""
+
+msgctxt "model:ir.sequence,name:sequence_subscription"
+msgid "Subscription"
+msgstr "Abonnement"
+
+msgctxt "model:ir.sequence.type,name:sequence_type_subscription"
+msgid "Subscription"
+msgstr "Abonnement"
+
+#, fuzzy
+msgctxt "model:ir.ui.menu,name:menu_configuration"
+msgid "Subscription"
+msgstr "Abonnement"
+
+msgctxt "model:ir.ui.menu,name:menu_create_invoice"
+msgid "Create Subscription Invoices"
+msgstr "Abonnementsfactuur maken"
+
+msgctxt "model:ir.ui.menu,name:menu_line_consumption_create"
+msgid "Create Line Consumptions"
+msgstr "Maak een verbruiksartikel"
+
+msgctxt "model:ir.ui.menu,name:menu_recurrence_rule_set_form"
+msgid "Subscription Recurrence Rule Sets"
+msgstr "Herhalingsregels abonnement"
+
+msgctxt "model:ir.ui.menu,name:menu_service_form"
+msgid "Subscription Services"
+msgstr "Abonnementsdiensten"
+
+msgctxt "model:ir.ui.menu,name:menu_subscription_form"
+msgid "Subscriptions"
+msgstr "Abonnementen"
+
+msgctxt "model:sale.subscription,name:"
+msgid "Subscription"
+msgstr "Abonnement"
+
+msgctxt "model:sale.subscription.create_invoice.start,name:"
+msgid "Create Subscription Invoice"
+msgstr "Abonnementsfactuur maken"
+
+msgctxt "model:sale.subscription.line,name:"
+msgid "Subscription Line"
+msgstr "Abonnementsregel"
+
+msgctxt "model:sale.subscription.line.consumption,name:"
+msgid "Subscription Line Consumption"
+msgstr "Abonnement verbruik"
+
+msgctxt "model:sale.subscription.line.consumption.create.start,name:"
+msgid "Create Subscription Line Consumption"
+msgstr "Creëer consumptie voor het abonnement item"
+
+msgctxt "model:sale.subscription.recurrence.rule,name:"
+msgid "Subscription Recurrence Rule"
+msgstr "abonnement herhalingsregel"
+
+msgctxt "model:sale.subscription.recurrence.rule.set,name:"
+msgid "Subscription Recurrence Rule Set"
+msgstr "Herhalingsregels abonnement"
+
+msgctxt "model:sale.subscription.service,name:"
+msgid "Subscription Service"
+msgstr "Abonnementsdienst"
+
+msgctxt "selection:ir.cron,method:"
+msgid "Generate Subscription Invoices"
+msgstr "Abonnementsfacturen genereren"
+
+msgctxt "selection:ir.cron,method:"
+msgid "Generate Subscription Line Consumptions"
+msgstr "Consumpties voor abonnementsregels genereren"
+
+msgctxt "selection:sale.subscription,state:"
+msgid "Cancelled"
+msgstr "Geannuleerd"
+
+msgctxt "selection:sale.subscription,state:"
+msgid "Closed"
+msgstr "Afgesloten"
+
+msgctxt "selection:sale.subscription,state:"
+msgid "Draft"
+msgstr "Concept"
+
+msgctxt "selection:sale.subscription,state:"
+msgid "Quotation"
+msgstr "Offerte"
+
+msgctxt "selection:sale.subscription,state:"
+msgid "Running"
+msgstr "in uitvoering"
+
+msgctxt "selection:sale.subscription.recurrence.rule,freq:"
+msgid "Daily"
+msgstr "Dagelijks"
+
+msgctxt "selection:sale.subscription.recurrence.rule,freq:"
+msgid "Monthly"
+msgstr "Maandelijks"
+
+msgctxt "selection:sale.subscription.recurrence.rule,freq:"
+msgid "Weekly"
+msgstr "Wekelijks"
+
+msgctxt "selection:sale.subscription.recurrence.rule,freq:"
+msgid "Yearly"
+msgstr "Jaarlijks"
+
+msgctxt "view:sale.subscription.create_invoice.start:"
+msgid "Create Subscription Invoices for date"
+msgstr "Abonnementsfacturen voor datum maken"
+
+msgctxt "view:sale.subscription.line.consumption.create.start:"
+msgid "Create Subscription Line Consumptions for date"
+msgstr "Creëer abonnementsregelconsumpties voor datum"
+
+msgctxt "view:sale.subscription.line:"
+msgid "General"
+msgstr "Algemeen"
+
+msgctxt "view:sale.subscription:"
+msgid "Other Info"
+msgstr "Overige informatie"
+
+msgctxt "view:sale.subscription:"
+msgid "Subscription"
+msgstr "Abonnement"
+
+msgctxt "wizard_button:sale.subscription.create_invoice,start,create_:"
+msgid "Create"
+msgstr "Maken"
+
+msgctxt "wizard_button:sale.subscription.create_invoice,start,end:"
+msgid "Cancel"
+msgstr "Annuleer"
+
+msgctxt ""
+"wizard_button:sale.subscription.line.consumption.create,start,create_:"
+msgid "Create"
+msgstr "Maken"
+
+msgctxt "wizard_button:sale.subscription.line.consumption.create,start,end:"
+msgid "Cancel"
+msgstr "Annuleer"
diff --git a/modules/sale_subscription/locale/pl.po b/modules/sale_subscription/locale/pl.po
new file mode 100644
index 0000000000..7277c91576
--- /dev/null
+++ b/modules/sale_subscription/locale/pl.po
@@ -0,0 +1,609 @@
+#
+msgid ""
+msgstr "Content-Type: text/plain; charset=utf-8\n"
+
+msgctxt "field:sale.configuration,subscription_sequence:"
+msgid "Subscription Sequence"
+msgstr "Sekwencja subskrypcji"
+
+msgctxt "field:sale.configuration.sequence,subscription_sequence:"
+msgid "Subscription Sequence"
+msgstr "Sekwencja subskrypcji"
+
+msgctxt "field:sale.subscription,company:"
+msgid "Company"
+msgstr "Firma"
+
+msgctxt "field:sale.subscription,contact:"
+msgid "Contact"
+msgstr ""
+
+msgctxt "field:sale.subscription,currency:"
+msgid "Currency"
+msgstr "Waluta"
+
+msgctxt "field:sale.subscription,description:"
+msgid "Description"
+msgstr "Opis"
+
+msgctxt "field:sale.subscription,end_date:"
+msgid "End Date"
+msgstr "Data ukończenia"
+
+msgctxt "field:sale.subscription,invoice_address:"
+msgid "Invoice Address"
+msgstr "Adres faktury"
+
+#, fuzzy
+msgctxt "field:sale.subscription,invoice_party:"
+msgid "Invoice Party"
+msgstr "Adres faktury"
+
+msgctxt "field:sale.subscription,invoice_recurrence:"
+msgid "Invoice Recurrence"
+msgstr ""
+
+msgctxt "field:sale.subscription,invoice_start_date:"
+msgid "Invoice Start Date"
+msgstr ""
+
+msgctxt "field:sale.subscription,lines:"
+msgid "Lines"
+msgstr "Wiersze"
+
+msgctxt "field:sale.subscription,next_invoice_date:"
+msgid "Next Invoice Date"
+msgstr ""
+
+msgctxt "field:sale.subscription,number:"
+msgid "Number"
+msgstr "Numer"
+
+msgctxt "field:sale.subscription,party:"
+msgid "Party"
+msgstr "Strona"
+
+msgctxt "field:sale.subscription,payment_term:"
+msgid "Payment Term"
+msgstr "Termin płatności"
+
+#, fuzzy
+msgctxt "field:sale.subscription,quoted_by:"
+msgid "Quoted By"
+msgstr "Quote"
+
+msgctxt "field:sale.subscription,reference:"
+msgid "Reference"
+msgstr "Referencja"
+
+msgctxt "field:sale.subscription,run_by:"
+msgid "Run By"
+msgstr ""
+
+msgctxt "field:sale.subscription,start_date:"
+msgid "Start Date"
+msgstr "Data rozpoczęcia"
+
+msgctxt "field:sale.subscription,state:"
+msgid "State"
+msgstr "Stan"
+
+msgctxt "field:sale.subscription.create_invoice.start,date:"
+msgid "Date"
+msgstr "Data"
+
+#, fuzzy
+msgctxt "field:sale.subscription.line,company:"
+msgid "Company"
+msgstr "Firma"
+
+#, fuzzy
+msgctxt "field:sale.subscription.line,consumed_until:"
+msgid "Consumed until"
+msgstr "Consumptions"
+
+msgctxt "field:sale.subscription.line,consumption_delay:"
+msgid "Consumption Delay"
+msgstr ""
+
+msgctxt "field:sale.subscription.line,consumption_recurrence:"
+msgid "Consumption Recurrence"
+msgstr ""
+
+#, fuzzy
+msgctxt "field:sale.subscription.line,currency:"
+msgid "Currency"
+msgstr "Waluta"
+
+msgctxt "field:sale.subscription.line,description:"
+msgid "Description"
+msgstr "Opis"
+
+msgctxt "field:sale.subscription.line,end_date:"
+msgid "End Date"
+msgstr "Data ukończenia"
+
+msgctxt "field:sale.subscription.line,next_consumption_date:"
+msgid "Next Consumption Date"
+msgstr ""
+
+msgctxt "field:sale.subscription.line,next_consumption_date_delayed:"
+msgid "Next Consumption Delayed"
+msgstr ""
+
+msgctxt "field:sale.subscription.line,quantity:"
+msgid "Quantity"
+msgstr "Ilość"
+
+msgctxt "field:sale.subscription.line,service:"
+msgid "Service"
+msgstr "Usługa"
+
+msgctxt "field:sale.subscription.line,service_unit_category:"
+msgid "Service Unit Category"
+msgstr "Kategoria jednostki usługi"
+
+msgctxt "field:sale.subscription.line,start_date:"
+msgid "Start Date"
+msgstr "Data rozpoczęcia"
+
+msgctxt "field:sale.subscription.line,subscription:"
+msgid "Subscription"
+msgstr "Subskrypcja"
+
+msgctxt "field:sale.subscription.line,subscription_end_date:"
+msgid "Subscription End Date"
+msgstr "Data zakończenia subskrypcji"
+
+msgctxt "field:sale.subscription.line,subscription_start_date:"
+msgid "Subscription Start Date"
+msgstr "Data rozpoczęcia subskrypcji"
+
+msgctxt "field:sale.subscription.line,subscription_state:"
+msgid "Subscription State"
+msgstr "Stan subskrypcji"
+
+msgctxt "field:sale.subscription.line,unit:"
+msgid "Unit"
+msgstr "Jednostka"
+
+msgctxt "field:sale.subscription.line,unit_digits:"
+msgid "Unit Digits"
+msgstr "Cyfry jednostki"
+
+msgctxt "field:sale.subscription.line,unit_price:"
+msgid "Unit Price"
+msgstr "Cena jednostkowa"
+
+msgctxt "field:sale.subscription.line.consumption,date:"
+msgid "Date"
+msgstr "Data"
+
+msgctxt "field:sale.subscription.line.consumption,invoice_line:"
+msgid "Invoice Line"
+msgstr "Wiersz faktury"
+
+msgctxt "field:sale.subscription.line.consumption,line:"
+msgid "Line"
+msgstr "Wiersz"
+
+msgctxt "field:sale.subscription.line.consumption,quantity:"
+msgid "Quantity"
+msgstr "Ilość"
+
+msgctxt "field:sale.subscription.line.consumption,unit_digits:"
+msgid "Unit Digits"
+msgstr "Cyfry jednostki"
+
+msgctxt "field:sale.subscription.line.consumption.create.start,date:"
+msgid "Date"
+msgstr "Data"
+
+msgctxt "field:sale.subscription.recurrence.rule,bymonth:"
+msgid "By Month"
+msgstr "Wg miesiąca"
+
+msgctxt "field:sale.subscription.recurrence.rule,bymonthday:"
+msgid "By Month Day"
+msgstr "Wg dnia miesiąca"
+
+msgctxt "field:sale.subscription.recurrence.rule,bysetpos:"
+msgid "By Position"
+msgstr "Wg pozycji"
+
+msgctxt "field:sale.subscription.recurrence.rule,byweekday:"
+msgid "By Week Day"
+msgstr "Wg dnia tygodnia"
+
+msgctxt "field:sale.subscription.recurrence.rule,byweekno:"
+msgid "By Week Number"
+msgstr "Wg numeru tygodnia"
+
+msgctxt "field:sale.subscription.recurrence.rule,byyearday:"
+msgid "By Year Day"
+msgstr "Wg dnia roku"
+
+msgctxt "field:sale.subscription.recurrence.rule,exclusive:"
+msgid "Exclusive"
+msgstr ""
+
+msgctxt "field:sale.subscription.recurrence.rule,freq:"
+msgid "Frequency"
+msgstr "Częstotliwość"
+
+msgctxt "field:sale.subscription.recurrence.rule,interval:"
+msgid "Interval"
+msgstr ""
+
+msgctxt "field:sale.subscription.recurrence.rule,set_:"
+msgid "Set"
+msgstr "Ustaw"
+
+#, fuzzy
+msgctxt "field:sale.subscription.recurrence.rule,week_start_day:"
+msgid "Week Start Day"
+msgstr "Dzień rozpoczęcia tygodnia"
+
+msgctxt "field:sale.subscription.recurrence.rule.set,name:"
+msgid "Name"
+msgstr "Nazwa"
+
+msgctxt "field:sale.subscription.recurrence.rule.set,rules:"
+msgid "Rules"
+msgstr "Reguły"
+
+msgctxt "field:sale.subscription.service,consumption_delay:"
+msgid "Consumption Delay"
+msgstr ""
+
+msgctxt "field:sale.subscription.service,consumption_recurrence:"
+msgid "Consumption Recurrence"
+msgstr ""
+
+msgctxt "field:sale.subscription.service,product:"
+msgid "Product"
+msgstr "Produkt"
+
+msgctxt "help:sale.subscription,company:"
+msgid "Make the subscription belong to the company."
+msgstr ""
+
+msgctxt "help:sale.subscription,number:"
+msgid "The main identification of the subscription."
+msgstr ""
+
+msgctxt "help:sale.subscription,party:"
+msgid "The party who subscribes."
+msgstr ""
+
+msgctxt "help:sale.subscription,reference:"
+msgid "The identification of an external origin."
+msgstr ""
+
+msgctxt "help:sale.subscription,state:"
+msgid "The current state of the subscription."
+msgstr ""
+
+msgctxt "help:sale.subscription.line,subscription:"
+msgid "Add the line below the subscription."
+msgstr ""
+
+msgctxt "help:sale.subscription.recurrence.rule,bymonth:"
+msgid "A comma separated list of integers."
+msgstr ""
+
+msgctxt "help:sale.subscription.recurrence.rule,bymonthday:"
+msgid "A comma separated list of integers."
+msgstr ""
+
+msgctxt "help:sale.subscription.recurrence.rule,bysetpos:"
+msgid "A comma separated list of integers."
+msgstr ""
+
+msgctxt "help:sale.subscription.recurrence.rule,byweekday:"
+msgid "A comma separated list of integers or weekday (MO, TU etc)."
+msgstr ""
+
+msgctxt "help:sale.subscription.recurrence.rule,byweekno:"
+msgid "A comma separated list of integers (ISO8601)."
+msgstr ""
+
+msgctxt "help:sale.subscription.recurrence.rule,byyearday:"
+msgid "A comma separated list of integers."
+msgstr ""
+
+msgctxt "help:sale.subscription.recurrence.rule,set_:"
+msgid "Add the rule below the set."
+msgstr ""
+
+msgctxt "help:sale.subscription.recurrence.rule.set,name:"
+msgid "The main identifier of the rule set."
+msgstr ""
+
+msgctxt "model:ir.action,name:act_create_invoice"
+msgid "Create Subscription Invoices"
+msgstr "Create Subscription Invoices"
+
+msgctxt "model:ir.action,name:act_line_consumption_create"
+msgid "Create Line Consumptions"
+msgstr "Create Line Consumptions"
+
+msgctxt "model:ir.action,name:act_recurrence_rule_set_form"
+msgid "Subscription Recurrence Rule Sets"
+msgstr "Subscription Recurrence Rule Sets"
+
+#, fuzzy
+msgctxt "model:ir.action,name:act_service_form"
+msgid "Subscription Services"
+msgstr "Sekwencja subskrypcji"
+
+#, fuzzy
+msgctxt "model:ir.action,name:act_subscription_form"
+msgid "Subscriptions"
+msgstr "Subskrypcje"
+
+msgctxt "model:ir.action,name:act_subscription_invoice_relate"
+msgid "Invoices"
+msgstr ""
+
+msgctxt "model:ir.action,name:act_subscription_line_consumption_form"
+msgid "Consumptions"
+msgstr "Consumptions"
+
+msgctxt ""
+"model:ir.action,name:act_subscription_line_consumption_subscription_line_relate"
+msgid "Consumptions"
+msgstr "Consumptions"
+
+msgctxt ""
+"model:ir.action,name:act_subscription_line_consumption_subscription_relate"
+msgid "Consumptions"
+msgstr "Consumptions"
+
+#, fuzzy
+msgctxt "model:ir.action,name:act_subscription_party_relate"
+msgid "Subscriptions"
+msgstr "Subskrypcje"
+
+msgctxt ""
+"model:ir.action.act_window.domain,name:act_subscription_form_domain_all"
+msgid "All"
+msgstr "All"
+
+msgctxt ""
+"model:ir.action.act_window.domain,name:act_subscription_form_domain_draft"
+msgid "Draft"
+msgstr "Draft"
+
+msgctxt ""
+"model:ir.action.act_window.domain,name:act_subscription_form_domain_quotation"
+msgid "Quotation"
+msgstr "Quotation"
+
+msgctxt ""
+"model:ir.action.act_window.domain,name:act_subscription_form_domain_running"
+msgid "Running"
+msgstr "Running"
+
+msgctxt "model:ir.message,text:msg_consumption_delete_invoiced"
+msgid "You cannot delete invoiced consumption \"%(consumption)s\"."
+msgstr ""
+
+msgctxt ""
+"model:ir.message,text:msg_consumption_invoice_missing_account_revenue"
+msgid ""
+"To invoice consumptions you must define an account revenue for product "
+"\"%(product)s\"."
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_consumption_modify_invoiced"
+msgid "You cannot modify invoiced consumption \"%(consumption)s\"."
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_consumption_recurrence_invalid"
+msgid ""
+"The consumption recurrence of line \"%(line)s\" of subscription "
+"\"%(subscription)s\" does not generate any occurrence."
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_erase_party_pending_subscription"
+msgid ""
+"You cannot erase party \"%(party)s\" while they have pending subscriptions "
+"with company \"%(company)s\"."
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_invoice_recurrence_invalid"
+msgid ""
+"The invoice recurrence of subscription \"%(subscription)s\" does not "
+"generate any occurrence."
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_recurrence_rule_invalid_by"
+msgid ""
+"Invalid \"%(field)s\" \"%(value)s\" in recurence rule "
+"\"%(recurrence_rule)s\" with exception \"%(exception)s\"."
+msgstr ""
+
+msgctxt "model:ir.model.button,string:subscription_cancel_button"
+msgid "Cancel"
+msgstr "Cancel"
+
+msgctxt "model:ir.model.button,string:subscription_draft_button"
+msgid "Draft"
+msgstr "Draft"
+
+msgctxt "model:ir.model.button,string:subscription_quote_button"
+msgid "Quote"
+msgstr "Quote"
+
+msgctxt "model:ir.model.button,string:subscription_run_button"
+msgid "Run"
+msgstr "Run"
+
+msgctxt "model:ir.rule.group,name:rule_group_subscription_companies"
+msgid "User in companies"
+msgstr ""
+
+#, fuzzy
+msgctxt "model:ir.sequence,name:sequence_subscription"
+msgid "Subscription"
+msgstr "Subscription"
+
+#, fuzzy
+msgctxt "model:ir.sequence.type,name:sequence_type_subscription"
+msgid "Subscription"
+msgstr "Subscription"
+
+#, fuzzy
+msgctxt "model:ir.ui.menu,name:menu_configuration"
+msgid "Subscription"
+msgstr "Subskrypcja"
+
+msgctxt "model:ir.ui.menu,name:menu_create_invoice"
+msgid "Create Subscription Invoices"
+msgstr "Create Subscription Invoices"
+
+msgctxt "model:ir.ui.menu,name:menu_line_consumption_create"
+msgid "Create Line Consumptions"
+msgstr "Create Line Consumptions"
+
+msgctxt "model:ir.ui.menu,name:menu_recurrence_rule_set_form"
+msgid "Subscription Recurrence Rule Sets"
+msgstr "Subscription Recurrence Rule Sets"
+
+#, fuzzy
+msgctxt "model:ir.ui.menu,name:menu_service_form"
+msgid "Subscription Services"
+msgstr "Sekwencja subskrypcji"
+
+#, fuzzy
+msgctxt "model:ir.ui.menu,name:menu_subscription_form"
+msgid "Subscriptions"
+msgstr "Subscriptions"
+
+msgctxt "model:sale.subscription,name:"
+msgid "Subscription"
+msgstr "Subskrypcja"
+
+#, fuzzy
+msgctxt "model:sale.subscription.create_invoice.start,name:"
+msgid "Create Subscription Invoice"
+msgstr "Create Subscription Invoices"
+
+msgctxt "model:sale.subscription.line,name:"
+msgid "Subscription Line"
+msgstr "Wiersz subskrypcji"
+
+#, fuzzy
+msgctxt "model:sale.subscription.line.consumption,name:"
+msgid "Subscription Line Consumption"
+msgstr "Generate Subscription Line Consumptions"
+
+#, fuzzy
+msgctxt "model:sale.subscription.line.consumption.create.start,name:"
+msgid "Create Subscription Line Consumption"
+msgstr "Generate Subscription Line Consumptions"
+
+#, fuzzy
+msgctxt "model:sale.subscription.recurrence.rule,name:"
+msgid "Subscription Recurrence Rule"
+msgstr "Subscription Recurrence Rule Sets"
+
+#, fuzzy
+msgctxt "model:sale.subscription.recurrence.rule.set,name:"
+msgid "Subscription Recurrence Rule Set"
+msgstr "Subscription Recurrence Rule Sets"
+
+#, fuzzy
+msgctxt "model:sale.subscription.service,name:"
+msgid "Subscription Service"
+msgstr "Sekwencja subskrypcji"
+
+#, fuzzy
+msgctxt "selection:ir.cron,method:"
+msgid "Generate Subscription Invoices"
+msgstr "Generate Subscription Invoices"
+
+#, fuzzy
+msgctxt "selection:ir.cron,method:"
+msgid "Generate Subscription Line Consumptions"
+msgstr "Generate Subscription Line Consumptions"
+
+#, fuzzy
+msgctxt "selection:sale.subscription,state:"
+msgid "Cancelled"
+msgstr "Anulowano"
+
+msgctxt "selection:sale.subscription,state:"
+msgid "Closed"
+msgstr "Zamknięto"
+
+#, fuzzy
+msgctxt "selection:sale.subscription,state:"
+msgid "Draft"
+msgstr "Draft"
+
+#, fuzzy
+msgctxt "selection:sale.subscription,state:"
+msgid "Quotation"
+msgstr "Quotation"
+
+#, fuzzy
+msgctxt "selection:sale.subscription,state:"
+msgid "Running"
+msgstr "Running"
+
+msgctxt "selection:sale.subscription.recurrence.rule,freq:"
+msgid "Daily"
+msgstr "Dziennie"
+
+msgctxt "selection:sale.subscription.recurrence.rule,freq:"
+msgid "Monthly"
+msgstr "Miesięcznie"
+
+msgctxt "selection:sale.subscription.recurrence.rule,freq:"
+msgid "Weekly"
+msgstr "Tygodniowo"
+
+msgctxt "selection:sale.subscription.recurrence.rule,freq:"
+msgid "Yearly"
+msgstr "Rocznie"
+
+#, fuzzy
+msgctxt "view:sale.subscription.create_invoice.start:"
+msgid "Create Subscription Invoices for date"
+msgstr "Create Subscription Invoices"
+
+#, fuzzy
+msgctxt "view:sale.subscription.line.consumption.create.start:"
+msgid "Create Subscription Line Consumptions for date"
+msgstr "Generate Subscription Line Consumptions"
+
+msgctxt "view:sale.subscription.line:"
+msgid "General"
+msgstr "Ogólne"
+
+msgctxt "view:sale.subscription:"
+msgid "Other Info"
+msgstr "Inne informacje"
+
+msgctxt "view:sale.subscription:"
+msgid "Subscription"
+msgstr "Subskrypcja"
+
+msgctxt "wizard_button:sale.subscription.create_invoice,start,create_:"
+msgid "Create"
+msgstr "Utwórz"
+
+msgctxt "wizard_button:sale.subscription.create_invoice,start,end:"
+msgid "Cancel"
+msgstr "Anuluj"
+
+msgctxt ""
+"wizard_button:sale.subscription.line.consumption.create,start,create_:"
+msgid "Create"
+msgstr "Utwórz"
+
+msgctxt "wizard_button:sale.subscription.line.consumption.create,start,end:"
+msgid "Cancel"
+msgstr "Anuluj"
diff --git a/modules/sale_subscription/locale/pt.po b/modules/sale_subscription/locale/pt.po
new file mode 100644
index 0000000000..e704015c8c
--- /dev/null
+++ b/modules/sale_subscription/locale/pt.po
@@ -0,0 +1,612 @@
+#
+msgid ""
+msgstr "Content-Type: text/plain; charset=utf-8\n"
+
+msgctxt "field:sale.configuration,subscription_sequence:"
+msgid "Subscription Sequence"
+msgstr "Sequência de Assinatura"
+
+msgctxt "field:sale.configuration.sequence,subscription_sequence:"
+msgid "Subscription Sequence"
+msgstr "Sequência de Assinatura"
+
+msgctxt "field:sale.subscription,company:"
+msgid "Company"
+msgstr "Empresa"
+
+msgctxt "field:sale.subscription,contact:"
+msgid "Contact"
+msgstr ""
+
+msgctxt "field:sale.subscription,currency:"
+msgid "Currency"
+msgstr "Moeda"
+
+msgctxt "field:sale.subscription,description:"
+msgid "Description"
+msgstr "Descrição"
+
+msgctxt "field:sale.subscription,end_date:"
+msgid "End Date"
+msgstr "Data de Término"
+
+msgctxt "field:sale.subscription,invoice_address:"
+msgid "Invoice Address"
+msgstr "Endereço para Faturamento"
+
+#, fuzzy
+msgctxt "field:sale.subscription,invoice_party:"
+msgid "Invoice Party"
+msgstr "Data de Início da Fatura"
+
+msgctxt "field:sale.subscription,invoice_recurrence:"
+msgid "Invoice Recurrence"
+msgstr "Recorrência da Fatura"
+
+msgctxt "field:sale.subscription,invoice_start_date:"
+msgid "Invoice Start Date"
+msgstr "Data de Início da Fatura"
+
+msgctxt "field:sale.subscription,lines:"
+msgid "Lines"
+msgstr "Linhas"
+
+msgctxt "field:sale.subscription,next_invoice_date:"
+msgid "Next Invoice Date"
+msgstr "Próxima Data da Fatura"
+
+msgctxt "field:sale.subscription,number:"
+msgid "Number"
+msgstr "Número"
+
+msgctxt "field:sale.subscription,party:"
+msgid "Party"
+msgstr "Pessoa"
+
+msgctxt "field:sale.subscription,payment_term:"
+msgid "Payment Term"
+msgstr "Prazo de Pagamento"
+
+#, fuzzy
+msgctxt "field:sale.subscription,quoted_by:"
+msgid "Quoted By"
+msgstr "Quote"
+
+msgctxt "field:sale.subscription,reference:"
+msgid "Reference"
+msgstr "Referência"
+
+msgctxt "field:sale.subscription,run_by:"
+msgid "Run By"
+msgstr ""
+
+msgctxt "field:sale.subscription,start_date:"
+msgid "Start Date"
+msgstr "Data de Início"
+
+msgctxt "field:sale.subscription,state:"
+msgid "State"
+msgstr "Estado"
+
+msgctxt "field:sale.subscription.create_invoice.start,date:"
+msgid "Date"
+msgstr "Data"
+
+#, fuzzy
+msgctxt "field:sale.subscription.line,company:"
+msgid "Company"
+msgstr "Empresa"
+
+#, fuzzy
+msgctxt "field:sale.subscription.line,consumed_until:"
+msgid "Consumed until"
+msgstr "Consumido"
+
+msgctxt "field:sale.subscription.line,consumption_delay:"
+msgid "Consumption Delay"
+msgstr "Atraso no Consumo"
+
+msgctxt "field:sale.subscription.line,consumption_recurrence:"
+msgid "Consumption Recurrence"
+msgstr "Recorrência do Consumo"
+
+#, fuzzy
+msgctxt "field:sale.subscription.line,currency:"
+msgid "Currency"
+msgstr "Moeda"
+
+msgctxt "field:sale.subscription.line,description:"
+msgid "Description"
+msgstr "Descrição"
+
+msgctxt "field:sale.subscription.line,end_date:"
+msgid "End Date"
+msgstr "Data de término"
+
+msgctxt "field:sale.subscription.line,next_consumption_date:"
+msgid "Next Consumption Date"
+msgstr "Próxima Data de Consumo"
+
+msgctxt "field:sale.subscription.line,next_consumption_date_delayed:"
+msgid "Next Consumption Delayed"
+msgstr "Próximo Consumo Atrasado"
+
+msgctxt "field:sale.subscription.line,quantity:"
+msgid "Quantity"
+msgstr "Quantidade"
+
+msgctxt "field:sale.subscription.line,service:"
+msgid "Service"
+msgstr "Serviço"
+
+msgctxt "field:sale.subscription.line,service_unit_category:"
+msgid "Service Unit Category"
+msgstr "Categoria da Unidade de Serviço"
+
+msgctxt "field:sale.subscription.line,start_date:"
+msgid "Start Date"
+msgstr "Data de início"
+
+msgctxt "field:sale.subscription.line,subscription:"
+msgid "Subscription"
+msgstr "Assinatura"
+
+msgctxt "field:sale.subscription.line,subscription_end_date:"
+msgid "Subscription End Date"
+msgstr "Data de Término da Assinatura"
+
+msgctxt "field:sale.subscription.line,subscription_start_date:"
+msgid "Subscription Start Date"
+msgstr "Data de Início da Assinatura"
+
+msgctxt "field:sale.subscription.line,subscription_state:"
+msgid "Subscription State"
+msgstr "Estado da Assinatura"
+
+msgctxt "field:sale.subscription.line,unit:"
+msgid "Unit"
+msgstr "Unidade"
+
+msgctxt "field:sale.subscription.line,unit_digits:"
+msgid "Unit Digits"
+msgstr "Dígitos Decimais da Unidade"
+
+msgctxt "field:sale.subscription.line,unit_price:"
+msgid "Unit Price"
+msgstr "Preço Unitário"
+
+msgctxt "field:sale.subscription.line.consumption,date:"
+msgid "Date"
+msgstr "Data"
+
+msgctxt "field:sale.subscription.line.consumption,invoice_line:"
+msgid "Invoice Line"
+msgstr "Linha da Fatura"
+
+msgctxt "field:sale.subscription.line.consumption,line:"
+msgid "Line"
+msgstr "Linha"
+
+msgctxt "field:sale.subscription.line.consumption,quantity:"
+msgid "Quantity"
+msgstr "Quantidade"
+
+msgctxt "field:sale.subscription.line.consumption,unit_digits:"
+msgid "Unit Digits"
+msgstr "Dígitos Decimais da Unidade"
+
+msgctxt "field:sale.subscription.line.consumption.create.start,date:"
+msgid "Date"
+msgstr "Data"
+
+msgctxt "field:sale.subscription.recurrence.rule,bymonth:"
+msgid "By Month"
+msgstr "Por Mês"
+
+msgctxt "field:sale.subscription.recurrence.rule,bymonthday:"
+msgid "By Month Day"
+msgstr "Por Dia do Mês"
+
+msgctxt "field:sale.subscription.recurrence.rule,bysetpos:"
+msgid "By Position"
+msgstr "Por Posição"
+
+msgctxt "field:sale.subscription.recurrence.rule,byweekday:"
+msgid "By Week Day"
+msgstr "Por Dia da Semana"
+
+msgctxt "field:sale.subscription.recurrence.rule,byweekno:"
+msgid "By Week Number"
+msgstr "Por Número da Semana"
+
+msgctxt "field:sale.subscription.recurrence.rule,byyearday:"
+msgid "By Year Day"
+msgstr "Por Dia do Ano"
+
+msgctxt "field:sale.subscription.recurrence.rule,exclusive:"
+msgid "Exclusive"
+msgstr "Exclusivo"
+
+msgctxt "field:sale.subscription.recurrence.rule,freq:"
+msgid "Frequency"
+msgstr "Frequência"
+
+msgctxt "field:sale.subscription.recurrence.rule,interval:"
+msgid "Interval"
+msgstr "Intervalo"
+
+msgctxt "field:sale.subscription.recurrence.rule,set_:"
+msgid "Set"
+msgstr "Definir"
+
+#, fuzzy
+msgctxt "field:sale.subscription.recurrence.rule,week_start_day:"
+msgid "Week Start Day"
+msgstr "Dia de Início da Semana"
+
+msgctxt "field:sale.subscription.recurrence.rule.set,name:"
+msgid "Name"
+msgstr "Nome"
+
+msgctxt "field:sale.subscription.recurrence.rule.set,rules:"
+msgid "Rules"
+msgstr "Regras"
+
+msgctxt "field:sale.subscription.service,consumption_delay:"
+msgid "Consumption Delay"
+msgstr "Atraso no Consumo"
+
+msgctxt "field:sale.subscription.service,consumption_recurrence:"
+msgid "Consumption Recurrence"
+msgstr "Recorrência do Consumo"
+
+msgctxt "field:sale.subscription.service,product:"
+msgid "Product"
+msgstr "Produto"
+
+msgctxt "help:sale.subscription,company:"
+msgid "Make the subscription belong to the company."
+msgstr "Faça com que a assinatura pertença à empresa."
+
+msgctxt "help:sale.subscription,number:"
+msgid "The main identification of the subscription."
+msgstr "O identificador principal da assinatura."
+
+msgctxt "help:sale.subscription,party:"
+msgid "The party who subscribes."
+msgstr "A pessoa que assina."
+
+msgctxt "help:sale.subscription,reference:"
+msgid "The identification of an external origin."
+msgstr "Identificador de origem externa."
+
+msgctxt "help:sale.subscription,state:"
+msgid "The current state of the subscription."
+msgstr "O estado atual da assinatura."
+
+msgctxt "help:sale.subscription.line,subscription:"
+msgid "Add the line below the subscription."
+msgstr "Adicionar linha abaixo da assinatura."
+
+msgctxt "help:sale.subscription.recurrence.rule,bymonth:"
+msgid "A comma separated list of integers."
+msgstr "Lista de inteiros separados por vírgula."
+
+msgctxt "help:sale.subscription.recurrence.rule,bymonthday:"
+msgid "A comma separated list of integers."
+msgstr "Lista de inteiros separados por vírgula."
+
+msgctxt "help:sale.subscription.recurrence.rule,bysetpos:"
+msgid "A comma separated list of integers."
+msgstr "Lista de inteiros separados por vírgula."
+
+msgctxt "help:sale.subscription.recurrence.rule,byweekday:"
+msgid "A comma separated list of integers or weekday (MO, TU etc)."
+msgstr ""
+"Lista de inteiros (que representem dias da semana) separados por vírgula."
+
+msgctxt "help:sale.subscription.recurrence.rule,byweekno:"
+msgid "A comma separated list of integers (ISO8601)."
+msgstr "Lista de inteiros (ISO8601) separados por vírgula."
+
+msgctxt "help:sale.subscription.recurrence.rule,byyearday:"
+msgid "A comma separated list of integers."
+msgstr "Lista de inteiros separados por vírgula."
+
+msgctxt "help:sale.subscription.recurrence.rule,set_:"
+msgid "Add the rule below the set."
+msgstr "Adicionar a regra abaixo do conjunto."
+
+msgctxt "help:sale.subscription.recurrence.rule.set,name:"
+msgid "The main identifier of the rule set."
+msgstr "O principal identificador do grupo de regras."
+
+#, fuzzy
+msgctxt "model:ir.action,name:act_create_invoice"
+msgid "Create Subscription Invoices"
+msgstr "Create Subscription Invoices"
+
+#, fuzzy
+msgctxt "model:ir.action,name:act_line_consumption_create"
+msgid "Create Line Consumptions"
+msgstr "Create Line Consumptions"
+
+#, fuzzy
+msgctxt "model:ir.action,name:act_recurrence_rule_set_form"
+msgid "Subscription Recurrence Rule Sets"
+msgstr "Subscription Recurrence Rule Sets"
+
+#, fuzzy
+msgctxt "model:ir.action,name:act_service_form"
+msgid "Subscription Services"
+msgstr "Subscription Services"
+
+#, fuzzy
+msgctxt "model:ir.action,name:act_subscription_form"
+msgid "Subscriptions"
+msgstr "Subscriptions"
+
+msgctxt "model:ir.action,name:act_subscription_invoice_relate"
+msgid "Invoices"
+msgstr ""
+
+#, fuzzy
+msgctxt "model:ir.action,name:act_subscription_line_consumption_form"
+msgid "Consumptions"
+msgstr "Consumptions"
+
+#, fuzzy
+msgctxt ""
+"model:ir.action,name:act_subscription_line_consumption_subscription_line_relate"
+msgid "Consumptions"
+msgstr "Consumptions"
+
+#, fuzzy
+msgctxt ""
+"model:ir.action,name:act_subscription_line_consumption_subscription_relate"
+msgid "Consumptions"
+msgstr "Consumptions"
+
+#, fuzzy
+msgctxt "model:ir.action,name:act_subscription_party_relate"
+msgid "Subscriptions"
+msgstr "Subscriptions"
+
+#, fuzzy
+msgctxt ""
+"model:ir.action.act_window.domain,name:act_subscription_form_domain_all"
+msgid "All"
+msgstr "All"
+
+#, fuzzy
+msgctxt ""
+"model:ir.action.act_window.domain,name:act_subscription_form_domain_draft"
+msgid "Draft"
+msgstr "Draft"
+
+#, fuzzy
+msgctxt ""
+"model:ir.action.act_window.domain,name:act_subscription_form_domain_quotation"
+msgid "Quotation"
+msgstr "Quotation"
+
+#, fuzzy
+msgctxt ""
+"model:ir.action.act_window.domain,name:act_subscription_form_domain_running"
+msgid "Running"
+msgstr "Running"
+
+msgctxt "model:ir.message,text:msg_consumption_delete_invoiced"
+msgid "You cannot delete invoiced consumption \"%(consumption)s\"."
+msgstr ""
+
+msgctxt ""
+"model:ir.message,text:msg_consumption_invoice_missing_account_revenue"
+msgid ""
+"To invoice consumptions you must define an account revenue for product "
+"\"%(product)s\"."
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_consumption_modify_invoiced"
+msgid "You cannot modify invoiced consumption \"%(consumption)s\"."
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_consumption_recurrence_invalid"
+msgid ""
+"The consumption recurrence of line \"%(line)s\" of subscription "
+"\"%(subscription)s\" does not generate any occurrence."
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_erase_party_pending_subscription"
+msgid ""
+"You cannot erase party \"%(party)s\" while they have pending subscriptions "
+"with company \"%(company)s\"."
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_invoice_recurrence_invalid"
+msgid ""
+"The invoice recurrence of subscription \"%(subscription)s\" does not "
+"generate any occurrence."
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_recurrence_rule_invalid_by"
+msgid ""
+"Invalid \"%(field)s\" \"%(value)s\" in recurence rule "
+"\"%(recurrence_rule)s\" with exception \"%(exception)s\"."
+msgstr ""
+
+msgctxt "model:ir.model.button,string:subscription_cancel_button"
+msgid "Cancel"
+msgstr "Cancel"
+
+msgctxt "model:ir.model.button,string:subscription_draft_button"
+msgid "Draft"
+msgstr "Draft"
+
+msgctxt "model:ir.model.button,string:subscription_quote_button"
+msgid "Quote"
+msgstr "Quote"
+
+msgctxt "model:ir.model.button,string:subscription_run_button"
+msgid "Run"
+msgstr "Run"
+
+msgctxt "model:ir.rule.group,name:rule_group_subscription_companies"
+msgid "User in companies"
+msgstr ""
+
+#, fuzzy
+msgctxt "model:ir.sequence,name:sequence_subscription"
+msgid "Subscription"
+msgstr "Subscription"
+
+#, fuzzy
+msgctxt "model:ir.sequence.type,name:sequence_type_subscription"
+msgid "Subscription"
+msgstr "Subscription"
+
+#, fuzzy
+msgctxt "model:ir.ui.menu,name:menu_configuration"
+msgid "Subscription"
+msgstr "Assinatura"
+
+#, fuzzy
+msgctxt "model:ir.ui.menu,name:menu_create_invoice"
+msgid "Create Subscription Invoices"
+msgstr "Create Subscription Invoices"
+
+#, fuzzy
+msgctxt "model:ir.ui.menu,name:menu_line_consumption_create"
+msgid "Create Line Consumptions"
+msgstr "Create Line Consumptions"
+
+#, fuzzy
+msgctxt "model:ir.ui.menu,name:menu_recurrence_rule_set_form"
+msgid "Subscription Recurrence Rule Sets"
+msgstr "Subscription Recurrence Rule Sets"
+
+#, fuzzy
+msgctxt "model:ir.ui.menu,name:menu_service_form"
+msgid "Subscription Services"
+msgstr "Subscription Services"
+
+#, fuzzy
+msgctxt "model:ir.ui.menu,name:menu_subscription_form"
+msgid "Subscriptions"
+msgstr "Subscriptions"
+
+msgctxt "model:sale.subscription,name:"
+msgid "Subscription"
+msgstr "Assinatura"
+
+msgctxt "model:sale.subscription.create_invoice.start,name:"
+msgid "Create Subscription Invoice"
+msgstr "Criar Assinatura de Fatura"
+
+msgctxt "model:sale.subscription.line,name:"
+msgid "Subscription Line"
+msgstr "Linha de Assinatura"
+
+msgctxt "model:sale.subscription.line.consumption,name:"
+msgid "Subscription Line Consumption"
+msgstr "Linha de Consumo da Assinatura"
+
+msgctxt "model:sale.subscription.line.consumption.create.start,name:"
+msgid "Create Subscription Line Consumption"
+msgstr "Criar Linha de Consumo da Assinatura"
+
+msgctxt "model:sale.subscription.recurrence.rule,name:"
+msgid "Subscription Recurrence Rule"
+msgstr "Regra de Recorrência da Assinatura"
+
+msgctxt "model:sale.subscription.recurrence.rule.set,name:"
+msgid "Subscription Recurrence Rule Set"
+msgstr "Grupo de Regras de Recorrência da Assinatura"
+
+msgctxt "model:sale.subscription.service,name:"
+msgid "Subscription Service"
+msgstr "Serviço de Assinatura"
+
+#, fuzzy
+msgctxt "selection:ir.cron,method:"
+msgid "Generate Subscription Invoices"
+msgstr "Generate Subscription Invoices"
+
+#, fuzzy
+msgctxt "selection:ir.cron,method:"
+msgid "Generate Subscription Line Consumptions"
+msgstr "Generate Subscription Line Consumptions"
+
+#, fuzzy
+msgctxt "selection:sale.subscription,state:"
+msgid "Cancelled"
+msgstr "Cancelado"
+
+msgctxt "selection:sale.subscription,state:"
+msgid "Closed"
+msgstr "Fechado"
+
+msgctxt "selection:sale.subscription,state:"
+msgid "Draft"
+msgstr "Rascunho"
+
+msgctxt "selection:sale.subscription,state:"
+msgid "Quotation"
+msgstr "Cotação"
+
+msgctxt "selection:sale.subscription,state:"
+msgid "Running"
+msgstr "Em execução"
+
+msgctxt "selection:sale.subscription.recurrence.rule,freq:"
+msgid "Daily"
+msgstr "Diariamente"
+
+msgctxt "selection:sale.subscription.recurrence.rule,freq:"
+msgid "Monthly"
+msgstr "Mensalmente"
+
+msgctxt "selection:sale.subscription.recurrence.rule,freq:"
+msgid "Weekly"
+msgstr "Semanalmente"
+
+msgctxt "selection:sale.subscription.recurrence.rule,freq:"
+msgid "Yearly"
+msgstr "Anualmente"
+
+msgctxt "view:sale.subscription.create_invoice.start:"
+msgid "Create Subscription Invoices for date"
+msgstr "Criar Faturas de Assinatura para Data"
+
+msgctxt "view:sale.subscription.line.consumption.create.start:"
+msgid "Create Subscription Line Consumptions for date"
+msgstr "Criar Linha de Consumo de Assinatura para Data"
+
+msgctxt "view:sale.subscription.line:"
+msgid "General"
+msgstr "Geral"
+
+msgctxt "view:sale.subscription:"
+msgid "Other Info"
+msgstr "Outras informações"
+
+msgctxt "view:sale.subscription:"
+msgid "Subscription"
+msgstr "Assinatura"
+
+msgctxt "wizard_button:sale.subscription.create_invoice,start,create_:"
+msgid "Create"
+msgstr "Criar"
+
+msgctxt "wizard_button:sale.subscription.create_invoice,start,end:"
+msgid "Cancel"
+msgstr "Cancelar"
+
+msgctxt ""
+"wizard_button:sale.subscription.line.consumption.create,start,create_:"
+msgid "Create"
+msgstr "Criar"
+
+msgctxt "wizard_button:sale.subscription.line.consumption.create,start,end:"
+msgid "Cancel"
+msgstr "Cancelar"
diff --git a/modules/sale_subscription/locale/ro.po b/modules/sale_subscription/locale/ro.po
new file mode 100644
index 0000000000..574cd37e26
--- /dev/null
+++ b/modules/sale_subscription/locale/ro.po
@@ -0,0 +1,583 @@
+#
+msgid ""
+msgstr "Content-Type: text/plain; charset=utf-8\n"
+
+msgctxt "field:sale.configuration,subscription_sequence:"
+msgid "Subscription Sequence"
+msgstr ""
+
+msgctxt "field:sale.configuration.sequence,subscription_sequence:"
+msgid "Subscription Sequence"
+msgstr ""
+
+msgctxt "field:sale.subscription,company:"
+msgid "Company"
+msgstr "Companie"
+
+msgctxt "field:sale.subscription,contact:"
+msgid "Contact"
+msgstr ""
+
+msgctxt "field:sale.subscription,currency:"
+msgid "Currency"
+msgstr "Moneda"
+
+msgctxt "field:sale.subscription,description:"
+msgid "Description"
+msgstr "Descriere"
+
+msgctxt "field:sale.subscription,end_date:"
+msgid "End Date"
+msgstr ""
+
+msgctxt "field:sale.subscription,invoice_address:"
+msgid "Invoice Address"
+msgstr ""
+
+msgctxt "field:sale.subscription,invoice_party:"
+msgid "Invoice Party"
+msgstr "Parte Facturata"
+
+msgctxt "field:sale.subscription,invoice_recurrence:"
+msgid "Invoice Recurrence"
+msgstr ""
+
+msgctxt "field:sale.subscription,invoice_start_date:"
+msgid "Invoice Start Date"
+msgstr ""
+
+msgctxt "field:sale.subscription,lines:"
+msgid "Lines"
+msgstr "Rânduri"
+
+msgctxt "field:sale.subscription,next_invoice_date:"
+msgid "Next Invoice Date"
+msgstr ""
+
+msgctxt "field:sale.subscription,number:"
+msgid "Number"
+msgstr ""
+
+msgctxt "field:sale.subscription,party:"
+msgid "Party"
+msgstr "Parte"
+
+msgctxt "field:sale.subscription,payment_term:"
+msgid "Payment Term"
+msgstr ""
+
+msgctxt "field:sale.subscription,quoted_by:"
+msgid "Quoted By"
+msgstr ""
+
+msgctxt "field:sale.subscription,reference:"
+msgid "Reference"
+msgstr ""
+
+msgctxt "field:sale.subscription,run_by:"
+msgid "Run By"
+msgstr ""
+
+msgctxt "field:sale.subscription,start_date:"
+msgid "Start Date"
+msgstr ""
+
+msgctxt "field:sale.subscription,state:"
+msgid "State"
+msgstr ""
+
+msgctxt "field:sale.subscription.create_invoice.start,date:"
+msgid "Date"
+msgstr "Data"
+
+#, fuzzy
+msgctxt "field:sale.subscription.line,company:"
+msgid "Company"
+msgstr "Companie"
+
+msgctxt "field:sale.subscription.line,consumed_until:"
+msgid "Consumed until"
+msgstr ""
+
+msgctxt "field:sale.subscription.line,consumption_delay:"
+msgid "Consumption Delay"
+msgstr ""
+
+msgctxt "field:sale.subscription.line,consumption_recurrence:"
+msgid "Consumption Recurrence"
+msgstr ""
+
+msgctxt "field:sale.subscription.line,currency:"
+msgid "Currency"
+msgstr "Valută"
+
+msgctxt "field:sale.subscription.line,description:"
+msgid "Description"
+msgstr "Descriere"
+
+msgctxt "field:sale.subscription.line,end_date:"
+msgid "End Date"
+msgstr ""
+
+msgctxt "field:sale.subscription.line,next_consumption_date:"
+msgid "Next Consumption Date"
+msgstr ""
+
+msgctxt "field:sale.subscription.line,next_consumption_date_delayed:"
+msgid "Next Consumption Delayed"
+msgstr ""
+
+msgctxt "field:sale.subscription.line,quantity:"
+msgid "Quantity"
+msgstr ""
+
+msgctxt "field:sale.subscription.line,service:"
+msgid "Service"
+msgstr ""
+
+msgctxt "field:sale.subscription.line,service_unit_category:"
+msgid "Service Unit Category"
+msgstr ""
+
+msgctxt "field:sale.subscription.line,start_date:"
+msgid "Start Date"
+msgstr ""
+
+msgctxt "field:sale.subscription.line,subscription:"
+msgid "Subscription"
+msgstr ""
+
+msgctxt "field:sale.subscription.line,subscription_end_date:"
+msgid "Subscription End Date"
+msgstr ""
+
+msgctxt "field:sale.subscription.line,subscription_start_date:"
+msgid "Subscription Start Date"
+msgstr ""
+
+msgctxt "field:sale.subscription.line,subscription_state:"
+msgid "Subscription State"
+msgstr ""
+
+msgctxt "field:sale.subscription.line,unit:"
+msgid "Unit"
+msgstr ""
+
+msgctxt "field:sale.subscription.line,unit_digits:"
+msgid "Unit Digits"
+msgstr ""
+
+msgctxt "field:sale.subscription.line,unit_price:"
+msgid "Unit Price"
+msgstr ""
+
+msgctxt "field:sale.subscription.line.consumption,date:"
+msgid "Date"
+msgstr "Data"
+
+msgctxt "field:sale.subscription.line.consumption,invoice_line:"
+msgid "Invoice Line"
+msgstr ""
+
+msgctxt "field:sale.subscription.line.consumption,line:"
+msgid "Line"
+msgstr ""
+
+msgctxt "field:sale.subscription.line.consumption,quantity:"
+msgid "Quantity"
+msgstr ""
+
+msgctxt "field:sale.subscription.line.consumption,unit_digits:"
+msgid "Unit Digits"
+msgstr ""
+
+msgctxt "field:sale.subscription.line.consumption.create.start,date:"
+msgid "Date"
+msgstr "Data"
+
+msgctxt "field:sale.subscription.recurrence.rule,bymonth:"
+msgid "By Month"
+msgstr ""
+
+msgctxt "field:sale.subscription.recurrence.rule,bymonthday:"
+msgid "By Month Day"
+msgstr ""
+
+msgctxt "field:sale.subscription.recurrence.rule,bysetpos:"
+msgid "By Position"
+msgstr ""
+
+msgctxt "field:sale.subscription.recurrence.rule,byweekday:"
+msgid "By Week Day"
+msgstr ""
+
+msgctxt "field:sale.subscription.recurrence.rule,byweekno:"
+msgid "By Week Number"
+msgstr ""
+
+msgctxt "field:sale.subscription.recurrence.rule,byyearday:"
+msgid "By Year Day"
+msgstr ""
+
+msgctxt "field:sale.subscription.recurrence.rule,exclusive:"
+msgid "Exclusive"
+msgstr ""
+
+msgctxt "field:sale.subscription.recurrence.rule,freq:"
+msgid "Frequency"
+msgstr ""
+
+msgctxt "field:sale.subscription.recurrence.rule,interval:"
+msgid "Interval"
+msgstr ""
+
+msgctxt "field:sale.subscription.recurrence.rule,set_:"
+msgid "Set"
+msgstr ""
+
+msgctxt "field:sale.subscription.recurrence.rule,week_start_day:"
+msgid "Week Start Day"
+msgstr ""
+
+msgctxt "field:sale.subscription.recurrence.rule.set,name:"
+msgid "Name"
+msgstr ""
+
+msgctxt "field:sale.subscription.recurrence.rule.set,rules:"
+msgid "Rules"
+msgstr ""
+
+msgctxt "field:sale.subscription.service,consumption_delay:"
+msgid "Consumption Delay"
+msgstr ""
+
+msgctxt "field:sale.subscription.service,consumption_recurrence:"
+msgid "Consumption Recurrence"
+msgstr ""
+
+msgctxt "field:sale.subscription.service,product:"
+msgid "Product"
+msgstr "Produs"
+
+msgctxt "help:sale.subscription,company:"
+msgid "Make the subscription belong to the company."
+msgstr ""
+
+msgctxt "help:sale.subscription,number:"
+msgid "The main identification of the subscription."
+msgstr ""
+
+msgctxt "help:sale.subscription,party:"
+msgid "The party who subscribes."
+msgstr ""
+
+msgctxt "help:sale.subscription,reference:"
+msgid "The identification of an external origin."
+msgstr ""
+
+msgctxt "help:sale.subscription,state:"
+msgid "The current state of the subscription."
+msgstr ""
+
+msgctxt "help:sale.subscription.line,subscription:"
+msgid "Add the line below the subscription."
+msgstr ""
+
+msgctxt "help:sale.subscription.recurrence.rule,bymonth:"
+msgid "A comma separated list of integers."
+msgstr ""
+
+msgctxt "help:sale.subscription.recurrence.rule,bymonthday:"
+msgid "A comma separated list of integers."
+msgstr ""
+
+msgctxt "help:sale.subscription.recurrence.rule,bysetpos:"
+msgid "A comma separated list of integers."
+msgstr ""
+
+msgctxt "help:sale.subscription.recurrence.rule,byweekday:"
+msgid "A comma separated list of integers or weekday (MO, TU etc)."
+msgstr ""
+
+msgctxt "help:sale.subscription.recurrence.rule,byweekno:"
+msgid "A comma separated list of integers (ISO8601)."
+msgstr ""
+
+msgctxt "help:sale.subscription.recurrence.rule,byyearday:"
+msgid "A comma separated list of integers."
+msgstr ""
+
+msgctxt "help:sale.subscription.recurrence.rule,set_:"
+msgid "Add the rule below the set."
+msgstr ""
+
+msgctxt "help:sale.subscription.recurrence.rule.set,name:"
+msgid "The main identifier of the rule set."
+msgstr ""
+
+msgctxt "model:ir.action,name:act_create_invoice"
+msgid "Create Subscription Invoices"
+msgstr ""
+
+msgctxt "model:ir.action,name:act_line_consumption_create"
+msgid "Create Line Consumptions"
+msgstr ""
+
+msgctxt "model:ir.action,name:act_recurrence_rule_set_form"
+msgid "Subscription Recurrence Rule Sets"
+msgstr ""
+
+msgctxt "model:ir.action,name:act_service_form"
+msgid "Subscription Services"
+msgstr ""
+
+msgctxt "model:ir.action,name:act_subscription_form"
+msgid "Subscriptions"
+msgstr ""
+
+msgctxt "model:ir.action,name:act_subscription_invoice_relate"
+msgid "Invoices"
+msgstr ""
+
+msgctxt "model:ir.action,name:act_subscription_line_consumption_form"
+msgid "Consumptions"
+msgstr ""
+
+msgctxt ""
+"model:ir.action,name:act_subscription_line_consumption_subscription_line_relate"
+msgid "Consumptions"
+msgstr ""
+
+msgctxt ""
+"model:ir.action,name:act_subscription_line_consumption_subscription_relate"
+msgid "Consumptions"
+msgstr ""
+
+msgctxt "model:ir.action,name:act_subscription_party_relate"
+msgid "Subscriptions"
+msgstr ""
+
+msgctxt ""
+"model:ir.action.act_window.domain,name:act_subscription_form_domain_all"
+msgid "All"
+msgstr ""
+
+msgctxt ""
+"model:ir.action.act_window.domain,name:act_subscription_form_domain_draft"
+msgid "Draft"
+msgstr ""
+
+msgctxt ""
+"model:ir.action.act_window.domain,name:act_subscription_form_domain_quotation"
+msgid "Quotation"
+msgstr ""
+
+msgctxt ""
+"model:ir.action.act_window.domain,name:act_subscription_form_domain_running"
+msgid "Running"
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_consumption_delete_invoiced"
+msgid "You cannot delete invoiced consumption \"%(consumption)s\"."
+msgstr ""
+
+msgctxt ""
+"model:ir.message,text:msg_consumption_invoice_missing_account_revenue"
+msgid ""
+"To invoice consumptions you must define an account revenue for product "
+"\"%(product)s\"."
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_consumption_modify_invoiced"
+msgid "You cannot modify invoiced consumption \"%(consumption)s\"."
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_consumption_recurrence_invalid"
+msgid ""
+"The consumption recurrence of line \"%(line)s\" of subscription "
+"\"%(subscription)s\" does not generate any occurrence."
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_erase_party_pending_subscription"
+msgid ""
+"You cannot erase party \"%(party)s\" while they have pending subscriptions "
+"with company \"%(company)s\"."
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_invoice_recurrence_invalid"
+msgid ""
+"The invoice recurrence of subscription \"%(subscription)s\" does not "
+"generate any occurrence."
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_recurrence_rule_invalid_by"
+msgid ""
+"Invalid \"%(field)s\" \"%(value)s\" in recurence rule "
+"\"%(recurrence_rule)s\" with exception \"%(exception)s\"."
+msgstr ""
+
+msgctxt "model:ir.model.button,string:subscription_cancel_button"
+msgid "Cancel"
+msgstr ""
+
+msgctxt "model:ir.model.button,string:subscription_draft_button"
+msgid "Draft"
+msgstr ""
+
+msgctxt "model:ir.model.button,string:subscription_quote_button"
+msgid "Quote"
+msgstr ""
+
+msgctxt "model:ir.model.button,string:subscription_run_button"
+msgid "Run"
+msgstr ""
+
+msgctxt "model:ir.rule.group,name:rule_group_subscription_companies"
+msgid "User in companies"
+msgstr ""
+
+msgctxt "model:ir.sequence,name:sequence_subscription"
+msgid "Subscription"
+msgstr ""
+
+msgctxt "model:ir.sequence.type,name:sequence_type_subscription"
+msgid "Subscription"
+msgstr ""
+
+#, fuzzy
+msgctxt "model:ir.ui.menu,name:menu_configuration"
+msgid "Subscription"
+msgstr "Descriere"
+
+msgctxt "model:ir.ui.menu,name:menu_create_invoice"
+msgid "Create Subscription Invoices"
+msgstr ""
+
+msgctxt "model:ir.ui.menu,name:menu_line_consumption_create"
+msgid "Create Line Consumptions"
+msgstr ""
+
+msgctxt "model:ir.ui.menu,name:menu_recurrence_rule_set_form"
+msgid "Subscription Recurrence Rule Sets"
+msgstr ""
+
+msgctxt "model:ir.ui.menu,name:menu_service_form"
+msgid "Subscription Services"
+msgstr ""
+
+msgctxt "model:ir.ui.menu,name:menu_subscription_form"
+msgid "Subscriptions"
+msgstr ""
+
+msgctxt "model:sale.subscription,name:"
+msgid "Subscription"
+msgstr ""
+
+msgctxt "model:sale.subscription.create_invoice.start,name:"
+msgid "Create Subscription Invoice"
+msgstr ""
+
+msgctxt "model:sale.subscription.line,name:"
+msgid "Subscription Line"
+msgstr ""
+
+msgctxt "model:sale.subscription.line.consumption,name:"
+msgid "Subscription Line Consumption"
+msgstr ""
+
+msgctxt "model:sale.subscription.line.consumption.create.start,name:"
+msgid "Create Subscription Line Consumption"
+msgstr ""
+
+msgctxt "model:sale.subscription.recurrence.rule,name:"
+msgid "Subscription Recurrence Rule"
+msgstr ""
+
+msgctxt "model:sale.subscription.recurrence.rule.set,name:"
+msgid "Subscription Recurrence Rule Set"
+msgstr ""
+
+msgctxt "model:sale.subscription.service,name:"
+msgid "Subscription Service"
+msgstr ""
+
+msgctxt "selection:ir.cron,method:"
+msgid "Generate Subscription Invoices"
+msgstr ""
+
+msgctxt "selection:ir.cron,method:"
+msgid "Generate Subscription Line Consumptions"
+msgstr ""
+
+msgctxt "selection:sale.subscription,state:"
+msgid "Cancelled"
+msgstr ""
+
+msgctxt "selection:sale.subscription,state:"
+msgid "Closed"
+msgstr "Închis"
+
+msgctxt "selection:sale.subscription,state:"
+msgid "Draft"
+msgstr ""
+
+msgctxt "selection:sale.subscription,state:"
+msgid "Quotation"
+msgstr ""
+
+msgctxt "selection:sale.subscription,state:"
+msgid "Running"
+msgstr ""
+
+msgctxt "selection:sale.subscription.recurrence.rule,freq:"
+msgid "Daily"
+msgstr ""
+
+msgctxt "selection:sale.subscription.recurrence.rule,freq:"
+msgid "Monthly"
+msgstr ""
+
+msgctxt "selection:sale.subscription.recurrence.rule,freq:"
+msgid "Weekly"
+msgstr ""
+
+msgctxt "selection:sale.subscription.recurrence.rule,freq:"
+msgid "Yearly"
+msgstr ""
+
+msgctxt "view:sale.subscription.create_invoice.start:"
+msgid "Create Subscription Invoices for date"
+msgstr ""
+
+msgctxt "view:sale.subscription.line.consumption.create.start:"
+msgid "Create Subscription Line Consumptions for date"
+msgstr ""
+
+msgctxt "view:sale.subscription.line:"
+msgid "General"
+msgstr ""
+
+msgctxt "view:sale.subscription:"
+msgid "Other Info"
+msgstr ""
+
+msgctxt "view:sale.subscription:"
+msgid "Subscription"
+msgstr ""
+
+msgctxt "wizard_button:sale.subscription.create_invoice,start,create_:"
+msgid "Create"
+msgstr ""
+
+msgctxt "wizard_button:sale.subscription.create_invoice,start,end:"
+msgid "Cancel"
+msgstr ""
+
+msgctxt ""
+"wizard_button:sale.subscription.line.consumption.create,start,create_:"
+msgid "Create"
+msgstr ""
+
+msgctxt "wizard_button:sale.subscription.line.consumption.create,start,end:"
+msgid "Cancel"
+msgstr ""
diff --git a/modules/sale_subscription/locale/ru.po b/modules/sale_subscription/locale/ru.po
new file mode 100644
index 0000000000..4e46c4f6c0
--- /dev/null
+++ b/modules/sale_subscription/locale/ru.po
@@ -0,0 +1,611 @@
+#
+msgid ""
+msgstr "Content-Type: text/plain; charset=utf-8\n"
+
+#, fuzzy
+msgctxt "field:sale.configuration,subscription_sequence:"
+msgid "Subscription Sequence"
+msgstr "Subscription Services"
+
+#, fuzzy
+msgctxt "field:sale.configuration.sequence,subscription_sequence:"
+msgid "Subscription Sequence"
+msgstr "Subscription Services"
+
+msgctxt "field:sale.subscription,company:"
+msgid "Company"
+msgstr ""
+
+msgctxt "field:sale.subscription,contact:"
+msgid "Contact"
+msgstr ""
+
+msgctxt "field:sale.subscription,currency:"
+msgid "Currency"
+msgstr ""
+
+#, fuzzy
+msgctxt "field:sale.subscription,description:"
+msgid "Description"
+msgstr "Subscription"
+
+msgctxt "field:sale.subscription,end_date:"
+msgid "End Date"
+msgstr ""
+
+msgctxt "field:sale.subscription,invoice_address:"
+msgid "Invoice Address"
+msgstr ""
+
+msgctxt "field:sale.subscription,invoice_party:"
+msgid "Invoice Party"
+msgstr ""
+
+msgctxt "field:sale.subscription,invoice_recurrence:"
+msgid "Invoice Recurrence"
+msgstr ""
+
+msgctxt "field:sale.subscription,invoice_start_date:"
+msgid "Invoice Start Date"
+msgstr ""
+
+msgctxt "field:sale.subscription,lines:"
+msgid "Lines"
+msgstr ""
+
+msgctxt "field:sale.subscription,next_invoice_date:"
+msgid "Next Invoice Date"
+msgstr ""
+
+msgctxt "field:sale.subscription,number:"
+msgid "Number"
+msgstr ""
+
+msgctxt "field:sale.subscription,party:"
+msgid "Party"
+msgstr ""
+
+msgctxt "field:sale.subscription,payment_term:"
+msgid "Payment Term"
+msgstr ""
+
+#, fuzzy
+msgctxt "field:sale.subscription,quoted_by:"
+msgid "Quoted By"
+msgstr "Quote"
+
+msgctxt "field:sale.subscription,reference:"
+msgid "Reference"
+msgstr ""
+
+msgctxt "field:sale.subscription,run_by:"
+msgid "Run By"
+msgstr ""
+
+msgctxt "field:sale.subscription,start_date:"
+msgid "Start Date"
+msgstr ""
+
+msgctxt "field:sale.subscription,state:"
+msgid "State"
+msgstr ""
+
+msgctxt "field:sale.subscription.create_invoice.start,date:"
+msgid "Date"
+msgstr ""
+
+msgctxt "field:sale.subscription.line,company:"
+msgid "Company"
+msgstr ""
+
+#, fuzzy
+msgctxt "field:sale.subscription.line,consumed_until:"
+msgid "Consumed until"
+msgstr "Consumptions"
+
+msgctxt "field:sale.subscription.line,consumption_delay:"
+msgid "Consumption Delay"
+msgstr ""
+
+msgctxt "field:sale.subscription.line,consumption_recurrence:"
+msgid "Consumption Recurrence"
+msgstr ""
+
+msgctxt "field:sale.subscription.line,currency:"
+msgid "Currency"
+msgstr ""
+
+#, fuzzy
+msgctxt "field:sale.subscription.line,description:"
+msgid "Description"
+msgstr "Subscription"
+
+msgctxt "field:sale.subscription.line,end_date:"
+msgid "End Date"
+msgstr ""
+
+msgctxt "field:sale.subscription.line,next_consumption_date:"
+msgid "Next Consumption Date"
+msgstr ""
+
+msgctxt "field:sale.subscription.line,next_consumption_date_delayed:"
+msgid "Next Consumption Delayed"
+msgstr ""
+
+msgctxt "field:sale.subscription.line,quantity:"
+msgid "Quantity"
+msgstr ""
+
+msgctxt "field:sale.subscription.line,service:"
+msgid "Service"
+msgstr ""
+
+msgctxt "field:sale.subscription.line,service_unit_category:"
+msgid "Service Unit Category"
+msgstr ""
+
+msgctxt "field:sale.subscription.line,start_date:"
+msgid "Start Date"
+msgstr ""
+
+#, fuzzy
+msgctxt "field:sale.subscription.line,subscription:"
+msgid "Subscription"
+msgstr "Subscription"
+
+#, fuzzy
+msgctxt "field:sale.subscription.line,subscription_end_date:"
+msgid "Subscription End Date"
+msgstr "Subscription Services"
+
+#, fuzzy
+msgctxt "field:sale.subscription.line,subscription_start_date:"
+msgid "Subscription Start Date"
+msgstr "Subscription Services"
+
+#, fuzzy
+msgctxt "field:sale.subscription.line,subscription_state:"
+msgid "Subscription State"
+msgstr "Subscription Services"
+
+msgctxt "field:sale.subscription.line,unit:"
+msgid "Unit"
+msgstr ""
+
+msgctxt "field:sale.subscription.line,unit_digits:"
+msgid "Unit Digits"
+msgstr ""
+
+msgctxt "field:sale.subscription.line,unit_price:"
+msgid "Unit Price"
+msgstr ""
+
+msgctxt "field:sale.subscription.line.consumption,date:"
+msgid "Date"
+msgstr ""
+
+msgctxt "field:sale.subscription.line.consumption,invoice_line:"
+msgid "Invoice Line"
+msgstr ""
+
+msgctxt "field:sale.subscription.line.consumption,line:"
+msgid "Line"
+msgstr ""
+
+msgctxt "field:sale.subscription.line.consumption,quantity:"
+msgid "Quantity"
+msgstr ""
+
+msgctxt "field:sale.subscription.line.consumption,unit_digits:"
+msgid "Unit Digits"
+msgstr ""
+
+msgctxt "field:sale.subscription.line.consumption.create.start,date:"
+msgid "Date"
+msgstr ""
+
+msgctxt "field:sale.subscription.recurrence.rule,bymonth:"
+msgid "By Month"
+msgstr ""
+
+msgctxt "field:sale.subscription.recurrence.rule,bymonthday:"
+msgid "By Month Day"
+msgstr ""
+
+msgctxt "field:sale.subscription.recurrence.rule,bysetpos:"
+msgid "By Position"
+msgstr ""
+
+msgctxt "field:sale.subscription.recurrence.rule,byweekday:"
+msgid "By Week Day"
+msgstr ""
+
+msgctxt "field:sale.subscription.recurrence.rule,byweekno:"
+msgid "By Week Number"
+msgstr ""
+
+msgctxt "field:sale.subscription.recurrence.rule,byyearday:"
+msgid "By Year Day"
+msgstr ""
+
+msgctxt "field:sale.subscription.recurrence.rule,exclusive:"
+msgid "Exclusive"
+msgstr ""
+
+msgctxt "field:sale.subscription.recurrence.rule,freq:"
+msgid "Frequency"
+msgstr ""
+
+msgctxt "field:sale.subscription.recurrence.rule,interval:"
+msgid "Interval"
+msgstr ""
+
+msgctxt "field:sale.subscription.recurrence.rule,set_:"
+msgid "Set"
+msgstr ""
+
+msgctxt "field:sale.subscription.recurrence.rule,week_start_day:"
+msgid "Week Start Day"
+msgstr ""
+
+msgctxt "field:sale.subscription.recurrence.rule.set,name:"
+msgid "Name"
+msgstr ""
+
+msgctxt "field:sale.subscription.recurrence.rule.set,rules:"
+msgid "Rules"
+msgstr ""
+
+msgctxt "field:sale.subscription.service,consumption_delay:"
+msgid "Consumption Delay"
+msgstr ""
+
+msgctxt "field:sale.subscription.service,consumption_recurrence:"
+msgid "Consumption Recurrence"
+msgstr ""
+
+msgctxt "field:sale.subscription.service,product:"
+msgid "Product"
+msgstr ""
+
+msgctxt "help:sale.subscription,company:"
+msgid "Make the subscription belong to the company."
+msgstr ""
+
+msgctxt "help:sale.subscription,number:"
+msgid "The main identification of the subscription."
+msgstr ""
+
+msgctxt "help:sale.subscription,party:"
+msgid "The party who subscribes."
+msgstr ""
+
+msgctxt "help:sale.subscription,reference:"
+msgid "The identification of an external origin."
+msgstr ""
+
+msgctxt "help:sale.subscription,state:"
+msgid "The current state of the subscription."
+msgstr ""
+
+msgctxt "help:sale.subscription.line,subscription:"
+msgid "Add the line below the subscription."
+msgstr ""
+
+msgctxt "help:sale.subscription.recurrence.rule,bymonth:"
+msgid "A comma separated list of integers."
+msgstr ""
+
+msgctxt "help:sale.subscription.recurrence.rule,bymonthday:"
+msgid "A comma separated list of integers."
+msgstr ""
+
+msgctxt "help:sale.subscription.recurrence.rule,bysetpos:"
+msgid "A comma separated list of integers."
+msgstr ""
+
+msgctxt "help:sale.subscription.recurrence.rule,byweekday:"
+msgid "A comma separated list of integers or weekday (MO, TU etc)."
+msgstr ""
+
+msgctxt "help:sale.subscription.recurrence.rule,byweekno:"
+msgid "A comma separated list of integers (ISO8601)."
+msgstr ""
+
+msgctxt "help:sale.subscription.recurrence.rule,byyearday:"
+msgid "A comma separated list of integers."
+msgstr ""
+
+msgctxt "help:sale.subscription.recurrence.rule,set_:"
+msgid "Add the rule below the set."
+msgstr ""
+
+msgctxt "help:sale.subscription.recurrence.rule.set,name:"
+msgid "The main identifier of the rule set."
+msgstr ""
+
+msgctxt "model:ir.action,name:act_create_invoice"
+msgid "Create Subscription Invoices"
+msgstr "Create Subscription Invoices"
+
+msgctxt "model:ir.action,name:act_line_consumption_create"
+msgid "Create Line Consumptions"
+msgstr "Create Line Consumptions"
+
+msgctxt "model:ir.action,name:act_recurrence_rule_set_form"
+msgid "Subscription Recurrence Rule Sets"
+msgstr "Subscription Recurrence Rule Sets"
+
+msgctxt "model:ir.action,name:act_service_form"
+msgid "Subscription Services"
+msgstr "Subscription Services"
+
+msgctxt "model:ir.action,name:act_subscription_form"
+msgid "Subscriptions"
+msgstr "Subscriptions"
+
+msgctxt "model:ir.action,name:act_subscription_invoice_relate"
+msgid "Invoices"
+msgstr ""
+
+msgctxt "model:ir.action,name:act_subscription_line_consumption_form"
+msgid "Consumptions"
+msgstr "Consumptions"
+
+msgctxt ""
+"model:ir.action,name:act_subscription_line_consumption_subscription_line_relate"
+msgid "Consumptions"
+msgstr "Consumptions"
+
+msgctxt ""
+"model:ir.action,name:act_subscription_line_consumption_subscription_relate"
+msgid "Consumptions"
+msgstr "Consumptions"
+
+msgctxt "model:ir.action,name:act_subscription_party_relate"
+msgid "Subscriptions"
+msgstr "Subscriptions"
+
+msgctxt ""
+"model:ir.action.act_window.domain,name:act_subscription_form_domain_all"
+msgid "All"
+msgstr "All"
+
+msgctxt ""
+"model:ir.action.act_window.domain,name:act_subscription_form_domain_draft"
+msgid "Draft"
+msgstr "Draft"
+
+msgctxt ""
+"model:ir.action.act_window.domain,name:act_subscription_form_domain_quotation"
+msgid "Quotation"
+msgstr "Quotation"
+
+msgctxt ""
+"model:ir.action.act_window.domain,name:act_subscription_form_domain_running"
+msgid "Running"
+msgstr "Running"
+
+msgctxt "model:ir.message,text:msg_consumption_delete_invoiced"
+msgid "You cannot delete invoiced consumption \"%(consumption)s\"."
+msgstr ""
+
+msgctxt ""
+"model:ir.message,text:msg_consumption_invoice_missing_account_revenue"
+msgid ""
+"To invoice consumptions you must define an account revenue for product "
+"\"%(product)s\"."
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_consumption_modify_invoiced"
+msgid "You cannot modify invoiced consumption \"%(consumption)s\"."
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_consumption_recurrence_invalid"
+msgid ""
+"The consumption recurrence of line \"%(line)s\" of subscription "
+"\"%(subscription)s\" does not generate any occurrence."
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_erase_party_pending_subscription"
+msgid ""
+"You cannot erase party \"%(party)s\" while they have pending subscriptions "
+"with company \"%(company)s\"."
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_invoice_recurrence_invalid"
+msgid ""
+"The invoice recurrence of subscription \"%(subscription)s\" does not "
+"generate any occurrence."
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_recurrence_rule_invalid_by"
+msgid ""
+"Invalid \"%(field)s\" \"%(value)s\" in recurence rule "
+"\"%(recurrence_rule)s\" with exception \"%(exception)s\"."
+msgstr ""
+
+msgctxt "model:ir.model.button,string:subscription_cancel_button"
+msgid "Cancel"
+msgstr "Cancel"
+
+msgctxt "model:ir.model.button,string:subscription_draft_button"
+msgid "Draft"
+msgstr "Draft"
+
+msgctxt "model:ir.model.button,string:subscription_quote_button"
+msgid "Quote"
+msgstr "Quote"
+
+msgctxt "model:ir.model.button,string:subscription_run_button"
+msgid "Run"
+msgstr "Run"
+
+msgctxt "model:ir.rule.group,name:rule_group_subscription_companies"
+msgid "User in companies"
+msgstr ""
+
+msgctxt "model:ir.sequence,name:sequence_subscription"
+msgid "Subscription"
+msgstr "Subscription"
+
+msgctxt "model:ir.sequence.type,name:sequence_type_subscription"
+msgid "Subscription"
+msgstr "Subscription"
+
+#, fuzzy
+msgctxt "model:ir.ui.menu,name:menu_configuration"
+msgid "Subscription"
+msgstr "Subscription"
+
+msgctxt "model:ir.ui.menu,name:menu_create_invoice"
+msgid "Create Subscription Invoices"
+msgstr "Create Subscription Invoices"
+
+msgctxt "model:ir.ui.menu,name:menu_line_consumption_create"
+msgid "Create Line Consumptions"
+msgstr "Create Line Consumptions"
+
+msgctxt "model:ir.ui.menu,name:menu_recurrence_rule_set_form"
+msgid "Subscription Recurrence Rule Sets"
+msgstr "Subscription Recurrence Rule Sets"
+
+msgctxt "model:ir.ui.menu,name:menu_service_form"
+msgid "Subscription Services"
+msgstr "Subscription Services"
+
+msgctxt "model:ir.ui.menu,name:menu_subscription_form"
+msgid "Subscriptions"
+msgstr "Subscriptions"
+
+#, fuzzy
+msgctxt "model:sale.subscription,name:"
+msgid "Subscription"
+msgstr "Subscription"
+
+#, fuzzy
+msgctxt "model:sale.subscription.create_invoice.start,name:"
+msgid "Create Subscription Invoice"
+msgstr "Create Subscription Invoices"
+
+#, fuzzy
+msgctxt "model:sale.subscription.line,name:"
+msgid "Subscription Line"
+msgstr "Subscription Services"
+
+#, fuzzy
+msgctxt "model:sale.subscription.line.consumption,name:"
+msgid "Subscription Line Consumption"
+msgstr "Generate Subscription Line Consumptions"
+
+#, fuzzy
+msgctxt "model:sale.subscription.line.consumption.create.start,name:"
+msgid "Create Subscription Line Consumption"
+msgstr "Generate Subscription Line Consumptions"
+
+#, fuzzy
+msgctxt "model:sale.subscription.recurrence.rule,name:"
+msgid "Subscription Recurrence Rule"
+msgstr "Subscription Recurrence Rule Sets"
+
+#, fuzzy
+msgctxt "model:sale.subscription.recurrence.rule.set,name:"
+msgid "Subscription Recurrence Rule Set"
+msgstr "Subscription Recurrence Rule Sets"
+
+#, fuzzy
+msgctxt "model:sale.subscription.service,name:"
+msgid "Subscription Service"
+msgstr "Subscription Services"
+
+#, fuzzy
+msgctxt "selection:ir.cron,method:"
+msgid "Generate Subscription Invoices"
+msgstr "Generate Subscription Invoices"
+
+#, fuzzy
+msgctxt "selection:ir.cron,method:"
+msgid "Generate Subscription Line Consumptions"
+msgstr "Generate Subscription Line Consumptions"
+
+#, fuzzy
+msgctxt "selection:sale.subscription,state:"
+msgid "Cancelled"
+msgstr "Cancel"
+
+msgctxt "selection:sale.subscription,state:"
+msgid "Closed"
+msgstr ""
+
+#, fuzzy
+msgctxt "selection:sale.subscription,state:"
+msgid "Draft"
+msgstr "Draft"
+
+#, fuzzy
+msgctxt "selection:sale.subscription,state:"
+msgid "Quotation"
+msgstr "Quotation"
+
+#, fuzzy
+msgctxt "selection:sale.subscription,state:"
+msgid "Running"
+msgstr "Running"
+
+msgctxt "selection:sale.subscription.recurrence.rule,freq:"
+msgid "Daily"
+msgstr ""
+
+msgctxt "selection:sale.subscription.recurrence.rule,freq:"
+msgid "Monthly"
+msgstr ""
+
+msgctxt "selection:sale.subscription.recurrence.rule,freq:"
+msgid "Weekly"
+msgstr ""
+
+msgctxt "selection:sale.subscription.recurrence.rule,freq:"
+msgid "Yearly"
+msgstr ""
+
+#, fuzzy
+msgctxt "view:sale.subscription.create_invoice.start:"
+msgid "Create Subscription Invoices for date"
+msgstr "Create Subscription Invoices"
+
+#, fuzzy
+msgctxt "view:sale.subscription.line.consumption.create.start:"
+msgid "Create Subscription Line Consumptions for date"
+msgstr "Generate Subscription Line Consumptions"
+
+msgctxt "view:sale.subscription.line:"
+msgid "General"
+msgstr ""
+
+msgctxt "view:sale.subscription:"
+msgid "Other Info"
+msgstr ""
+
+#, fuzzy
+msgctxt "view:sale.subscription:"
+msgid "Subscription"
+msgstr "Subscription"
+
+msgctxt "wizard_button:sale.subscription.create_invoice,start,create_:"
+msgid "Create"
+msgstr ""
+
+#, fuzzy
+msgctxt "wizard_button:sale.subscription.create_invoice,start,end:"
+msgid "Cancel"
+msgstr "Cancel"
+
+msgctxt ""
+"wizard_button:sale.subscription.line.consumption.create,start,create_:"
+msgid "Create"
+msgstr ""
+
+#, fuzzy
+msgctxt "wizard_button:sale.subscription.line.consumption.create,start,end:"
+msgid "Cancel"
+msgstr "Cancel"
diff --git a/modules/sale_subscription/locale/sl.po b/modules/sale_subscription/locale/sl.po
new file mode 100644
index 0000000000..992dedeac1
--- /dev/null
+++ b/modules/sale_subscription/locale/sl.po
@@ -0,0 +1,617 @@
+#
+msgid ""
+msgstr "Content-Type: text/plain; charset=utf-8\n"
+
+msgctxt "field:sale.configuration,subscription_sequence:"
+msgid "Subscription Sequence"
+msgstr "Štetje naročnin"
+
+msgctxt "field:sale.configuration.sequence,subscription_sequence:"
+msgid "Subscription Sequence"
+msgstr "Štetje naročnin"
+
+msgctxt "field:sale.subscription,company:"
+msgid "Company"
+msgstr "Družba"
+
+msgctxt "field:sale.subscription,contact:"
+msgid "Contact"
+msgstr ""
+
+msgctxt "field:sale.subscription,currency:"
+msgid "Currency"
+msgstr "Valuta"
+
+msgctxt "field:sale.subscription,description:"
+msgid "Description"
+msgstr "Opis"
+
+msgctxt "field:sale.subscription,end_date:"
+msgid "End Date"
+msgstr "Konec"
+
+msgctxt "field:sale.subscription,invoice_address:"
+msgid "Invoice Address"
+msgstr "Naslov plačnika"
+
+#, fuzzy
+msgctxt "field:sale.subscription,invoice_party:"
+msgid "Invoice Party"
+msgstr "Začetek zaračunavanja"
+
+msgctxt "field:sale.subscription,invoice_recurrence:"
+msgid "Invoice Recurrence"
+msgstr "Perioda zaračunavanja"
+
+msgctxt "field:sale.subscription,invoice_start_date:"
+msgid "Invoice Start Date"
+msgstr "Začetek zaračunavanja"
+
+msgctxt "field:sale.subscription,lines:"
+msgid "Lines"
+msgstr "Postavke"
+
+msgctxt "field:sale.subscription,next_invoice_date:"
+msgid "Next Invoice Date"
+msgstr "Datum naslednjega računa"
+
+msgctxt "field:sale.subscription,number:"
+msgid "Number"
+msgstr "Številka"
+
+msgctxt "field:sale.subscription,party:"
+msgid "Party"
+msgstr "Partner"
+
+msgctxt "field:sale.subscription,payment_term:"
+msgid "Payment Term"
+msgstr "Plačilni pogoj"
+
+#, fuzzy
+msgctxt "field:sale.subscription,quoted_by:"
+msgid "Quoted By"
+msgstr "Quote"
+
+msgctxt "field:sale.subscription,reference:"
+msgid "Reference"
+msgstr "Sklic"
+
+msgctxt "field:sale.subscription,run_by:"
+msgid "Run By"
+msgstr ""
+
+msgctxt "field:sale.subscription,start_date:"
+msgid "Start Date"
+msgstr "Začetek"
+
+msgctxt "field:sale.subscription,state:"
+msgid "State"
+msgstr "Stanje"
+
+msgctxt "field:sale.subscription.create_invoice.start,date:"
+msgid "Date"
+msgstr "Datum"
+
+#, fuzzy
+msgctxt "field:sale.subscription.line,company:"
+msgid "Company"
+msgstr "Družba"
+
+#, fuzzy
+msgctxt "field:sale.subscription.line,consumed_until:"
+msgid "Consumed until"
+msgstr "Porabljeno"
+
+msgctxt "field:sale.subscription.line,consumption_delay:"
+msgid "Consumption Delay"
+msgstr "Zamki porabe"
+
+msgctxt "field:sale.subscription.line,consumption_recurrence:"
+msgid "Consumption Recurrence"
+msgstr "Perioda porabe"
+
+#, fuzzy
+msgctxt "field:sale.subscription.line,currency:"
+msgid "Currency"
+msgstr "Valuta"
+
+msgctxt "field:sale.subscription.line,description:"
+msgid "Description"
+msgstr "Opis"
+
+msgctxt "field:sale.subscription.line,end_date:"
+msgid "End Date"
+msgstr "Konec"
+
+msgctxt "field:sale.subscription.line,next_consumption_date:"
+msgid "Next Consumption Date"
+msgstr "Naslednja poraba"
+
+msgctxt "field:sale.subscription.line,next_consumption_date_delayed:"
+msgid "Next Consumption Delayed"
+msgstr "Naslednja poraba z zamikom"
+
+msgctxt "field:sale.subscription.line,quantity:"
+msgid "Quantity"
+msgstr "Količina"
+
+msgctxt "field:sale.subscription.line,service:"
+msgid "Service"
+msgstr "Storitev"
+
+msgctxt "field:sale.subscription.line,service_unit_category:"
+msgid "Service Unit Category"
+msgstr "Kategorija ME storitve"
+
+msgctxt "field:sale.subscription.line,start_date:"
+msgid "Start Date"
+msgstr "Začetek"
+
+msgctxt "field:sale.subscription.line,subscription:"
+msgid "Subscription"
+msgstr "Naročnina"
+
+msgctxt "field:sale.subscription.line,subscription_end_date:"
+msgid "Subscription End Date"
+msgstr "Konec naročnine"
+
+msgctxt "field:sale.subscription.line,subscription_start_date:"
+msgid "Subscription Start Date"
+msgstr "Začetek naročnine"
+
+msgctxt "field:sale.subscription.line,subscription_state:"
+msgid "Subscription State"
+msgstr "Stanje naročnine"
+
+msgctxt "field:sale.subscription.line,unit:"
+msgid "Unit"
+msgstr "Enota"
+
+msgctxt "field:sale.subscription.line,unit_digits:"
+msgid "Unit Digits"
+msgstr "Decimalke"
+
+msgctxt "field:sale.subscription.line,unit_price:"
+msgid "Unit Price"
+msgstr "Cena enote"
+
+msgctxt "field:sale.subscription.line.consumption,date:"
+msgid "Date"
+msgstr "Datum"
+
+msgctxt "field:sale.subscription.line.consumption,invoice_line:"
+msgid "Invoice Line"
+msgstr "Postavka računa"
+
+msgctxt "field:sale.subscription.line.consumption,line:"
+msgid "Line"
+msgstr "Postavka"
+
+msgctxt "field:sale.subscription.line.consumption,quantity:"
+msgid "Quantity"
+msgstr "Količina"
+
+msgctxt "field:sale.subscription.line.consumption,unit_digits:"
+msgid "Unit Digits"
+msgstr "Decimalke"
+
+msgctxt "field:sale.subscription.line.consumption.create.start,date:"
+msgid "Date"
+msgstr "Datum"
+
+msgctxt "field:sale.subscription.recurrence.rule,bymonth:"
+msgid "By Month"
+msgstr "Po mesecih"
+
+msgctxt "field:sale.subscription.recurrence.rule,bymonthday:"
+msgid "By Month Day"
+msgstr "Po dnevih v mesecu"
+
+msgctxt "field:sale.subscription.recurrence.rule,bysetpos:"
+msgid "By Position"
+msgstr "Po položaju znotraj periode"
+
+msgctxt "field:sale.subscription.recurrence.rule,byweekday:"
+msgid "By Week Day"
+msgstr "Po dnevih v tednu"
+
+msgctxt "field:sale.subscription.recurrence.rule,byweekno:"
+msgid "By Week Number"
+msgstr "Po tednih"
+
+msgctxt "field:sale.subscription.recurrence.rule,byyearday:"
+msgid "By Year Day"
+msgstr "Po dnevih v letu"
+
+msgctxt "field:sale.subscription.recurrence.rule,exclusive:"
+msgid "Exclusive"
+msgstr "Izključno"
+
+msgctxt "field:sale.subscription.recurrence.rule,freq:"
+msgid "Frequency"
+msgstr "Pogostost"
+
+msgctxt "field:sale.subscription.recurrence.rule,interval:"
+msgid "Interval"
+msgstr "Razmik"
+
+msgctxt "field:sale.subscription.recurrence.rule,set_:"
+msgid "Set"
+msgstr "Niz"
+
+#, fuzzy
+msgctxt "field:sale.subscription.recurrence.rule,week_start_day:"
+msgid "Week Start Day"
+msgstr "Začetek tedna"
+
+msgctxt "field:sale.subscription.recurrence.rule.set,name:"
+msgid "Name"
+msgstr "Naziv"
+
+msgctxt "field:sale.subscription.recurrence.rule.set,rules:"
+msgid "Rules"
+msgstr "Pravila"
+
+msgctxt "field:sale.subscription.service,consumption_delay:"
+msgid "Consumption Delay"
+msgstr "Zamik porabe"
+
+msgctxt "field:sale.subscription.service,consumption_recurrence:"
+msgid "Consumption Recurrence"
+msgstr "Ponovitev porabe"
+
+msgctxt "field:sale.subscription.service,product:"
+msgid "Product"
+msgstr "Izdelek"
+
+msgctxt "help:sale.subscription,company:"
+msgid "Make the subscription belong to the company."
+msgstr "Poveži naročnino z družbo."
+
+msgctxt "help:sale.subscription,number:"
+msgid "The main identification of the subscription."
+msgstr "Glavni identifikator naročnine."
+
+msgctxt "help:sale.subscription,party:"
+msgid "The party who subscribes."
+msgstr "Naročnik"
+
+msgctxt "help:sale.subscription,reference:"
+msgid "The identification of an external origin."
+msgstr "Identifikacija zunanjega vira."
+
+msgctxt "help:sale.subscription,state:"
+msgid "The current state of the subscription."
+msgstr "Stanje naroćnine"
+
+msgctxt "help:sale.subscription.line,subscription:"
+msgid "Add the line below the subscription."
+msgstr "Dodajanje postavke naročnini."
+
+msgctxt "help:sale.subscription.recurrence.rule,bymonth:"
+msgid "A comma separated list of integers."
+msgstr "Z vejico loćen seznam celih števil, ki predstavljajo mesece."
+
+msgctxt "help:sale.subscription.recurrence.rule,bymonthday:"
+msgid "A comma separated list of integers."
+msgstr "Z vejico loćen seznam celih števil, ki predstavljajo dneve v mesecu."
+
+msgctxt "help:sale.subscription.recurrence.rule,bysetpos:"
+msgid "A comma separated list of integers."
+msgstr ""
+"Z vejico loćen seznam celih števil, ki predstavljajo položaj znotraj "
+"obdobja."
+
+msgctxt "help:sale.subscription.recurrence.rule,byweekday:"
+msgid "A comma separated list of integers or weekday (MO, TU etc)."
+msgstr ""
+"Z vejico loćen seznam celih števil ali kratic, ki predstavljajo dneve v "
+"tednu (1,2, ... ali MO, TU, itd)."
+
+msgctxt "help:sale.subscription.recurrence.rule,byweekno:"
+msgid "A comma separated list of integers (ISO8601)."
+msgstr ""
+"Z vejico loćen seznam celih števil, ki predstavljajo tedne v letu "
+"(ISO-8601)."
+
+msgctxt "help:sale.subscription.recurrence.rule,byyearday:"
+msgid "A comma separated list of integers."
+msgstr "Z vejico loćen seznam celih števil, ki predstavljajo dneve v letu."
+
+msgctxt "help:sale.subscription.recurrence.rule,set_:"
+msgid "Add the rule below the set."
+msgstr "Dodajanje pravila nizu pravil."
+
+msgctxt "help:sale.subscription.recurrence.rule.set,name:"
+msgid "The main identifier of the rule set."
+msgstr "Glavni identifikator niza pravil."
+
+#, fuzzy
+msgctxt "model:ir.action,name:act_create_invoice"
+msgid "Create Subscription Invoices"
+msgstr "Create Subscription Invoices"
+
+#, fuzzy
+msgctxt "model:ir.action,name:act_line_consumption_create"
+msgid "Create Line Consumptions"
+msgstr "Create Line Consumptions"
+
+#, fuzzy
+msgctxt "model:ir.action,name:act_recurrence_rule_set_form"
+msgid "Subscription Recurrence Rule Sets"
+msgstr "Subscription Recurrence Rule Sets"
+
+#, fuzzy
+msgctxt "model:ir.action,name:act_service_form"
+msgid "Subscription Services"
+msgstr "Subscription Services"
+
+#, fuzzy
+msgctxt "model:ir.action,name:act_subscription_form"
+msgid "Subscriptions"
+msgstr "Subscriptions"
+
+msgctxt "model:ir.action,name:act_subscription_invoice_relate"
+msgid "Invoices"
+msgstr ""
+
+#, fuzzy
+msgctxt "model:ir.action,name:act_subscription_line_consumption_form"
+msgid "Consumptions"
+msgstr "Consumptions"
+
+#, fuzzy
+msgctxt ""
+"model:ir.action,name:act_subscription_line_consumption_subscription_line_relate"
+msgid "Consumptions"
+msgstr "Consumptions"
+
+#, fuzzy
+msgctxt ""
+"model:ir.action,name:act_subscription_line_consumption_subscription_relate"
+msgid "Consumptions"
+msgstr "Consumptions"
+
+#, fuzzy
+msgctxt "model:ir.action,name:act_subscription_party_relate"
+msgid "Subscriptions"
+msgstr "Subscriptions"
+
+#, fuzzy
+msgctxt ""
+"model:ir.action.act_window.domain,name:act_subscription_form_domain_all"
+msgid "All"
+msgstr "All"
+
+#, fuzzy
+msgctxt ""
+"model:ir.action.act_window.domain,name:act_subscription_form_domain_draft"
+msgid "Draft"
+msgstr "Draft"
+
+#, fuzzy
+msgctxt ""
+"model:ir.action.act_window.domain,name:act_subscription_form_domain_quotation"
+msgid "Quotation"
+msgstr "Quotation"
+
+#, fuzzy
+msgctxt ""
+"model:ir.action.act_window.domain,name:act_subscription_form_domain_running"
+msgid "Running"
+msgstr "Running"
+
+msgctxt "model:ir.message,text:msg_consumption_delete_invoiced"
+msgid "You cannot delete invoiced consumption \"%(consumption)s\"."
+msgstr ""
+
+msgctxt ""
+"model:ir.message,text:msg_consumption_invoice_missing_account_revenue"
+msgid ""
+"To invoice consumptions you must define an account revenue for product "
+"\"%(product)s\"."
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_consumption_modify_invoiced"
+msgid "You cannot modify invoiced consumption \"%(consumption)s\"."
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_consumption_recurrence_invalid"
+msgid ""
+"The consumption recurrence of line \"%(line)s\" of subscription "
+"\"%(subscription)s\" does not generate any occurrence."
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_erase_party_pending_subscription"
+msgid ""
+"You cannot erase party \"%(party)s\" while they have pending subscriptions "
+"with company \"%(company)s\"."
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_invoice_recurrence_invalid"
+msgid ""
+"The invoice recurrence of subscription \"%(subscription)s\" does not "
+"generate any occurrence."
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_recurrence_rule_invalid_by"
+msgid ""
+"Invalid \"%(field)s\" \"%(value)s\" in recurence rule "
+"\"%(recurrence_rule)s\" with exception \"%(exception)s\"."
+msgstr ""
+
+msgctxt "model:ir.model.button,string:subscription_cancel_button"
+msgid "Cancel"
+msgstr "Cancel"
+
+msgctxt "model:ir.model.button,string:subscription_draft_button"
+msgid "Draft"
+msgstr "Draft"
+
+msgctxt "model:ir.model.button,string:subscription_quote_button"
+msgid "Quote"
+msgstr "Quote"
+
+msgctxt "model:ir.model.button,string:subscription_run_button"
+msgid "Run"
+msgstr "Run"
+
+msgctxt "model:ir.rule.group,name:rule_group_subscription_companies"
+msgid "User in companies"
+msgstr ""
+
+#, fuzzy
+msgctxt "model:ir.sequence,name:sequence_subscription"
+msgid "Subscription"
+msgstr "Subscription"
+
+#, fuzzy
+msgctxt "model:ir.sequence.type,name:sequence_type_subscription"
+msgid "Subscription"
+msgstr "Subscription"
+
+#, fuzzy
+msgctxt "model:ir.ui.menu,name:menu_configuration"
+msgid "Subscription"
+msgstr "Naročnina"
+
+#, fuzzy
+msgctxt "model:ir.ui.menu,name:menu_create_invoice"
+msgid "Create Subscription Invoices"
+msgstr "Create Subscription Invoices"
+
+#, fuzzy
+msgctxt "model:ir.ui.menu,name:menu_line_consumption_create"
+msgid "Create Line Consumptions"
+msgstr "Create Line Consumptions"
+
+#, fuzzy
+msgctxt "model:ir.ui.menu,name:menu_recurrence_rule_set_form"
+msgid "Subscription Recurrence Rule Sets"
+msgstr "Subscription Recurrence Rule Sets"
+
+#, fuzzy
+msgctxt "model:ir.ui.menu,name:menu_service_form"
+msgid "Subscription Services"
+msgstr "Subscription Services"
+
+#, fuzzy
+msgctxt "model:ir.ui.menu,name:menu_subscription_form"
+msgid "Subscriptions"
+msgstr "Subscriptions"
+
+msgctxt "model:sale.subscription,name:"
+msgid "Subscription"
+msgstr "Naročnina"
+
+msgctxt "model:sale.subscription.create_invoice.start,name:"
+msgid "Create Subscription Invoice"
+msgstr "Izdelava računa naročnine"
+
+msgctxt "model:sale.subscription.line,name:"
+msgid "Subscription Line"
+msgstr "Postavka naročnine"
+
+msgctxt "model:sale.subscription.line.consumption,name:"
+msgid "Subscription Line Consumption"
+msgstr "Poraba naročniške postavke"
+
+msgctxt "model:sale.subscription.line.consumption.create.start,name:"
+msgid "Create Subscription Line Consumption"
+msgstr "Izdelava porabe naročniške postavke"
+
+msgctxt "model:sale.subscription.recurrence.rule,name:"
+msgid "Subscription Recurrence Rule"
+msgstr "Pravilo za periodičnost naročnine"
+
+msgctxt "model:sale.subscription.recurrence.rule.set,name:"
+msgid "Subscription Recurrence Rule Set"
+msgstr "Niz pravil za periodičnost naročnine"
+
+msgctxt "model:sale.subscription.service,name:"
+msgid "Subscription Service"
+msgstr "Naročniška storitev"
+
+#, fuzzy
+msgctxt "selection:ir.cron,method:"
+msgid "Generate Subscription Invoices"
+msgstr "Generate Subscription Invoices"
+
+#, fuzzy
+msgctxt "selection:ir.cron,method:"
+msgid "Generate Subscription Line Consumptions"
+msgstr "Generate Subscription Line Consumptions"
+
+#, fuzzy
+msgctxt "selection:sale.subscription,state:"
+msgid "Cancelled"
+msgstr "Preklicano"
+
+msgctxt "selection:sale.subscription,state:"
+msgid "Closed"
+msgstr "Zaprto"
+
+msgctxt "selection:sale.subscription,state:"
+msgid "Draft"
+msgstr "V pripravi"
+
+msgctxt "selection:sale.subscription,state:"
+msgid "Quotation"
+msgstr "Ponudba"
+
+msgctxt "selection:sale.subscription,state:"
+msgid "Running"
+msgstr "Tekoče"
+
+msgctxt "selection:sale.subscription.recurrence.rule,freq:"
+msgid "Daily"
+msgstr "Dnevno"
+
+msgctxt "selection:sale.subscription.recurrence.rule,freq:"
+msgid "Monthly"
+msgstr "Mesečno"
+
+msgctxt "selection:sale.subscription.recurrence.rule,freq:"
+msgid "Weekly"
+msgstr "Tedensko"
+
+msgctxt "selection:sale.subscription.recurrence.rule,freq:"
+msgid "Yearly"
+msgstr "Letno"
+
+msgctxt "view:sale.subscription.create_invoice.start:"
+msgid "Create Subscription Invoices for date"
+msgstr "Zaračunavanje naročnine na dan"
+
+msgctxt "view:sale.subscription.line.consumption.create.start:"
+msgid "Create Subscription Line Consumptions for date"
+msgstr "Poraba naročnine na dan"
+
+msgctxt "view:sale.subscription.line:"
+msgid "General"
+msgstr "Splošno"
+
+msgctxt "view:sale.subscription:"
+msgid "Other Info"
+msgstr "Drugo"
+
+msgctxt "view:sale.subscription:"
+msgid "Subscription"
+msgstr "Naročnina"
+
+msgctxt "wizard_button:sale.subscription.create_invoice,start,create_:"
+msgid "Create"
+msgstr "Izdelava"
+
+msgctxt "wizard_button:sale.subscription.create_invoice,start,end:"
+msgid "Cancel"
+msgstr "Prekliči"
+
+msgctxt ""
+"wizard_button:sale.subscription.line.consumption.create,start,create_:"
+msgid "Create"
+msgstr "Izdelava"
+
+msgctxt "wizard_button:sale.subscription.line.consumption.create,start,end:"
+msgid "Cancel"
+msgstr "Prekliči"
diff --git a/modules/sale_subscription/locale/tr.po b/modules/sale_subscription/locale/tr.po
new file mode 100644
index 0000000000..4e46c4f6c0
--- /dev/null
+++ b/modules/sale_subscription/locale/tr.po
@@ -0,0 +1,611 @@
+#
+msgid ""
+msgstr "Content-Type: text/plain; charset=utf-8\n"
+
+#, fuzzy
+msgctxt "field:sale.configuration,subscription_sequence:"
+msgid "Subscription Sequence"
+msgstr "Subscription Services"
+
+#, fuzzy
+msgctxt "field:sale.configuration.sequence,subscription_sequence:"
+msgid "Subscription Sequence"
+msgstr "Subscription Services"
+
+msgctxt "field:sale.subscription,company:"
+msgid "Company"
+msgstr ""
+
+msgctxt "field:sale.subscription,contact:"
+msgid "Contact"
+msgstr ""
+
+msgctxt "field:sale.subscription,currency:"
+msgid "Currency"
+msgstr ""
+
+#, fuzzy
+msgctxt "field:sale.subscription,description:"
+msgid "Description"
+msgstr "Subscription"
+
+msgctxt "field:sale.subscription,end_date:"
+msgid "End Date"
+msgstr ""
+
+msgctxt "field:sale.subscription,invoice_address:"
+msgid "Invoice Address"
+msgstr ""
+
+msgctxt "field:sale.subscription,invoice_party:"
+msgid "Invoice Party"
+msgstr ""
+
+msgctxt "field:sale.subscription,invoice_recurrence:"
+msgid "Invoice Recurrence"
+msgstr ""
+
+msgctxt "field:sale.subscription,invoice_start_date:"
+msgid "Invoice Start Date"
+msgstr ""
+
+msgctxt "field:sale.subscription,lines:"
+msgid "Lines"
+msgstr ""
+
+msgctxt "field:sale.subscription,next_invoice_date:"
+msgid "Next Invoice Date"
+msgstr ""
+
+msgctxt "field:sale.subscription,number:"
+msgid "Number"
+msgstr ""
+
+msgctxt "field:sale.subscription,party:"
+msgid "Party"
+msgstr ""
+
+msgctxt "field:sale.subscription,payment_term:"
+msgid "Payment Term"
+msgstr ""
+
+#, fuzzy
+msgctxt "field:sale.subscription,quoted_by:"
+msgid "Quoted By"
+msgstr "Quote"
+
+msgctxt "field:sale.subscription,reference:"
+msgid "Reference"
+msgstr ""
+
+msgctxt "field:sale.subscription,run_by:"
+msgid "Run By"
+msgstr ""
+
+msgctxt "field:sale.subscription,start_date:"
+msgid "Start Date"
+msgstr ""
+
+msgctxt "field:sale.subscription,state:"
+msgid "State"
+msgstr ""
+
+msgctxt "field:sale.subscription.create_invoice.start,date:"
+msgid "Date"
+msgstr ""
+
+msgctxt "field:sale.subscription.line,company:"
+msgid "Company"
+msgstr ""
+
+#, fuzzy
+msgctxt "field:sale.subscription.line,consumed_until:"
+msgid "Consumed until"
+msgstr "Consumptions"
+
+msgctxt "field:sale.subscription.line,consumption_delay:"
+msgid "Consumption Delay"
+msgstr ""
+
+msgctxt "field:sale.subscription.line,consumption_recurrence:"
+msgid "Consumption Recurrence"
+msgstr ""
+
+msgctxt "field:sale.subscription.line,currency:"
+msgid "Currency"
+msgstr ""
+
+#, fuzzy
+msgctxt "field:sale.subscription.line,description:"
+msgid "Description"
+msgstr "Subscription"
+
+msgctxt "field:sale.subscription.line,end_date:"
+msgid "End Date"
+msgstr ""
+
+msgctxt "field:sale.subscription.line,next_consumption_date:"
+msgid "Next Consumption Date"
+msgstr ""
+
+msgctxt "field:sale.subscription.line,next_consumption_date_delayed:"
+msgid "Next Consumption Delayed"
+msgstr ""
+
+msgctxt "field:sale.subscription.line,quantity:"
+msgid "Quantity"
+msgstr ""
+
+msgctxt "field:sale.subscription.line,service:"
+msgid "Service"
+msgstr ""
+
+msgctxt "field:sale.subscription.line,service_unit_category:"
+msgid "Service Unit Category"
+msgstr ""
+
+msgctxt "field:sale.subscription.line,start_date:"
+msgid "Start Date"
+msgstr ""
+
+#, fuzzy
+msgctxt "field:sale.subscription.line,subscription:"
+msgid "Subscription"
+msgstr "Subscription"
+
+#, fuzzy
+msgctxt "field:sale.subscription.line,subscription_end_date:"
+msgid "Subscription End Date"
+msgstr "Subscription Services"
+
+#, fuzzy
+msgctxt "field:sale.subscription.line,subscription_start_date:"
+msgid "Subscription Start Date"
+msgstr "Subscription Services"
+
+#, fuzzy
+msgctxt "field:sale.subscription.line,subscription_state:"
+msgid "Subscription State"
+msgstr "Subscription Services"
+
+msgctxt "field:sale.subscription.line,unit:"
+msgid "Unit"
+msgstr ""
+
+msgctxt "field:sale.subscription.line,unit_digits:"
+msgid "Unit Digits"
+msgstr ""
+
+msgctxt "field:sale.subscription.line,unit_price:"
+msgid "Unit Price"
+msgstr ""
+
+msgctxt "field:sale.subscription.line.consumption,date:"
+msgid "Date"
+msgstr ""
+
+msgctxt "field:sale.subscription.line.consumption,invoice_line:"
+msgid "Invoice Line"
+msgstr ""
+
+msgctxt "field:sale.subscription.line.consumption,line:"
+msgid "Line"
+msgstr ""
+
+msgctxt "field:sale.subscription.line.consumption,quantity:"
+msgid "Quantity"
+msgstr ""
+
+msgctxt "field:sale.subscription.line.consumption,unit_digits:"
+msgid "Unit Digits"
+msgstr ""
+
+msgctxt "field:sale.subscription.line.consumption.create.start,date:"
+msgid "Date"
+msgstr ""
+
+msgctxt "field:sale.subscription.recurrence.rule,bymonth:"
+msgid "By Month"
+msgstr ""
+
+msgctxt "field:sale.subscription.recurrence.rule,bymonthday:"
+msgid "By Month Day"
+msgstr ""
+
+msgctxt "field:sale.subscription.recurrence.rule,bysetpos:"
+msgid "By Position"
+msgstr ""
+
+msgctxt "field:sale.subscription.recurrence.rule,byweekday:"
+msgid "By Week Day"
+msgstr ""
+
+msgctxt "field:sale.subscription.recurrence.rule,byweekno:"
+msgid "By Week Number"
+msgstr ""
+
+msgctxt "field:sale.subscription.recurrence.rule,byyearday:"
+msgid "By Year Day"
+msgstr ""
+
+msgctxt "field:sale.subscription.recurrence.rule,exclusive:"
+msgid "Exclusive"
+msgstr ""
+
+msgctxt "field:sale.subscription.recurrence.rule,freq:"
+msgid "Frequency"
+msgstr ""
+
+msgctxt "field:sale.subscription.recurrence.rule,interval:"
+msgid "Interval"
+msgstr ""
+
+msgctxt "field:sale.subscription.recurrence.rule,set_:"
+msgid "Set"
+msgstr ""
+
+msgctxt "field:sale.subscription.recurrence.rule,week_start_day:"
+msgid "Week Start Day"
+msgstr ""
+
+msgctxt "field:sale.subscription.recurrence.rule.set,name:"
+msgid "Name"
+msgstr ""
+
+msgctxt "field:sale.subscription.recurrence.rule.set,rules:"
+msgid "Rules"
+msgstr ""
+
+msgctxt "field:sale.subscription.service,consumption_delay:"
+msgid "Consumption Delay"
+msgstr ""
+
+msgctxt "field:sale.subscription.service,consumption_recurrence:"
+msgid "Consumption Recurrence"
+msgstr ""
+
+msgctxt "field:sale.subscription.service,product:"
+msgid "Product"
+msgstr ""
+
+msgctxt "help:sale.subscription,company:"
+msgid "Make the subscription belong to the company."
+msgstr ""
+
+msgctxt "help:sale.subscription,number:"
+msgid "The main identification of the subscription."
+msgstr ""
+
+msgctxt "help:sale.subscription,party:"
+msgid "The party who subscribes."
+msgstr ""
+
+msgctxt "help:sale.subscription,reference:"
+msgid "The identification of an external origin."
+msgstr ""
+
+msgctxt "help:sale.subscription,state:"
+msgid "The current state of the subscription."
+msgstr ""
+
+msgctxt "help:sale.subscription.line,subscription:"
+msgid "Add the line below the subscription."
+msgstr ""
+
+msgctxt "help:sale.subscription.recurrence.rule,bymonth:"
+msgid "A comma separated list of integers."
+msgstr ""
+
+msgctxt "help:sale.subscription.recurrence.rule,bymonthday:"
+msgid "A comma separated list of integers."
+msgstr ""
+
+msgctxt "help:sale.subscription.recurrence.rule,bysetpos:"
+msgid "A comma separated list of integers."
+msgstr ""
+
+msgctxt "help:sale.subscription.recurrence.rule,byweekday:"
+msgid "A comma separated list of integers or weekday (MO, TU etc)."
+msgstr ""
+
+msgctxt "help:sale.subscription.recurrence.rule,byweekno:"
+msgid "A comma separated list of integers (ISO8601)."
+msgstr ""
+
+msgctxt "help:sale.subscription.recurrence.rule,byyearday:"
+msgid "A comma separated list of integers."
+msgstr ""
+
+msgctxt "help:sale.subscription.recurrence.rule,set_:"
+msgid "Add the rule below the set."
+msgstr ""
+
+msgctxt "help:sale.subscription.recurrence.rule.set,name:"
+msgid "The main identifier of the rule set."
+msgstr ""
+
+msgctxt "model:ir.action,name:act_create_invoice"
+msgid "Create Subscription Invoices"
+msgstr "Create Subscription Invoices"
+
+msgctxt "model:ir.action,name:act_line_consumption_create"
+msgid "Create Line Consumptions"
+msgstr "Create Line Consumptions"
+
+msgctxt "model:ir.action,name:act_recurrence_rule_set_form"
+msgid "Subscription Recurrence Rule Sets"
+msgstr "Subscription Recurrence Rule Sets"
+
+msgctxt "model:ir.action,name:act_service_form"
+msgid "Subscription Services"
+msgstr "Subscription Services"
+
+msgctxt "model:ir.action,name:act_subscription_form"
+msgid "Subscriptions"
+msgstr "Subscriptions"
+
+msgctxt "model:ir.action,name:act_subscription_invoice_relate"
+msgid "Invoices"
+msgstr ""
+
+msgctxt "model:ir.action,name:act_subscription_line_consumption_form"
+msgid "Consumptions"
+msgstr "Consumptions"
+
+msgctxt ""
+"model:ir.action,name:act_subscription_line_consumption_subscription_line_relate"
+msgid "Consumptions"
+msgstr "Consumptions"
+
+msgctxt ""
+"model:ir.action,name:act_subscription_line_consumption_subscription_relate"
+msgid "Consumptions"
+msgstr "Consumptions"
+
+msgctxt "model:ir.action,name:act_subscription_party_relate"
+msgid "Subscriptions"
+msgstr "Subscriptions"
+
+msgctxt ""
+"model:ir.action.act_window.domain,name:act_subscription_form_domain_all"
+msgid "All"
+msgstr "All"
+
+msgctxt ""
+"model:ir.action.act_window.domain,name:act_subscription_form_domain_draft"
+msgid "Draft"
+msgstr "Draft"
+
+msgctxt ""
+"model:ir.action.act_window.domain,name:act_subscription_form_domain_quotation"
+msgid "Quotation"
+msgstr "Quotation"
+
+msgctxt ""
+"model:ir.action.act_window.domain,name:act_subscription_form_domain_running"
+msgid "Running"
+msgstr "Running"
+
+msgctxt "model:ir.message,text:msg_consumption_delete_invoiced"
+msgid "You cannot delete invoiced consumption \"%(consumption)s\"."
+msgstr ""
+
+msgctxt ""
+"model:ir.message,text:msg_consumption_invoice_missing_account_revenue"
+msgid ""
+"To invoice consumptions you must define an account revenue for product "
+"\"%(product)s\"."
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_consumption_modify_invoiced"
+msgid "You cannot modify invoiced consumption \"%(consumption)s\"."
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_consumption_recurrence_invalid"
+msgid ""
+"The consumption recurrence of line \"%(line)s\" of subscription "
+"\"%(subscription)s\" does not generate any occurrence."
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_erase_party_pending_subscription"
+msgid ""
+"You cannot erase party \"%(party)s\" while they have pending subscriptions "
+"with company \"%(company)s\"."
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_invoice_recurrence_invalid"
+msgid ""
+"The invoice recurrence of subscription \"%(subscription)s\" does not "
+"generate any occurrence."
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_recurrence_rule_invalid_by"
+msgid ""
+"Invalid \"%(field)s\" \"%(value)s\" in recurence rule "
+"\"%(recurrence_rule)s\" with exception \"%(exception)s\"."
+msgstr ""
+
+msgctxt "model:ir.model.button,string:subscription_cancel_button"
+msgid "Cancel"
+msgstr "Cancel"
+
+msgctxt "model:ir.model.button,string:subscription_draft_button"
+msgid "Draft"
+msgstr "Draft"
+
+msgctxt "model:ir.model.button,string:subscription_quote_button"
+msgid "Quote"
+msgstr "Quote"
+
+msgctxt "model:ir.model.button,string:subscription_run_button"
+msgid "Run"
+msgstr "Run"
+
+msgctxt "model:ir.rule.group,name:rule_group_subscription_companies"
+msgid "User in companies"
+msgstr ""
+
+msgctxt "model:ir.sequence,name:sequence_subscription"
+msgid "Subscription"
+msgstr "Subscription"
+
+msgctxt "model:ir.sequence.type,name:sequence_type_subscription"
+msgid "Subscription"
+msgstr "Subscription"
+
+#, fuzzy
+msgctxt "model:ir.ui.menu,name:menu_configuration"
+msgid "Subscription"
+msgstr "Subscription"
+
+msgctxt "model:ir.ui.menu,name:menu_create_invoice"
+msgid "Create Subscription Invoices"
+msgstr "Create Subscription Invoices"
+
+msgctxt "model:ir.ui.menu,name:menu_line_consumption_create"
+msgid "Create Line Consumptions"
+msgstr "Create Line Consumptions"
+
+msgctxt "model:ir.ui.menu,name:menu_recurrence_rule_set_form"
+msgid "Subscription Recurrence Rule Sets"
+msgstr "Subscription Recurrence Rule Sets"
+
+msgctxt "model:ir.ui.menu,name:menu_service_form"
+msgid "Subscription Services"
+msgstr "Subscription Services"
+
+msgctxt "model:ir.ui.menu,name:menu_subscription_form"
+msgid "Subscriptions"
+msgstr "Subscriptions"
+
+#, fuzzy
+msgctxt "model:sale.subscription,name:"
+msgid "Subscription"
+msgstr "Subscription"
+
+#, fuzzy
+msgctxt "model:sale.subscription.create_invoice.start,name:"
+msgid "Create Subscription Invoice"
+msgstr "Create Subscription Invoices"
+
+#, fuzzy
+msgctxt "model:sale.subscription.line,name:"
+msgid "Subscription Line"
+msgstr "Subscription Services"
+
+#, fuzzy
+msgctxt "model:sale.subscription.line.consumption,name:"
+msgid "Subscription Line Consumption"
+msgstr "Generate Subscription Line Consumptions"
+
+#, fuzzy
+msgctxt "model:sale.subscription.line.consumption.create.start,name:"
+msgid "Create Subscription Line Consumption"
+msgstr "Generate Subscription Line Consumptions"
+
+#, fuzzy
+msgctxt "model:sale.subscription.recurrence.rule,name:"
+msgid "Subscription Recurrence Rule"
+msgstr "Subscription Recurrence Rule Sets"
+
+#, fuzzy
+msgctxt "model:sale.subscription.recurrence.rule.set,name:"
+msgid "Subscription Recurrence Rule Set"
+msgstr "Subscription Recurrence Rule Sets"
+
+#, fuzzy
+msgctxt "model:sale.subscription.service,name:"
+msgid "Subscription Service"
+msgstr "Subscription Services"
+
+#, fuzzy
+msgctxt "selection:ir.cron,method:"
+msgid "Generate Subscription Invoices"
+msgstr "Generate Subscription Invoices"
+
+#, fuzzy
+msgctxt "selection:ir.cron,method:"
+msgid "Generate Subscription Line Consumptions"
+msgstr "Generate Subscription Line Consumptions"
+
+#, fuzzy
+msgctxt "selection:sale.subscription,state:"
+msgid "Cancelled"
+msgstr "Cancel"
+
+msgctxt "selection:sale.subscription,state:"
+msgid "Closed"
+msgstr ""
+
+#, fuzzy
+msgctxt "selection:sale.subscription,state:"
+msgid "Draft"
+msgstr "Draft"
+
+#, fuzzy
+msgctxt "selection:sale.subscription,state:"
+msgid "Quotation"
+msgstr "Quotation"
+
+#, fuzzy
+msgctxt "selection:sale.subscription,state:"
+msgid "Running"
+msgstr "Running"
+
+msgctxt "selection:sale.subscription.recurrence.rule,freq:"
+msgid "Daily"
+msgstr ""
+
+msgctxt "selection:sale.subscription.recurrence.rule,freq:"
+msgid "Monthly"
+msgstr ""
+
+msgctxt "selection:sale.subscription.recurrence.rule,freq:"
+msgid "Weekly"
+msgstr ""
+
+msgctxt "selection:sale.subscription.recurrence.rule,freq:"
+msgid "Yearly"
+msgstr ""
+
+#, fuzzy
+msgctxt "view:sale.subscription.create_invoice.start:"
+msgid "Create Subscription Invoices for date"
+msgstr "Create Subscription Invoices"
+
+#, fuzzy
+msgctxt "view:sale.subscription.line.consumption.create.start:"
+msgid "Create Subscription Line Consumptions for date"
+msgstr "Generate Subscription Line Consumptions"
+
+msgctxt "view:sale.subscription.line:"
+msgid "General"
+msgstr ""
+
+msgctxt "view:sale.subscription:"
+msgid "Other Info"
+msgstr ""
+
+#, fuzzy
+msgctxt "view:sale.subscription:"
+msgid "Subscription"
+msgstr "Subscription"
+
+msgctxt "wizard_button:sale.subscription.create_invoice,start,create_:"
+msgid "Create"
+msgstr ""
+
+#, fuzzy
+msgctxt "wizard_button:sale.subscription.create_invoice,start,end:"
+msgid "Cancel"
+msgstr "Cancel"
+
+msgctxt ""
+"wizard_button:sale.subscription.line.consumption.create,start,create_:"
+msgid "Create"
+msgstr ""
+
+#, fuzzy
+msgctxt "wizard_button:sale.subscription.line.consumption.create,start,end:"
+msgid "Cancel"
+msgstr "Cancel"
diff --git a/modules/sale_subscription/locale/zh_CN.po b/modules/sale_subscription/locale/zh_CN.po
new file mode 100644
index 0000000000..4e46c4f6c0
--- /dev/null
+++ b/modules/sale_subscription/locale/zh_CN.po
@@ -0,0 +1,611 @@
+#
+msgid ""
+msgstr "Content-Type: text/plain; charset=utf-8\n"
+
+#, fuzzy
+msgctxt "field:sale.configuration,subscription_sequence:"
+msgid "Subscription Sequence"
+msgstr "Subscription Services"
+
+#, fuzzy
+msgctxt "field:sale.configuration.sequence,subscription_sequence:"
+msgid "Subscription Sequence"
+msgstr "Subscription Services"
+
+msgctxt "field:sale.subscription,company:"
+msgid "Company"
+msgstr ""
+
+msgctxt "field:sale.subscription,contact:"
+msgid "Contact"
+msgstr ""
+
+msgctxt "field:sale.subscription,currency:"
+msgid "Currency"
+msgstr ""
+
+#, fuzzy
+msgctxt "field:sale.subscription,description:"
+msgid "Description"
+msgstr "Subscription"
+
+msgctxt "field:sale.subscription,end_date:"
+msgid "End Date"
+msgstr ""
+
+msgctxt "field:sale.subscription,invoice_address:"
+msgid "Invoice Address"
+msgstr ""
+
+msgctxt "field:sale.subscription,invoice_party:"
+msgid "Invoice Party"
+msgstr ""
+
+msgctxt "field:sale.subscription,invoice_recurrence:"
+msgid "Invoice Recurrence"
+msgstr ""
+
+msgctxt "field:sale.subscription,invoice_start_date:"
+msgid "Invoice Start Date"
+msgstr ""
+
+msgctxt "field:sale.subscription,lines:"
+msgid "Lines"
+msgstr ""
+
+msgctxt "field:sale.subscription,next_invoice_date:"
+msgid "Next Invoice Date"
+msgstr ""
+
+msgctxt "field:sale.subscription,number:"
+msgid "Number"
+msgstr ""
+
+msgctxt "field:sale.subscription,party:"
+msgid "Party"
+msgstr ""
+
+msgctxt "field:sale.subscription,payment_term:"
+msgid "Payment Term"
+msgstr ""
+
+#, fuzzy
+msgctxt "field:sale.subscription,quoted_by:"
+msgid "Quoted By"
+msgstr "Quote"
+
+msgctxt "field:sale.subscription,reference:"
+msgid "Reference"
+msgstr ""
+
+msgctxt "field:sale.subscription,run_by:"
+msgid "Run By"
+msgstr ""
+
+msgctxt "field:sale.subscription,start_date:"
+msgid "Start Date"
+msgstr ""
+
+msgctxt "field:sale.subscription,state:"
+msgid "State"
+msgstr ""
+
+msgctxt "field:sale.subscription.create_invoice.start,date:"
+msgid "Date"
+msgstr ""
+
+msgctxt "field:sale.subscription.line,company:"
+msgid "Company"
+msgstr ""
+
+#, fuzzy
+msgctxt "field:sale.subscription.line,consumed_until:"
+msgid "Consumed until"
+msgstr "Consumptions"
+
+msgctxt "field:sale.subscription.line,consumption_delay:"
+msgid "Consumption Delay"
+msgstr ""
+
+msgctxt "field:sale.subscription.line,consumption_recurrence:"
+msgid "Consumption Recurrence"
+msgstr ""
+
+msgctxt "field:sale.subscription.line,currency:"
+msgid "Currency"
+msgstr ""
+
+#, fuzzy
+msgctxt "field:sale.subscription.line,description:"
+msgid "Description"
+msgstr "Subscription"
+
+msgctxt "field:sale.subscription.line,end_date:"
+msgid "End Date"
+msgstr ""
+
+msgctxt "field:sale.subscription.line,next_consumption_date:"
+msgid "Next Consumption Date"
+msgstr ""
+
+msgctxt "field:sale.subscription.line,next_consumption_date_delayed:"
+msgid "Next Consumption Delayed"
+msgstr ""
+
+msgctxt "field:sale.subscription.line,quantity:"
+msgid "Quantity"
+msgstr ""
+
+msgctxt "field:sale.subscription.line,service:"
+msgid "Service"
+msgstr ""
+
+msgctxt "field:sale.subscription.line,service_unit_category:"
+msgid "Service Unit Category"
+msgstr ""
+
+msgctxt "field:sale.subscription.line,start_date:"
+msgid "Start Date"
+msgstr ""
+
+#, fuzzy
+msgctxt "field:sale.subscription.line,subscription:"
+msgid "Subscription"
+msgstr "Subscription"
+
+#, fuzzy
+msgctxt "field:sale.subscription.line,subscription_end_date:"
+msgid "Subscription End Date"
+msgstr "Subscription Services"
+
+#, fuzzy
+msgctxt "field:sale.subscription.line,subscription_start_date:"
+msgid "Subscription Start Date"
+msgstr "Subscription Services"
+
+#, fuzzy
+msgctxt "field:sale.subscription.line,subscription_state:"
+msgid "Subscription State"
+msgstr "Subscription Services"
+
+msgctxt "field:sale.subscription.line,unit:"
+msgid "Unit"
+msgstr ""
+
+msgctxt "field:sale.subscription.line,unit_digits:"
+msgid "Unit Digits"
+msgstr ""
+
+msgctxt "field:sale.subscription.line,unit_price:"
+msgid "Unit Price"
+msgstr ""
+
+msgctxt "field:sale.subscription.line.consumption,date:"
+msgid "Date"
+msgstr ""
+
+msgctxt "field:sale.subscription.line.consumption,invoice_line:"
+msgid "Invoice Line"
+msgstr ""
+
+msgctxt "field:sale.subscription.line.consumption,line:"
+msgid "Line"
+msgstr ""
+
+msgctxt "field:sale.subscription.line.consumption,quantity:"
+msgid "Quantity"
+msgstr ""
+
+msgctxt "field:sale.subscription.line.consumption,unit_digits:"
+msgid "Unit Digits"
+msgstr ""
+
+msgctxt "field:sale.subscription.line.consumption.create.start,date:"
+msgid "Date"
+msgstr ""
+
+msgctxt "field:sale.subscription.recurrence.rule,bymonth:"
+msgid "By Month"
+msgstr ""
+
+msgctxt "field:sale.subscription.recurrence.rule,bymonthday:"
+msgid "By Month Day"
+msgstr ""
+
+msgctxt "field:sale.subscription.recurrence.rule,bysetpos:"
+msgid "By Position"
+msgstr ""
+
+msgctxt "field:sale.subscription.recurrence.rule,byweekday:"
+msgid "By Week Day"
+msgstr ""
+
+msgctxt "field:sale.subscription.recurrence.rule,byweekno:"
+msgid "By Week Number"
+msgstr ""
+
+msgctxt "field:sale.subscription.recurrence.rule,byyearday:"
+msgid "By Year Day"
+msgstr ""
+
+msgctxt "field:sale.subscription.recurrence.rule,exclusive:"
+msgid "Exclusive"
+msgstr ""
+
+msgctxt "field:sale.subscription.recurrence.rule,freq:"
+msgid "Frequency"
+msgstr ""
+
+msgctxt "field:sale.subscription.recurrence.rule,interval:"
+msgid "Interval"
+msgstr ""
+
+msgctxt "field:sale.subscription.recurrence.rule,set_:"
+msgid "Set"
+msgstr ""
+
+msgctxt "field:sale.subscription.recurrence.rule,week_start_day:"
+msgid "Week Start Day"
+msgstr ""
+
+msgctxt "field:sale.subscription.recurrence.rule.set,name:"
+msgid "Name"
+msgstr ""
+
+msgctxt "field:sale.subscription.recurrence.rule.set,rules:"
+msgid "Rules"
+msgstr ""
+
+msgctxt "field:sale.subscription.service,consumption_delay:"
+msgid "Consumption Delay"
+msgstr ""
+
+msgctxt "field:sale.subscription.service,consumption_recurrence:"
+msgid "Consumption Recurrence"
+msgstr ""
+
+msgctxt "field:sale.subscription.service,product:"
+msgid "Product"
+msgstr ""
+
+msgctxt "help:sale.subscription,company:"
+msgid "Make the subscription belong to the company."
+msgstr ""
+
+msgctxt "help:sale.subscription,number:"
+msgid "The main identification of the subscription."
+msgstr ""
+
+msgctxt "help:sale.subscription,party:"
+msgid "The party who subscribes."
+msgstr ""
+
+msgctxt "help:sale.subscription,reference:"
+msgid "The identification of an external origin."
+msgstr ""
+
+msgctxt "help:sale.subscription,state:"
+msgid "The current state of the subscription."
+msgstr ""
+
+msgctxt "help:sale.subscription.line,subscription:"
+msgid "Add the line below the subscription."
+msgstr ""
+
+msgctxt "help:sale.subscription.recurrence.rule,bymonth:"
+msgid "A comma separated list of integers."
+msgstr ""
+
+msgctxt "help:sale.subscription.recurrence.rule,bymonthday:"
+msgid "A comma separated list of integers."
+msgstr ""
+
+msgctxt "help:sale.subscription.recurrence.rule,bysetpos:"
+msgid "A comma separated list of integers."
+msgstr ""
+
+msgctxt "help:sale.subscription.recurrence.rule,byweekday:"
+msgid "A comma separated list of integers or weekday (MO, TU etc)."
+msgstr ""
+
+msgctxt "help:sale.subscription.recurrence.rule,byweekno:"
+msgid "A comma separated list of integers (ISO8601)."
+msgstr ""
+
+msgctxt "help:sale.subscription.recurrence.rule,byyearday:"
+msgid "A comma separated list of integers."
+msgstr ""
+
+msgctxt "help:sale.subscription.recurrence.rule,set_:"
+msgid "Add the rule below the set."
+msgstr ""
+
+msgctxt "help:sale.subscription.recurrence.rule.set,name:"
+msgid "The main identifier of the rule set."
+msgstr ""
+
+msgctxt "model:ir.action,name:act_create_invoice"
+msgid "Create Subscription Invoices"
+msgstr "Create Subscription Invoices"
+
+msgctxt "model:ir.action,name:act_line_consumption_create"
+msgid "Create Line Consumptions"
+msgstr "Create Line Consumptions"
+
+msgctxt "model:ir.action,name:act_recurrence_rule_set_form"
+msgid "Subscription Recurrence Rule Sets"
+msgstr "Subscription Recurrence Rule Sets"
+
+msgctxt "model:ir.action,name:act_service_form"
+msgid "Subscription Services"
+msgstr "Subscription Services"
+
+msgctxt "model:ir.action,name:act_subscription_form"
+msgid "Subscriptions"
+msgstr "Subscriptions"
+
+msgctxt "model:ir.action,name:act_subscription_invoice_relate"
+msgid "Invoices"
+msgstr ""
+
+msgctxt "model:ir.action,name:act_subscription_line_consumption_form"
+msgid "Consumptions"
+msgstr "Consumptions"
+
+msgctxt ""
+"model:ir.action,name:act_subscription_line_consumption_subscription_line_relate"
+msgid "Consumptions"
+msgstr "Consumptions"
+
+msgctxt ""
+"model:ir.action,name:act_subscription_line_consumption_subscription_relate"
+msgid "Consumptions"
+msgstr "Consumptions"
+
+msgctxt "model:ir.action,name:act_subscription_party_relate"
+msgid "Subscriptions"
+msgstr "Subscriptions"
+
+msgctxt ""
+"model:ir.action.act_window.domain,name:act_subscription_form_domain_all"
+msgid "All"
+msgstr "All"
+
+msgctxt ""
+"model:ir.action.act_window.domain,name:act_subscription_form_domain_draft"
+msgid "Draft"
+msgstr "Draft"
+
+msgctxt ""
+"model:ir.action.act_window.domain,name:act_subscription_form_domain_quotation"
+msgid "Quotation"
+msgstr "Quotation"
+
+msgctxt ""
+"model:ir.action.act_window.domain,name:act_subscription_form_domain_running"
+msgid "Running"
+msgstr "Running"
+
+msgctxt "model:ir.message,text:msg_consumption_delete_invoiced"
+msgid "You cannot delete invoiced consumption \"%(consumption)s\"."
+msgstr ""
+
+msgctxt ""
+"model:ir.message,text:msg_consumption_invoice_missing_account_revenue"
+msgid ""
+"To invoice consumptions you must define an account revenue for product "
+"\"%(product)s\"."
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_consumption_modify_invoiced"
+msgid "You cannot modify invoiced consumption \"%(consumption)s\"."
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_consumption_recurrence_invalid"
+msgid ""
+"The consumption recurrence of line \"%(line)s\" of subscription "
+"\"%(subscription)s\" does not generate any occurrence."
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_erase_party_pending_subscription"
+msgid ""
+"You cannot erase party \"%(party)s\" while they have pending subscriptions "
+"with company \"%(company)s\"."
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_invoice_recurrence_invalid"
+msgid ""
+"The invoice recurrence of subscription \"%(subscription)s\" does not "
+"generate any occurrence."
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_recurrence_rule_invalid_by"
+msgid ""
+"Invalid \"%(field)s\" \"%(value)s\" in recurence rule "
+"\"%(recurrence_rule)s\" with exception \"%(exception)s\"."
+msgstr ""
+
+msgctxt "model:ir.model.button,string:subscription_cancel_button"
+msgid "Cancel"
+msgstr "Cancel"
+
+msgctxt "model:ir.model.button,string:subscription_draft_button"
+msgid "Draft"
+msgstr "Draft"
+
+msgctxt "model:ir.model.button,string:subscription_quote_button"
+msgid "Quote"
+msgstr "Quote"
+
+msgctxt "model:ir.model.button,string:subscription_run_button"
+msgid "Run"
+msgstr "Run"
+
+msgctxt "model:ir.rule.group,name:rule_group_subscription_companies"
+msgid "User in companies"
+msgstr ""
+
+msgctxt "model:ir.sequence,name:sequence_subscription"
+msgid "Subscription"
+msgstr "Subscription"
+
+msgctxt "model:ir.sequence.type,name:sequence_type_subscription"
+msgid "Subscription"
+msgstr "Subscription"
+
+#, fuzzy
+msgctxt "model:ir.ui.menu,name:menu_configuration"
+msgid "Subscription"
+msgstr "Subscription"
+
+msgctxt "model:ir.ui.menu,name:menu_create_invoice"
+msgid "Create Subscription Invoices"
+msgstr "Create Subscription Invoices"
+
+msgctxt "model:ir.ui.menu,name:menu_line_consumption_create"
+msgid "Create Line Consumptions"
+msgstr "Create Line Consumptions"
+
+msgctxt "model:ir.ui.menu,name:menu_recurrence_rule_set_form"
+msgid "Subscription Recurrence Rule Sets"
+msgstr "Subscription Recurrence Rule Sets"
+
+msgctxt "model:ir.ui.menu,name:menu_service_form"
+msgid "Subscription Services"
+msgstr "Subscription Services"
+
+msgctxt "model:ir.ui.menu,name:menu_subscription_form"
+msgid "Subscriptions"
+msgstr "Subscriptions"
+
+#, fuzzy
+msgctxt "model:sale.subscription,name:"
+msgid "Subscription"
+msgstr "Subscription"
+
+#, fuzzy
+msgctxt "model:sale.subscription.create_invoice.start,name:"
+msgid "Create Subscription Invoice"
+msgstr "Create Subscription Invoices"
+
+#, fuzzy
+msgctxt "model:sale.subscription.line,name:"
+msgid "Subscription Line"
+msgstr "Subscription Services"
+
+#, fuzzy
+msgctxt "model:sale.subscription.line.consumption,name:"
+msgid "Subscription Line Consumption"
+msgstr "Generate Subscription Line Consumptions"
+
+#, fuzzy
+msgctxt "model:sale.subscription.line.consumption.create.start,name:"
+msgid "Create Subscription Line Consumption"
+msgstr "Generate Subscription Line Consumptions"
+
+#, fuzzy
+msgctxt "model:sale.subscription.recurrence.rule,name:"
+msgid "Subscription Recurrence Rule"
+msgstr "Subscription Recurrence Rule Sets"
+
+#, fuzzy
+msgctxt "model:sale.subscription.recurrence.rule.set,name:"
+msgid "Subscription Recurrence Rule Set"
+msgstr "Subscription Recurrence Rule Sets"
+
+#, fuzzy
+msgctxt "model:sale.subscription.service,name:"
+msgid "Subscription Service"
+msgstr "Subscription Services"
+
+#, fuzzy
+msgctxt "selection:ir.cron,method:"
+msgid "Generate Subscription Invoices"
+msgstr "Generate Subscription Invoices"
+
+#, fuzzy
+msgctxt "selection:ir.cron,method:"
+msgid "Generate Subscription Line Consumptions"
+msgstr "Generate Subscription Line Consumptions"
+
+#, fuzzy
+msgctxt "selection:sale.subscription,state:"
+msgid "Cancelled"
+msgstr "Cancel"
+
+msgctxt "selection:sale.subscription,state:"
+msgid "Closed"
+msgstr ""
+
+#, fuzzy
+msgctxt "selection:sale.subscription,state:"
+msgid "Draft"
+msgstr "Draft"
+
+#, fuzzy
+msgctxt "selection:sale.subscription,state:"
+msgid "Quotation"
+msgstr "Quotation"
+
+#, fuzzy
+msgctxt "selection:sale.subscription,state:"
+msgid "Running"
+msgstr "Running"
+
+msgctxt "selection:sale.subscription.recurrence.rule,freq:"
+msgid "Daily"
+msgstr ""
+
+msgctxt "selection:sale.subscription.recurrence.rule,freq:"
+msgid "Monthly"
+msgstr ""
+
+msgctxt "selection:sale.subscription.recurrence.rule,freq:"
+msgid "Weekly"
+msgstr ""
+
+msgctxt "selection:sale.subscription.recurrence.rule,freq:"
+msgid "Yearly"
+msgstr ""
+
+#, fuzzy
+msgctxt "view:sale.subscription.create_invoice.start:"
+msgid "Create Subscription Invoices for date"
+msgstr "Create Subscription Invoices"
+
+#, fuzzy
+msgctxt "view:sale.subscription.line.consumption.create.start:"
+msgid "Create Subscription Line Consumptions for date"
+msgstr "Generate Subscription Line Consumptions"
+
+msgctxt "view:sale.subscription.line:"
+msgid "General"
+msgstr ""
+
+msgctxt "view:sale.subscription:"
+msgid "Other Info"
+msgstr ""
+
+#, fuzzy
+msgctxt "view:sale.subscription:"
+msgid "Subscription"
+msgstr "Subscription"
+
+msgctxt "wizard_button:sale.subscription.create_invoice,start,create_:"
+msgid "Create"
+msgstr ""
+
+#, fuzzy
+msgctxt "wizard_button:sale.subscription.create_invoice,start,end:"
+msgid "Cancel"
+msgstr "Cancel"
+
+msgctxt ""
+"wizard_button:sale.subscription.line.consumption.create,start,create_:"
+msgid "Create"
+msgstr ""
+
+#, fuzzy
+msgctxt "wizard_button:sale.subscription.line.consumption.create,start,end:"
+msgid "Cancel"
+msgstr "Cancel"
diff --git a/modules/sale_subscription/message.xml b/modules/sale_subscription/message.xml
new file mode 100644
index 0000000000..d9fed01f71
--- /dev/null
+++ b/modules/sale_subscription/message.xml
@@ -0,0 +1,28 @@
+
+
+
+
+
+ The invoice recurrence of subscription "%(subscription)s" does not generate any occurrence.
+
+
+ The consumption recurrence of line "%(line)s" of subscription "%(subscription)s" does not generate any occurrence.
+
+
+ You cannot modify invoiced consumption "%(consumption)s".
+
+
+ You cannot delete invoiced consumption "%(consumption)s".
+
+
+ To invoice consumptions you must define an account revenue for product "%(product)s".
+
+
+ You cannot erase party "%(party)s" while they have pending subscriptions with company "%(company)s".
+
+
+ Invalid "%(field)s" "%(value)s" in recurence rule "%(recurrence_rule)s" with exception "%(exception)s".
+
+
+
diff --git a/modules/sale_subscription/party.py b/modules/sale_subscription/party.py
new file mode 100644
index 0000000000..c1e35850b8
--- /dev/null
+++ b/modules/sale_subscription/party.py
@@ -0,0 +1,37 @@
+# This file is part of Tryton. The COPYRIGHT file at the top level of
+# this repository contains the full copyright notices and license terms.
+from trytond.i18n import gettext
+from trytond.pool import PoolMeta, Pool
+
+from trytond.modules.party.exceptions import EraseError
+
+
+class Replace(metaclass=PoolMeta):
+ __name__ = 'party.replace'
+
+ @classmethod
+ def fields_to_replace(cls):
+ return super().fields_to_replace() + [
+ ('sale.subscription', 'party'),
+ ]
+
+
+class Erase(metaclass=PoolMeta):
+ __name__ = 'party.erase'
+
+ def check_erase_company(self, party, company):
+ pool = Pool()
+ Subscription = pool.get('sale.subscription')
+ super().check_erase_company(party, company)
+
+ subscriptions = Subscription.search([
+ ('party', '=', party.id),
+ ('company', '=', company.id),
+ ('state', 'not in', ['closed', 'cancelled']),
+ ])
+ if subscriptions:
+ raise EraseError(
+ gettext('sale_subscription'
+ '.msg_erase_party_pending_subscription',
+ party=party.rec_name,
+ company=company.rec_name))
diff --git a/modules/sale_subscription/party.xml b/modules/sale_subscription/party.xml
new file mode 100644
index 0000000000..e5c6732c93
--- /dev/null
+++ b/modules/sale_subscription/party.xml
@@ -0,0 +1,12 @@
+
+
+
+
+
+ party.party
+
+ party_form
+
+
+
diff --git a/modules/sale_subscription/recurrence.py b/modules/sale_subscription/recurrence.py
new file mode 100644
index 0000000000..a167083205
--- /dev/null
+++ b/modules/sale_subscription/recurrence.py
@@ -0,0 +1,231 @@
+# This file is part of Tryton. The COPYRIGHT file at the top level of
+# this repository contains the full copyright notices and license terms.
+from dateutil.rrule import MO, TU, WE, TH, FR, SA, SU
+from dateutil.rrule import YEARLY, MONTHLY, WEEKLY, DAILY
+from dateutil.rrule import rrule, rruleset
+
+from trytond.i18n import gettext
+from trytond.model import ModelSQL, ModelView, fields
+from trytond.pool import Pool
+from trytond.transaction import Transaction
+
+from .exceptions import RecurrenceRuleValidationError
+
+WEEKDAYS = {
+ 'MO': MO,
+ 'TU': TU,
+ 'WE': WE,
+ 'TH': TH,
+ 'FR': FR,
+ 'SA': SA,
+ 'SU': SU,
+ }
+FREQUENCIES = {
+ 'yearly': YEARLY,
+ 'monthly': MONTHLY,
+ 'weekly': WEEKLY,
+ 'daily': DAILY,
+ }
+
+
+class RecurrenceRuleSet(ModelSQL, ModelView):
+ "Subscription Recurrence Rule Set"
+ __name__ = 'sale.subscription.recurrence.rule.set'
+
+ name = fields.Char(
+ "Name", required=True, translate=True,
+ help="The main identifier of the rule set.")
+ rules = fields.One2Many(
+ 'sale.subscription.recurrence.rule', 'set_', "Rules")
+
+ @classmethod
+ def __setup__(cls):
+ super().__setup__()
+ cls._order.insert(0, ('name', 'ASC'))
+
+ @classmethod
+ def default_rules(cls):
+ if Transaction().user == 0:
+ return []
+ return [{}]
+
+ def rruleset(self, dtstart):
+ set_ = rruleset(**self._rruleset())
+ for rule in self.rules:
+ if not rule.exclusive:
+ set_.rrule(rule.rrule(dtstart))
+ else:
+ set_.exrule(rule.rrule(dtstart))
+ return set_
+
+ def _rruleset(self):
+ return {}
+
+
+class RecurrenceRule(ModelSQL, ModelView):
+ "Subscription Recurrence Rule"
+ __name__ = 'sale.subscription.recurrence.rule'
+
+ set_ = fields.Many2One(
+ 'sale.subscription.recurrence.rule.set', "Set",
+ required=True, select=True,
+ help="Add the rule below the set.")
+ freq = fields.Selection([
+ ('yearly', 'Yearly'),
+ ('monthly', 'Monthly'),
+ ('weekly', 'Weekly'),
+ ('daily', 'Daily'),
+ ], "Frequency", sort=False, required=True)
+ interval = fields.Integer("Interval", required=True)
+ byweekday = fields.Char(
+ "By Week Day",
+ help="A comma separated list of integers or weekday (MO, TU etc).")
+ bymonthday = fields.Char(
+ "By Month Day",
+ help="A comma separated list of integers.")
+ byyearday = fields.Char(
+ "By Year Day",
+ help="A comma separated list of integers.")
+ byweekno = fields.Char(
+ "By Week Number",
+ help="A comma separated list of integers (ISO8601).")
+ bymonth = fields.Char(
+ "By Month",
+ help="A comma separated list of integers.")
+ bysetpos = fields.Char(
+ "By Position",
+ help="A comma separated list of integers.")
+ week_start_day = fields.Many2One('ir.calendar.day', "Week Start Day")
+
+ exclusive = fields.Boolean("Exclusive")
+
+ @classmethod
+ def __setup__(cls):
+ super().__setup__()
+ cls.__access__.add('set_')
+
+ @classmethod
+ def __register__(cls, module_name):
+ pool = Pool()
+ Day = pool.get('ir.calendar.day')
+ day = Day.__table__()
+ transaction = Transaction()
+ table = cls.__table__()
+
+ super().__register__(module_name)
+ table_h = cls.__table_handler__(module_name)
+
+ # Migration from 5.0: replace wkst by week_start_day
+ if table_h.column_exist('wkst'):
+ cursor = transaction.connection.cursor()
+ update = transaction.connection.cursor()
+ cursor.execute(*day.select(day.id, day.index))
+ for day_id, index in cursor:
+ update.execute(*table.update(
+ [table.week_start_day], [day_id],
+ where=table.wkst == str(index)))
+ table_h.drop_column('wkst')
+
+ @classmethod
+ def default_interval(cls):
+ return 1
+
+ @classmethod
+ def default_exclusive(cls):
+ return False
+
+ def rrule(self, dtstart):
+ return rrule(**self._rrule(dtstart))
+
+ def _rrule(self, dtstart):
+ return {
+ 'dtstart': dtstart,
+ 'freq': FREQUENCIES[self.freq],
+ 'interval': self.interval,
+ 'byweekday': self._byweekday,
+ 'bymonthday': self._bymonthday,
+ 'byyearday': self._byyearday,
+ 'byweekno': self._byweekno,
+ 'bymonth': self._bymonth,
+ 'bysetpos': self._bysetpos,
+ 'wkst': self.week_start_day.index if self.week_start_day else None,
+ }
+
+ @property
+ def _byweekday(self):
+ if not self.byweekday:
+ return None
+ byweekday = []
+ for weekday in self.byweekday.split(','):
+ try:
+ weekday = int(weekday)
+ except ValueError:
+ pass
+ else:
+ if 0 <= weekday <= len(WEEKDAYS):
+ byweekday.append(weekday)
+ continue
+ else:
+ raise ValueError('Invalid weekday')
+ try:
+ cls = WEEKDAYS[weekday[:2]]
+ except KeyError:
+ raise ValueError('Invalid weekday')
+ if not weekday[2:]:
+ byweekday.append(cls)
+ else:
+ byweekday.append(cls(int(weekday[3:-1])))
+ return byweekday
+
+ @property
+ def _bymonthday(self):
+ if not self.bymonthday:
+ return None
+ return [int(md) for md in self.bymonthday.split(',')]
+
+ @property
+ def _byyearday(self):
+ if not self.byyearday:
+ return None
+ return [int(yd) for yd in self.byyearday.split(',')]
+
+ @property
+ def _byweekno(self):
+ if not self.byweekno:
+ return None
+ return [int(wn) for wn in self.byweekno.split(',')]
+
+ @property
+ def _bymonth(self):
+ if not self.bymonth:
+ return None
+ return [int(m) for m in self.bymonth.split(',')]
+
+ @property
+ def _bysetpos(self):
+ if not self.bysetpos:
+ return None
+ positions = []
+ for setpos in self.bysetpos.split(','):
+ setpos = int(setpos)
+ if -366 <= setpos <= 366:
+ positions.append(setpos)
+ else:
+ raise ValueError('Invalid setpos')
+ return positions
+
+ def pre_validate(self):
+ for name in ['byweekday', 'bymonthday', 'byyearday', 'byweekno',
+ 'bymonth', 'bysetpos']:
+ self.check_by(name)
+
+ def check_by(self, name):
+ try:
+ getattr(self, '_%s' % name)
+ except ValueError as exception:
+ raise RecurrenceRuleValidationError(
+ gettext('sale_subscription.msg_recurrence_rule_invalid_by',
+ value=getattr(self, name),
+ recurrence_rule=self.rec_name,
+ exception=exception,
+ **self.__names__(name))) from exception
diff --git a/modules/sale_subscription/recurrence.xml b/modules/sale_subscription/recurrence.xml
new file mode 100644
index 0000000000..c220c8efdc
--- /dev/null
+++ b/modules/sale_subscription/recurrence.xml
@@ -0,0 +1,68 @@
+
+
+
+
+
+ sale.subscription.recurrence.rule.set
+ form
+ recurrence_rule_set_form
+
+
+
+ sale.subscription.recurrence.rule.set
+ tree
+ recurrence_rule_set_list
+
+
+
+ Subscription Recurrence Rule Sets
+ sale.subscription.recurrence.rule.set
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ sale.subscription.recurrence.rule
+ form
+ recurrence_rule_form
+
+
+
+ sale.subscription.recurrence.rule
+ tree
+ recurrence_rule_list
+
+
+
diff --git a/modules/sale_subscription/service.py b/modules/sale_subscription/service.py
new file mode 100644
index 0000000000..06f14b322c
--- /dev/null
+++ b/modules/sale_subscription/service.py
@@ -0,0 +1,29 @@
+# This file is part of Tryton. The COPYRIGHT file at the top level of
+# this repository contains the full copyright notices and license terms.
+from trytond.model import ModelSQL, ModelView, DeactivableMixin, fields
+from trytond.pyson import Eval
+
+
+class Service(DeactivableMixin, ModelSQL, ModelView):
+ "Subscription Service"
+ __name__ = 'sale.subscription.service'
+
+ product = fields.Many2One(
+ 'product.product', "Product", required=True,
+ domain=[
+ ('type', '=', 'service'),
+ ])
+ consumption_recurrence = fields.Many2One(
+ 'sale.subscription.recurrence.rule.set', "Consumption Recurrence")
+ consumption_delay = fields.TimeDelta("Consumption Delay",
+ states={
+ 'invisible': ~Eval('consumption_recurrence'),
+ },
+ depends=['consumption_recurrence'])
+
+ def get_rec_name(self, name):
+ return self.product.rec_name
+
+ @classmethod
+ def search_rec_name(cls, name, clause):
+ return [('product.rec_name',) + tuple(clause[1:])]
diff --git a/modules/sale_subscription/service.xml b/modules/sale_subscription/service.xml
new file mode 100644
index 0000000000..62d4bd1f63
--- /dev/null
+++ b/modules/sale_subscription/service.xml
@@ -0,0 +1,56 @@
+
+
+
+
+
+ sale.subscription.service
+ form
+ service_form
+
+
+
+ sale.subscription.service
+ tree
+ service_list
+
+
+
+ Subscription Services
+ sale.subscription.service
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/modules/sale_subscription/setup.py b/modules/sale_subscription/setup.py
new file mode 100755
index 0000000000..93ea4d00dd
--- /dev/null
+++ b/modules/sale_subscription/setup.py
@@ -0,0 +1,150 @@
+#!/usr/bin/env python3
+# This file is part of Tryton. The COPYRIGHT file at the top level of
+# this repository contains the full copyright notices and license terms.
+
+import io
+import os
+import re
+from configparser import ConfigParser
+from setuptools import setup, find_packages
+
+
+def read(fname):
+ return io.open(
+ os.path.join(os.path.dirname(__file__), fname),
+ 'r', encoding='utf-8').read()
+
+
+def get_require_version(name):
+ if minor_version % 2:
+ require = '%s >= %s.%s.dev0, < %s.%s'
+ else:
+ require = '%s >= %s.%s, < %s.%s'
+ require %= (name, major_version, minor_version,
+ major_version, minor_version + 1)
+ return require
+
+
+config = ConfigParser()
+config.read_file(open(os.path.join(os.path.dirname(__file__), 'tryton.cfg')))
+info = dict(config.items('tryton'))
+for key in ('depends', 'extras_depend', 'xml'):
+ if key in info:
+ info[key] = info[key].strip().splitlines()
+version = info.get('version', '0.0.1')
+major_version, minor_version, _ = version.split('.', 2)
+major_version = int(major_version)
+minor_version = int(minor_version)
+name = 'trytond_sale_subscription'
+
+download_url = 'http://downloads.tryton.org/%s.%s/' % (
+ major_version, minor_version)
+if minor_version % 2:
+ version = '%s.%s.dev0' % (major_version, minor_version)
+ download_url = (
+ 'hg+http://hg.tryton.org/modules/%s#egg=%s-%s' % (
+ name[8:], name, version))
+local_version = []
+if os.environ.get('CI_JOB_ID'):
+ local_version.append(os.environ['CI_JOB_ID'])
+else:
+ for build in ['CI_BUILD_NUMBER', 'CI_JOB_NUMBER']:
+ if os.environ.get(build):
+ local_version.append(os.environ[build])
+ else:
+ local_version = []
+ break
+if local_version:
+ version += '+' + '.'.join(local_version)
+
+requires = ['python-dateutil']
+for dep in info.get('depends', []):
+ if not re.match(r'(ir|res)(\W|$)', dep):
+ requires.append(get_require_version('trytond_%s' % dep))
+requires.append(get_require_version('trytond'))
+
+tests_require = [get_require_version('proteus')]
+dependency_links = []
+if minor_version % 2:
+ dependency_links.append(
+ 'https://trydevpi.tryton.org/?local_version='
+ + '.'.join(local_version))
+
+setup(name=name,
+ version=version,
+ description='Tryton module for subscription',
+ long_description=read('README.rst'),
+ author='Tryton',
+ author_email='bugs@tryton.org',
+ url='http://www.tryton.org/',
+ download_url=download_url,
+ project_urls={
+ "Bug Tracker": 'https://bugs.tryton.org/',
+ "Documentation": 'https://docs.tryton.org/',
+ "Forum": 'https://www.tryton.org/forum',
+ "Source Code": 'https://hg.tryton.org/modules/sale_subscription',
+ },
+ keywords='tryton sale subscription',
+ package_dir={'trytond.modules.sale_subscription': '.'},
+ packages=(
+ ['trytond.modules.sale_subscription']
+ + ['trytond.modules.sale_subscription.%s' % p for p in find_packages()]
+ ),
+ package_data={
+ 'trytond.modules.sale_subscription': (info.get('xml', [])
+ + ['tryton.cfg', 'view/*.xml', 'locale/*.po', '*.fodt',
+ 'icons/*.svg', 'tests/*.rst']),
+ },
+ classifiers=[
+ 'Development Status :: 5 - Production/Stable',
+ 'Environment :: Plugins',
+ 'Framework :: Tryton',
+ 'Intended Audience :: Developers',
+ 'Intended Audience :: Financial and Insurance Industry',
+ 'Intended Audience :: Legal Industry',
+ 'License :: OSI Approved :: '
+ 'GNU General Public License v3 or later (GPLv3+)',
+ 'Natural Language :: Bulgarian',
+ 'Natural Language :: Catalan',
+ 'Natural Language :: Chinese (Simplified)',
+ 'Natural Language :: Czech',
+ 'Natural Language :: Dutch',
+ 'Natural Language :: English',
+ 'Natural Language :: Finnish',
+ 'Natural Language :: French',
+ 'Natural Language :: German',
+ 'Natural Language :: Hungarian',
+ 'Natural Language :: Indonesian',
+ 'Natural Language :: Italian',
+ 'Natural Language :: Persian',
+ 'Natural Language :: Polish',
+ 'Natural Language :: Portuguese (Brazilian)',
+ 'Natural Language :: Romanian',
+ 'Natural Language :: Russian',
+ 'Natural Language :: Slovenian',
+ 'Natural Language :: Spanish',
+ 'Natural Language :: Turkish',
+ 'Operating System :: OS Independent',
+ 'Programming Language :: Python :: 3',
+ 'Programming Language :: Python :: 3.6',
+ 'Programming Language :: Python :: 3.7',
+ 'Programming Language :: Python :: 3.8',
+ 'Programming Language :: Python :: 3.9',
+ 'Programming Language :: Python :: Implementation :: CPython',
+ 'Programming Language :: Python :: Implementation :: PyPy',
+ 'Topic :: Office/Business',
+ 'Topic :: Office/Business :: Financial :: Accounting',
+ ],
+ license='GPL-3',
+ python_requires='>=3.6',
+ install_requires=requires,
+ dependency_links=dependency_links,
+ zip_safe=False,
+ entry_points="""
+ [trytond.modules]
+ sale_subscription = trytond.modules.sale_subscription
+ """,
+ test_suite='tests',
+ test_loader='trytond.test_loader:Loader',
+ tests_require=tests_require,
+ )
diff --git a/modules/sale_subscription/subscription.py b/modules/sale_subscription/subscription.py
new file mode 100644
index 0000000000..f48f7a6b13
--- /dev/null
+++ b/modules/sale_subscription/subscription.py
@@ -0,0 +1,1038 @@
+# This file is part of Tryton. The COPYRIGHT file at the top level of
+# this repository contains the full copyright notices and license terms.
+import datetime
+from itertools import groupby
+
+from sql import operators, Literal, Null
+from sql.conditionals import Coalesce, Case
+
+from trytond import backend
+from trytond.i18n import gettext
+from trytond.model import ModelSQL, ModelView, Workflow, fields, \
+ sequence_ordered
+from trytond.model.exceptions import AccessError
+from trytond.pool import Pool
+from trytond.pyson import Eval, If, Bool
+from trytond.transaction import Transaction
+from trytond.tools import sortable_values
+from trytond.wizard import Wizard, StateView, StateAction, StateTransition, \
+ Button
+
+from trytond.modules.company.model import (
+ employee_field, set_employee, reset_employee)
+from trytond.modules.product import price_digits, round_price
+from .exceptions import InvalidRecurrence, InvoiceError
+
+
+class Subscription(Workflow, ModelSQL, ModelView):
+ "Subscription"
+ __name__ = 'sale.subscription'
+ _rec_name = 'number'
+
+ company = fields.Many2One(
+ 'company.company', "Company", required=True, select=True,
+ states={
+ 'readonly': (Eval('state') != 'draft') | Eval('party', True),
+ },
+ depends=['state', 'party'],
+ help="Make the subscription belong to the company.")
+
+ number = fields.Char(
+ "Number", readonly=True, select=True,
+ help="The main identification of the subscription.")
+ # TODO revision
+ reference = fields.Char(
+ "Reference", select=True,
+ help="The identification of an external origin.")
+ description = fields.Char("Description",
+ states={
+ 'readonly': Eval('state') != 'draft',
+ },
+ depends=['state'])
+
+ party = fields.Many2One(
+ 'party.party', "Party", required=True,
+ states={
+ 'readonly': ((Eval('state') != 'draft')
+ | (Eval('lines', [0]) & Eval('party'))),
+ },
+ context={
+ 'company': Eval('company', -1),
+ },
+ depends=['state', 'company'],
+ help="The party who subscribes.")
+ contact = fields.Many2One(
+ 'party.contact_mechanism', "Contact",
+ context={
+ 'company': Eval('company', -1),
+ },
+ search_context={
+ 'related_party': Eval('party'),
+ },
+ depends=['company', 'party'])
+ invoice_party = fields.Many2One('party.party', "Invoice Party",
+ states={
+ 'readonly': ((Eval('state') != 'draft')
+ | Eval('lines', [0])),
+ },
+ context={
+ 'company': Eval('company', -1),
+ },
+ search_context={
+ 'related_party': Eval('party'),
+ },
+ depends=['state', 'company', 'party'])
+ invoice_address = fields.Many2One(
+ 'party.address', "Invoice Address",
+ domain=[
+ ('party', '=', If(Bool(Eval('invoice_party',)),
+ Eval('invoice_party'), Eval('party'))),
+ ],
+ states={
+ 'readonly': Eval('state') != 'draft',
+ 'required': ~Eval('state').in_(['draft']),
+ },
+ depends=['party', 'invoice_party', 'state'])
+ payment_term = fields.Many2One(
+ 'account.invoice.payment_term', "Payment Term",
+ states={
+ 'readonly': Eval('state') != 'draft',
+ },
+ depends=['state'])
+
+ currency = fields.Many2One(
+ 'currency.currency', "Currency", required=True,
+ states={
+ 'readonly': ((Eval('state') != 'draft')
+ | (Eval('lines', [0]) & Eval('currency', 0))),
+ },
+ depends=['state'])
+
+ start_date = fields.Date(
+ "Start Date", required=True,
+ states={
+ 'readonly': ((Eval('state') != 'draft')
+ | Eval('next_invoice_date')),
+ },
+ depends=['state', 'next_invoice_date'])
+ end_date = fields.Date(
+ "End Date",
+ domain=['OR',
+ ('end_date', '>=', If(
+ Bool(Eval('start_date')),
+ Eval('start_date', datetime.date.min),
+ datetime.date.min)),
+ ('end_date', '=', None),
+ ],
+ states={
+ 'readonly': Eval('state') != 'draft',
+ },
+ depends=['start_date', 'state'])
+
+ invoice_recurrence = fields.Many2One(
+ 'sale.subscription.recurrence.rule.set', "Invoice Recurrence",
+ required=True,
+ states={
+ 'readonly': Eval('state') != 'draft',
+ },
+ depends=['state'])
+ invoice_start_date = fields.Date("Invoice Start Date",
+ states={
+ 'readonly': ((Eval('state') != 'draft')
+ | Eval('next_invoice_date')),
+ },
+ depends=['state', 'next_invoice_date'])
+ next_invoice_date = fields.Date("Next Invoice Date", readonly=True)
+
+ lines = fields.One2Many(
+ 'sale.subscription.line', 'subscription', "Lines",
+ states={
+ 'readonly': ((Eval('state') != 'draft')
+ | ~Eval('start_date')),
+ },
+ depends=['state'])
+
+ quoted_by = employee_field(
+ "Quoted By", states=['quotation', 'running', 'closed', 'cancelled'])
+ run_by = employee_field(
+ "Run By", states=['running', 'closed', 'cancelled'])
+ state = fields.Selection([
+ ('draft', "Draft"),
+ ('quotation', "Quotation"),
+ ('running', "Running"),
+ ('closed', "Closed"),
+ ('cancelled', "Cancelled"),
+ ], "State", readonly=True, required=True,
+ help="The current state of the subscription.")
+
+ @classmethod
+ def __setup__(cls):
+ super(Subscription, cls).__setup__()
+ cls._order = [
+ ('start_date', 'DESC'),
+ ('id', 'DESC'),
+ ]
+ cls._transitions |= set((
+ ('draft', 'cancelled'),
+ ('draft', 'quotation'),
+ ('quotation', 'cancelled'),
+ ('quotation', 'draft'),
+ ('quotation', 'running'),
+ ('running', 'draft'),
+ ('running', 'closed'),
+ ('cancelled', 'draft'),
+ ))
+ cls._buttons.update({
+ 'cancel': {
+ 'invisible': ~Eval('state').in_(['draft', 'quotation']),
+ 'icon': 'tryton-cancel',
+ 'depends': ['state'],
+ },
+ 'draft': {
+ 'invisible': Eval('state').in_(['draft', 'closed']),
+ 'icon': If(Eval('state') == 'cancelled',
+ 'tryton-undo', 'tryton-back'),
+ 'depends': ['state'],
+ },
+ 'quote': {
+ 'invisible': Eval('state') != 'draft',
+ 'readonly': ~Eval('lines', []),
+ 'icon': 'tryton-forward',
+ 'depends': ['state'],
+ },
+ 'run': {
+ 'invisible': Eval('state') != 'quotation',
+ 'icon': 'tryton-forward',
+ 'depends': ['state'],
+ },
+ })
+
+ @classmethod
+ def __register__(cls, module_name):
+ cursor = Transaction().connection.cursor()
+ table = cls.__table__()
+
+ super().__register__(module_name)
+
+ # Migration from 5.6: rename state canceled to cancelled
+ cursor.execute(*table.update(
+ [table.state], ['cancelled'],
+ where=table.state == 'canceled'))
+
+ @classmethod
+ def default_company(cls):
+ return Transaction().context.get('company')
+
+ @classmethod
+ def default_currency(cls):
+ pool = Pool()
+ Company = pool.get('company.company')
+ company = cls.default_company()
+ if company:
+ return Company(company).currency.id
+
+ @classmethod
+ def default_state(cls):
+ return 'draft'
+
+ @fields.depends('party', 'invoice_party')
+ def on_change_party(self):
+ if not self.invoice_party:
+ self.invoice_address = None
+ if self.party:
+ if not self.invoice_party:
+ self.invoice_address = self.party.address_get(type='invoice')
+ self.payment_term = self.party.customer_payment_term
+
+ @fields.depends('party', 'invoice_party')
+ def on_change_invoice_party(self):
+ if self.invoice_party:
+ self.invoice_address = self.invoice_party.address_get(
+ type='invoice')
+ elif self.party:
+ self.invoice_address = self.party.address_get(type='invoice')
+
+ @classmethod
+ def set_number(cls, subscriptions):
+ pool = Pool()
+ Config = pool.get('sale.configuration')
+
+ config = Config(1)
+ for subscription in subscriptions:
+ if subscription.number:
+ continue
+ subscription.number = config.get_multivalue(
+ 'subscription_sequence',
+ company=subscription.company.id).get()
+ cls.save(subscriptions)
+
+ def compute_next_invoice_date(self):
+ start_date = self.invoice_start_date or self.start_date
+ date = self.next_invoice_date or start_date
+ rruleset = self.invoice_recurrence.rruleset(start_date)
+ dt = datetime.datetime.combine(date, datetime.time())
+ inc = (start_date == date) and not self.next_invoice_date
+ next_date = rruleset.after(dt, inc=inc)
+ if next_date:
+ return next_date.date()
+
+ @classmethod
+ def validate(cls, subscriptions):
+ super().validate(subscriptions)
+ for subscription in subscriptions:
+ subscription.validate_invoice_recurrence()
+
+ def validate_invoice_recurrence(self):
+ start_date = self.invoice_start_date or self.start_date
+ try:
+ self.invoice_recurrence.rruleset(start_date)[0]
+ except IndexError:
+ raise InvalidRecurrence(gettext(
+ 'sale_subscription.msg_invoice_recurrence_invalid',
+ subscription=self.rec_name))
+
+ @classmethod
+ def copy(cls, subscriptions, default=None):
+ if default is None:
+ default = {}
+ else:
+ default = default.copy()
+ default.setdefault('number', None)
+ default.setdefault('next_invoice_date', None)
+ default.setdefault('quoted_by')
+ default.setdefault('run_by')
+ return super(Subscription, cls).copy(subscriptions, default=default)
+
+ @classmethod
+ def view_attributes(cls):
+ return super().view_attributes() + [
+ ('/tree', 'visual',
+ If(Eval('state') == 'cancelled', 'muted', '')),
+ ]
+
+ @classmethod
+ @ModelView.button
+ @Workflow.transition('cancelled')
+ def cancel(cls, subscriptions):
+ pass
+
+ @classmethod
+ @ModelView.button
+ @Workflow.transition('draft')
+ @reset_employee('quoted_by', 'run_by')
+ def draft(cls, subscriptions):
+ pass
+
+ @classmethod
+ @ModelView.button
+ @Workflow.transition('quotation')
+ @set_employee('quoted_by')
+ def quote(cls, subscriptions):
+ cls.set_number(subscriptions)
+
+ @classmethod
+ @ModelView.button
+ @Workflow.transition('running')
+ @set_employee('run_by')
+ def run(cls, subscriptions):
+ pool = Pool()
+ Line = pool.get('sale.subscription.line')
+ lines = []
+ for subscription in subscriptions:
+ if not subscription.next_invoice_date:
+ subscription.next_invoice_date = (
+ subscription.compute_next_invoice_date())
+ for line in subscription.lines:
+ if (line.next_consumption_date is None
+ and not line.consumed_until):
+ line.next_consumption_date = (
+ line.compute_next_consumption_date())
+ lines.extend(subscription.lines)
+ Line.save(lines)
+ cls.save(subscriptions)
+
+ @classmethod
+ def process(cls, subscriptions):
+ to_close = []
+ for subscription in subscriptions:
+ if all(l.next_consumption_date is None
+ for l in subscription.lines):
+ to_close.append(subscription)
+ cls.close(to_close)
+
+ @classmethod
+ @Workflow.transition('closed')
+ def close(cls, subscriptions):
+ for subscription in subscriptions:
+ if not subscription.end_date and subscription.lines:
+ subscription.end_date = max(
+ l.end_date for l in subscription.lines)
+ cls.save(subscriptions)
+
+ @classmethod
+ def generate_invoice(cls, date=None):
+ pool = Pool()
+ Date = pool.get('ir.date')
+ Consumption = pool.get('sale.subscription.line.consumption')
+ Invoice = pool.get('account.invoice')
+ InvoiceLine = pool.get('account.invoice.line')
+
+ if date is None:
+ date = Date.today()
+
+ consumptions = Consumption.search([
+ ('invoice_line', '=', None),
+ ('line.subscription.next_invoice_date', '<=', date),
+ ('line.subscription.state', 'in', ['running', 'closed']),
+ ('line.subscription.company', '=',
+ Transaction().context.get('company')),
+ ],
+ order=[
+ ('line.subscription.id', 'DESC'),
+ ])
+
+ def keyfunc(consumption):
+ return consumption.line.subscription
+ invoices = {}
+ lines = {}
+ for subscription, consumptions in groupby(consumptions, key=keyfunc):
+ invoices[subscription] = invoice = subscription._get_invoice()
+ lines[subscription] = Consumption.get_invoice_lines(
+ consumptions, invoice)
+
+ all_invoices = list(invoices.values())
+ Invoice.save(all_invoices)
+
+ all_invoice_lines = []
+ for subscription, invoice in invoices.items():
+ invoice_lines, _ = lines[subscription]
+ for line in invoice_lines:
+ line.invoice = invoice
+ all_invoice_lines.extend(invoice_lines)
+ InvoiceLine.save(all_invoice_lines)
+
+ all_consumptions = []
+ for values in lines.values():
+ for invoice_line, consumptions in zip(*values):
+ for consumption in consumptions:
+ assert not consumption.invoice_line
+ consumption.invoice_line = invoice_line
+ all_consumptions.append(consumption)
+ Consumption.save(all_consumptions)
+
+ Invoice.update_taxes(all_invoices)
+
+ subscriptions = cls.search([
+ ('next_invoice_date', '<=', date),
+ ])
+ for subscription in subscriptions:
+ if subscription.state == 'running':
+ while subscription.next_invoice_date <= date:
+ subscription.next_invoice_date = (
+ subscription.compute_next_invoice_date())
+ else:
+ subscription.next_invoice_date = None
+ cls.save(subscriptions)
+
+ def _get_invoice(self):
+ pool = Pool()
+ Invoice = pool.get('account.invoice')
+ party = self.invoice_party or self.party
+ invoice = Invoice(
+ company=self.company,
+ type='out',
+ party=party,
+ invoice_address=self.invoice_address,
+ currency=self.currency,
+ account=party.account_receivable_used,
+ )
+ invoice.on_change_type()
+ invoice.payment_term = self.payment_term
+ return invoice
+
+
+class Line(sequence_ordered(), ModelSQL, ModelView):
+ "Subscription Line"
+ __name__ = 'sale.subscription.line'
+
+ subscription = fields.Many2One(
+ 'sale.subscription', "Subscription", required=True, select=True,
+ ondelete='CASCADE',
+ states={
+ 'readonly': ((Eval('subscription_state') != 'draft')
+ & Bool(Eval('subscription'))),
+ },
+ depends=['subscription_state'],
+ help="Add the line below the subscription.")
+ subscription_state = fields.Function(
+ fields.Selection('get_subscription_states', "Subscription State"),
+ 'on_change_with_subscription_state')
+ subscription_start_date = fields.Function(
+ fields.Date("Subscription Start Date"),
+ 'on_change_with_subscription_start_date')
+ subscription_end_date = fields.Function(
+ fields.Date("Subscription End Date"),
+ 'on_change_with_subscription_end_date')
+ company = fields.Function(
+ fields.Many2One('company.company', "Company"),
+ 'on_change_with_company')
+
+ service = fields.Many2One(
+ 'sale.subscription.service', "Service", required=True,
+ states={
+ 'readonly': Eval('subscription_state') != 'draft',
+ },
+ context={
+ 'company': Eval('company', None),
+ },
+ depends=['subscription_state', 'company'])
+ description = fields.Text("Description",
+ states={
+ 'readonly': Eval('subscription_state') != 'draft',
+ },
+ depends=['subscription_state'])
+
+ quantity = fields.Float(
+ "Quantity", digits=(16, Eval('unit_digits', 2)),
+ states={
+ 'readonly': Eval('subscription_state') != 'draft',
+ 'required': Bool(Eval('consumption_recurrence')),
+ },
+ depends=[
+ 'unit_digits', 'subscription_state', 'consumption_recurrence'])
+ unit = fields.Many2One(
+ 'product.uom', "Unit", required=True,
+ states={
+ 'readonly': Eval('subscription_state') != 'draft',
+ },
+ domain=[
+ If(Bool(Eval('service_unit_category')),
+ ('category', '=', Eval('service_unit_category')),
+ ('category', '!=', -1)),
+ ],
+ depends=['subscription_state', 'service_unit_category'])
+ unit_digits = fields.Function(
+ fields.Integer("Unit Digits"), 'on_change_with_unit_digits')
+ service_unit_category = fields.Function(
+ fields.Many2One('product.uom.category', "Service Unit Category"),
+ 'on_change_with_service_unit_category')
+
+ unit_price = fields.Numeric(
+ "Unit Price", digits=price_digits,
+ states={
+ 'readonly': Eval('subscription_state') != 'draft',
+ },
+ depends=['subscription_state'])
+ currency = fields.Function(fields.Many2One('currency.currency',
+ 'Currency'), 'on_change_with_currency')
+ consumption_recurrence = fields.Many2One(
+ 'sale.subscription.recurrence.rule.set', "Consumption Recurrence",
+ states={
+ 'readonly': Eval('subscription_state') != 'draft',
+ },
+ depends=['subscription_state'])
+ consumption_delay = fields.TimeDelta(
+ "Consumption Delay",
+ states={
+ 'readonly': Eval('subscription_state') != 'draft',
+ 'invisible': ~Eval('consumption_recurrence'),
+ },
+ depends=['subscription_state', 'consumption_recurrence'])
+ next_consumption_date = fields.Date("Next Consumption Date", readonly=True)
+ next_consumption_date_delayed = fields.Function(
+ fields.Date("Next Consumption Delayed"),
+ 'get_next_consumption_date_delayed')
+ consumed_until = fields.Date("Consumed until", readonly=True)
+ start_date = fields.Date(
+ "Start Date", required=True,
+ domain=[
+ ('start_date', '>=', Eval('subscription_start_date')),
+ ],
+ states={
+ 'readonly': ((Eval('subscription_state') != 'draft')
+ | Eval('consumed_until')),
+ },
+ depends=[
+ 'subscription_start_date', 'subscription_state', 'consumed_until'])
+ end_date = fields.Date(
+ "End Date",
+ domain=['OR', [
+ ('end_date', '>=', Eval('start_date')),
+ If(Bool(Eval('subscription_end_date')),
+ ('end_date', '<=', Eval('subscription_end_date')),
+ ()),
+ If(Bool(Eval('consumed_until')),
+ ('end_date', '>=', Eval('consumed_until')),
+ ()),
+ ],
+ ('end_date', '=', None),
+ ],
+ states={
+ 'readonly': ((Eval('subscription_state') != 'draft')
+ | (~Eval('consumed_until') & Eval('consumed_until'))),
+ },
+ depends=['subscription_end_date', 'start_date',
+ 'consumed_until', 'subscription_state', 'consumed_until'])
+
+ @classmethod
+ def __setup__(cls):
+ super().__setup__()
+ cls.__access__.add('subscription')
+
+ @classmethod
+ def __register__(cls, module):
+ pool = Pool()
+ Subscription = pool.get('sale.subscription')
+ transaction = Transaction()
+ cursor = transaction.connection.cursor()
+ table = cls.__table__()
+ subscription = Subscription.__table__()
+
+ # Migration from 4.8: start_date required
+ if backend.TableHandler.table_exist(cls._table):
+ table_h = cls.__table_handler__(module)
+ if table_h.column_exist('start_date'):
+ cursor.execute(*table.update(
+ [table.start_date],
+ subscription.select(
+ subscription.start_date,
+ where=subscription.id == table.subscription),
+ where=table.start_date == Null))
+
+ super(Line, cls).__register__(module)
+ table_h = cls.__table_handler__(module)
+
+ # Migration from 4.8: drop required on description
+ table_h.not_null_action('description', action='remove')
+
+ # Migration from 5.2: replace consumed by consumed_until
+ if table_h.column_exist('consumed'):
+ cursor.execute(*table.update(
+ [table.consumed_until],
+ [Case((table.consumed, Coalesce(
+ table.next_consumption_date,
+ table.end_date)), else_=Null)]))
+ table_h.drop_column('consumed')
+
+ @classmethod
+ def get_subscription_states(cls):
+ pool = Pool()
+ Subscription = pool.get('sale.subscription')
+ return Subscription.fields_get(['state'])['state']['selection']
+
+ @fields.depends('subscription', '_parent_subscription.state')
+ def on_change_with_subscription_state(self, name=None):
+ if self.subscription:
+ return self.subscription.state
+
+ @fields.depends('subscription', '_parent_subscription.start_date')
+ def on_change_with_subscription_start_date(self, name=None):
+ if self.subscription:
+ return self.subscription.start_date
+
+ @fields.depends('subscription', '_parent_subscription.end_date')
+ def on_change_with_subscription_end_date(self, name=None):
+ if self.subscription:
+ return self.subscription.end_date
+
+ @fields.depends('subscription', '_parent_subscription.company')
+ def on_change_with_company(self, name=None):
+ if self.subscription and self.subscription.company:
+ return self.subscription.company.id
+
+ @fields.depends('subscription', 'start_date', 'end_date',
+ '_parent_subscription.start_date', '_parent_subscription.end_date')
+ def on_change_subscription(self):
+ if self.subscription:
+ if not self.start_date:
+ self.start_date = self.subscription.start_date
+ if not self.end_date:
+ self.end_date = self.subscription.end_date
+
+ @classmethod
+ def default_quantity(cls):
+ return 1
+
+ @fields.depends('unit')
+ def on_change_with_unit_digits(self, name=None):
+ if self.unit:
+ return self.unit.digits
+ return 2
+
+ @fields.depends('subscription', '_parent_subscription.currency')
+ def on_change_with_currency(self, name=None):
+ if self.subscription and self.subscription.currency:
+ return self.subscription.currency.id
+
+ @fields.depends('service')
+ def on_change_with_service_unit_category(self, name=None):
+ if self.service:
+ return self.service.product.default_uom_category.id
+
+ @fields.depends('service', 'quantity', 'unit',
+ 'subscription', '_parent_subscription.party',
+ methods=['_get_context_sale_price'])
+ def on_change_service(self):
+ pool = Pool()
+ Product = pool.get('product.product')
+
+ if not self.service:
+ self.consumption_recurrence = None
+ self.consumption_delay = None
+ return
+
+ party = None
+ party_context = {}
+ if self.subscription and self.subscription.party:
+ party = self.subscription.party
+ if party.lang:
+ party_context['language'] = party.lang.code
+
+ product = self.service.product
+ category = product.sale_uom.category
+ if not self.unit or self.unit.category != category:
+ self.unit = product.sale_uom
+ self.unit_digits = product.sale_uom.digits
+
+ with Transaction().set_context(self._get_context_sale_price()):
+ self.unit_price = Product.get_sale_price(
+ [product], self.quantity or 0)[product.id]
+ if self.unit_price:
+ self.unit_price = round_price(self.unit_price)
+
+ self.consumption_recurrence = self.service.consumption_recurrence
+ self.consumption_delay = self.service.consumption_delay
+
+ @fields.depends('subscription', '_parent_subscription.currency',
+ '_parent_subscription.party', 'start_date', 'unit', 'service',
+ 'company')
+ def _get_context_sale_price(self):
+ context = {}
+ if self.subscription:
+ if self.subscription.currency:
+ context['currency'] = self.subscription.currency.id
+ if self.subscription.party:
+ context['customer'] = self.subscription.party.id
+ if self.start_date:
+ context['sale_date'] = self.start_date
+ if self.unit:
+ context['uom'] = self.unit.id
+ elif self.service:
+ context['uom'] = self.service.sale_uom.id
+ if self.company:
+ context['company'] = self.company.id
+ # TODO tax
+ return context
+
+ def get_next_consumption_date_delayed(self, name=None):
+ if self.next_consumption_date and self.consumption_delay:
+ return self.next_consumption_date + self.consumption_delay
+ return self.next_consumption_date
+
+ def get_rec_name(self, name):
+ pool = Pool()
+ Lang = pool.get('ir.lang')
+ lang = Lang.get()
+ return (lang.format(
+ '%.*f', (self.unit.digits, self.quantity or 0))
+ + '%s %s @ %s' % (
+ self.unit.symbol, self.service.rec_name,
+ self.subscription.rec_name))
+
+ @classmethod
+ def search_rec_name(cls, name, clause):
+ return ['OR',
+ ('subscription.rec_name',) + tuple(clause[1:]),
+ ('service.rec_name',) + tuple(clause[1:]),
+ ]
+
+ @classmethod
+ def domain_next_consumption_date_delayed(cls, domain, tables):
+ field = cls.next_consumption_date_delayed._field
+ table, _ = tables[None]
+ name, operator, value = domain
+ Operator = fields.SQL_OPERATORS[operator]
+ column = (
+ table.next_consumption_date + Coalesce(
+ table.consumption_delay, datetime.timedelta()))
+ expression = Operator(column, field._domain_value(operator, value))
+ if isinstance(expression, operators.In) and not expression.right:
+ expression = Literal(False)
+ elif isinstance(expression, operators.NotIn) and not expression.right:
+ expression = Literal(True)
+ expression = field._domain_add_null(
+ column, operator, value, expression)
+ return expression
+
+ @classmethod
+ def generate_consumption(cls, date=None):
+ pool = Pool()
+ Date = pool.get('ir.date')
+ Consumption = pool.get('sale.subscription.line.consumption')
+ Subscription = pool.get('sale.subscription')
+
+ if date is None:
+ date = Date.today()
+
+ remainings = all_lines = cls.search([
+ ('consumption_recurrence', '!=', None),
+ ('next_consumption_date_delayed', '<=', date),
+ ('subscription.state', '=', 'running'),
+ ('subscription.company', '=',
+ Transaction().context.get('company')),
+ ])
+
+ consumptions = []
+ subscription_ids = set()
+ while remainings:
+ lines, remainings = remainings, []
+ for line in lines:
+ consumption = line.get_consumption(line.next_consumption_date)
+ if consumption:
+ consumptions.append(consumption)
+ line.next_consumption_date = (
+ line.compute_next_consumption_date())
+ if line.next_consumption_date:
+ line.consumed_until = (
+ line.next_consumption_date - datetime.timedelta(1))
+ else:
+ line.consumed_until = line.end_date
+ if line.next_consumption_date is None:
+ subscription_ids.add(line.subscription.id)
+ elif line.get_next_consumption_date_delayed() <= date:
+ remainings.append(line)
+
+ Consumption.save(consumptions)
+ cls.save(all_lines)
+ Subscription.process(Subscription.browse(list(subscription_ids)))
+
+ def get_consumption(self, date):
+ pool = Pool()
+ Consumption = pool.get('sale.subscription.line.consumption')
+ end_date = self.end_date or self.subscription.end_date
+ if date < (end_date or datetime.date.max):
+ return Consumption(line=self, quantity=self.quantity, date=date)
+
+ def compute_next_consumption_date(self):
+ if not self.consumption_recurrence:
+ return None
+ date = self.next_consumption_date or self.start_date
+ rruleset = self.consumption_recurrence.rruleset(self.start_date)
+ dt = datetime.datetime.combine(date, datetime.time())
+ inc = (self.start_date == date) and not self.next_consumption_date
+ next_date = rruleset.after(dt, inc=inc)
+ if next_date:
+ next_date = next_date.date()
+ for end_date in [self.end_date, self.subscription.end_date]:
+ if end_date:
+ if next_date > end_date:
+ return None
+ return next_date
+
+ @classmethod
+ def validate(cls, lines):
+ super().validate(lines)
+ for line in lines:
+ line.validate_consumption_recurrence()
+
+ def validate_consumption_recurrence(self):
+ if self.consumption_recurrence:
+ try:
+ self.consumption_recurrence.rruleset(self.start_date)[0]
+ except IndexError:
+ raise InvalidRecurrence(gettext(
+ 'sale_subscription.msg_consumption_recurrence_invalid',
+ line=self.rec_name,
+ subscription=self.subscription.rec_name))
+
+ @classmethod
+ def copy(cls, lines, default=None):
+ if default is None:
+ default = {}
+ else:
+ default = default.copy()
+ default.setdefault('next_consumption_date', None)
+ default.setdefault('consumed', None)
+ default.setdefault('consumed_until', None)
+ return super(Line, cls).copy(lines, default=default)
+
+
+class LineConsumption(ModelSQL, ModelView):
+ "Subscription Line Consumption"
+ __name__ = 'sale.subscription.line.consumption'
+
+ line = fields.Many2One(
+ 'sale.subscription.line', "Line", required=True, select=True,
+ ondelete='RESTRICT')
+ quantity = fields.Float(
+ "Quantity", digits=(16, Eval('unit_digits', 2)), required=True,
+ depends=['unit_digits'])
+ unit_digits = fields.Function(
+ fields.Integer("Unit Digits"), 'on_change_with_unit_digits')
+ date = fields.Date("Date", required=True)
+ invoice_line = fields.Many2One(
+ 'account.invoice.line', "Invoice Line", readonly=True)
+
+ @classmethod
+ def __setup__(cls):
+ super(LineConsumption, cls).__setup__()
+ cls.__access__.add('line')
+ cls._order.insert(0, ('date', 'DESC'))
+
+ @fields.depends('line')
+ def on_change_with_unit_digits(self, name=None):
+ if self.line and self.line.unit:
+ return self.line.unit.digits
+ return 2
+
+ @classmethod
+ def copy(cls, consumptions, default=None):
+ if default is None:
+ default = {}
+ else:
+ default = default.copy()
+ default.setdefault('invoice_line', None)
+ return super(LineConsumption, cls).copy(consumptions, default=default)
+
+ @classmethod
+ def write(cls, *args):
+ for consumptions in args[::2]:
+ for consumption in consumptions:
+ if consumption.invoice_line:
+ raise AccessError(
+ gettext('sale_subscription'
+ '.msg_consumption_modify_invoiced',
+ consumption=consumption.rec_name))
+ super(LineConsumption, cls).write(*args)
+
+ @classmethod
+ def delete(cls, consumptions):
+ for consumption in consumptions:
+ if consumption.invoice_line:
+ raise AccessError(
+ gettext('sale_subscription'
+ '.msg_consumption_modify_invoiced',
+ consumption=consumption.rec_name))
+ super(LineConsumption, cls).delete(consumptions)
+
+ @classmethod
+ def get_invoice_lines(cls, consumptions, invoice):
+ "Return a list of lines and a list of consumptions"
+ pool = Pool()
+ InvoiceLine = pool.get('account.invoice.line')
+
+ lines, grouped_consumptions = [], []
+ consumptions = sorted(
+ consumptions, key=sortable_values(cls._group_invoice_key))
+ for key, sub_consumptions in groupby(
+ consumptions, key=cls._group_invoice_key):
+ sub_consumptions = list(sub_consumptions)
+ line = InvoiceLine(**dict(key))
+ line.invoice_type = 'out'
+ line.type = 'line'
+ line.quantity = sum(c.quantity for c in sub_consumptions)
+
+ line.account = line.product.account_revenue_used
+ if not line.account:
+ raise InvoiceError(
+ gettext('sale_subscription'
+ '.msg_consumption_invoice_missing_account_revenue',
+ product=line.product.rec_name))
+
+ taxes = set()
+ pattern = line._get_tax_rule_pattern()
+ party = invoice.party
+ for tax in line.product.customer_taxes_used:
+ if party.customer_tax_rule:
+ tax_ids = party.customer_tax_rule.apply(tax, pattern)
+ if tax_ids:
+ taxes.update(tax_ids)
+ continue
+ taxes.add(tax.id)
+ if party.customer_tax_rule:
+ tax_ids = party.customer_tax_rule.apply(None, pattern)
+ if tax_ids:
+ taxes.update(tax_ids)
+ line.taxes = taxes
+
+ lines.append(line)
+ grouped_consumptions.append(sub_consumptions)
+ return lines, grouped_consumptions
+
+ @classmethod
+ def _group_invoice_key(cls, consumption):
+ return (
+ ('company', consumption.line.subscription.company),
+ ('currency', consumption.line.subscription.currency),
+ ('unit', consumption.line.unit),
+ ('product', consumption.line.service.product),
+ ('unit_price', consumption.line.unit_price),
+ ('description', consumption.line.description),
+ ('origin', consumption.line),
+ )
+
+
+class CreateLineConsumption(Wizard):
+ "Create Subscription Line Consumption"
+ __name__ = 'sale.subscription.line.consumption.create'
+ start = StateView(
+ 'sale.subscription.line.consumption.create.start',
+ 'sale_subscription.line_consumption_create_start_view_form', [
+ Button("Cancel", 'end', 'tryton-cancel'),
+ Button("Create", 'create_', 'tryton-ok', default=True),
+ ])
+ create_ = StateAction(
+ 'sale_subscription.act_subscription_line_consumption_form')
+
+ def do_create_(self, action):
+ pool = Pool()
+ Line = pool.get('sale.subscription.line')
+ Line.generate_consumption(date=self.start.date)
+ return action, {}
+
+ def transition_create_(self):
+ return 'end'
+
+
+class CreateLineConsumptionStart(ModelView):
+ "Create Subscription Line Consumption"
+ __name__ = 'sale.subscription.line.consumption.create.start'
+
+ date = fields.Date("Date")
+
+ @classmethod
+ def default_date(cls):
+ pool = Pool()
+ Date = pool.get('ir.date')
+ return Date.today()
+
+
+class CreateSubscriptionInvoice(Wizard):
+ "Create Subscription Invoice"
+ __name__ = 'sale.subscription.create_invoice'
+ start = StateView(
+ 'sale.subscription.create_invoice.start',
+ 'sale_subscription.create_invoice_start_view_form', [
+ Button("Cancel", 'end', 'tryton-cancel'),
+ Button("Create", 'create_', 'tryton-ok', default=True),
+ ])
+ create_ = StateTransition()
+
+ def transition_create_(self):
+ pool = Pool()
+ Subscription = pool.get('sale.subscription')
+ Subscription.generate_invoice(date=self.start.date)
+ return 'end'
+
+
+class CreateSubscriptionInvoiceStart(ModelView):
+ "Create Subscription Invoice"
+ __name__ = 'sale.subscription.create_invoice.start'
+
+ date = fields.Date("Date")
+
+ @classmethod
+ def default_date(cls):
+ pool = Pool()
+ Date = pool.get('ir.date')
+ return Date.today()
diff --git a/modules/sale_subscription/subscription.xml b/modules/sale_subscription/subscription.xml
new file mode 100644
index 0000000000..1a2b223245
--- /dev/null
+++ b/modules/sale_subscription/subscription.xml
@@ -0,0 +1,323 @@
+
+
+
+
+
+ tryton-sale-subscription
+ icons/tryton-sale-subscription.svg
+
+
+
+ sale.subscription
+ form
+ subscription_form
+
+
+
+ sale.subscription
+ tree
+ subscription_list
+
+
+
+ Subscriptions
+ sale.subscription
+
+
+
+
+
+
+
+
+
+
+
+
+ Draft
+
+
+
+
+
+
+ Quotation
+
+
+
+
+
+
+ Running
+
+
+
+
+
+ All
+
+
+
+
+
+
+
+
+
+
+
+ Subscriptions
+ sale.subscription
+
+
+
+
+ form_relate
+ party.party,-1
+
+
+
+
+
+
+
+
+ User in companies
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ draft
+ Draft
+
+
+
+
+
+
+
+
+ run
+ Run
+
+
+
+
+
+
+
+
+ cancel
+ Cancel
+
+
+
+
+ quote
+ Quote
+
+
+
+
+ sale.subscription.line
+ form
+ subscription_line_form
+
+
+
+ sale.subscription.line
+ tree
+
+ subscription_line_list
+
+
+
+ sale.subscription.line
+ tree
+
+ subscription_line_list_sequence
+
+
+
+ sale.subscription.line.consumption
+ form
+ subscription_line_consumption_form
+
+
+
+ sale.subscription.line.consumption
+ tree
+ subscription_line_consumption_list
+
+
+
+ Consumptions
+ sale.subscription.line.consumption
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Consumptions
+ sale.subscription.line.consumption
+
+
+
+ form_relate
+ sale.subscription,-1
+
+
+
+
+ Invoices
+ account.invoice
+
+
+
+ form_relate
+ sale.subscription,-1
+
+
+
+
+ Consumptions
+ sale.subscription.line.consumption
+
+
+
+ form_relate
+ sale.subscription.line,-1
+
+
+
+
+ Create Line Consumptions
+ sale.subscription.line.consumption.create
+
+
+
+
+
+
+
+
+
+ sale.subscription.line.consumption.create.start
+ form
+ line_consumption_create_start_form
+
+
+
+ sale.subscription.line|generate_consumption
+
+ days
+
+
+
+ Create Subscription Invoices
+ sale.subscription.create_invoice
+
+
+
+
+
+
+
+
+
+ sale.subscription.create_invoice.start
+ form
+ create_invoice_start_form
+
+
+
+ sale.subscription|generate_invoice
+
+ days
+
+
+
+
diff --git a/modules/sale_subscription/tests/__init__.py b/modules/sale_subscription/tests/__init__.py
new file mode 100644
index 0000000000..3f572594c8
--- /dev/null
+++ b/modules/sale_subscription/tests/__init__.py
@@ -0,0 +1,10 @@
+# This file is part of Tryton. The COPYRIGHT file at the top level of
+# this repository contains the full copyright notices and license terms.
+
+try:
+ from trytond.modules.sale_subscription.tests.test_sale_subscription \
+ import suite
+except ImportError:
+ from .test_sale_subscription import suite
+
+__all__ = ['suite']
diff --git a/modules/sale_subscription/tests/scenario_sale_subscription.rst b/modules/sale_subscription/tests/scenario_sale_subscription.rst
new file mode 100644
index 0000000000..c6941fbe18
--- /dev/null
+++ b/modules/sale_subscription/tests/scenario_sale_subscription.rst
@@ -0,0 +1,197 @@
+==========================
+Sale Subscription Scenario
+==========================
+
+Imports::
+
+ >>> import datetime
+ >>> from decimal import Decimal
+ >>> from dateutil.relativedelta import relativedelta
+ >>> from proteus import Model, Wizard
+ >>> from trytond.tests.tools import activate_modules
+ >>> from trytond.modules.company.tests.tools import create_company, \
+ ... get_company
+ >>> from trytond.modules.account.tests.tools import create_chart, \
+ ... get_accounts
+
+Activate modules::
+
+ >>> config = activate_modules('sale_subscription')
+
+Create company::
+
+ >>> _ = create_company()
+ >>> company = get_company()
+
+Create sale user::
+
+ >>> User = Model.get('res.user')
+ >>> Group = Model.get('res.group')
+
+ >>> sale_user = User()
+ >>> sale_user.name = 'Sale'
+ >>> sale_user.login = 'sale'
+ >>> sale_group, = Group.find([('name', '=', 'Sales')])
+ >>> sale_user.groups.append(sale_group)
+ >>> sale_user.save()
+
+Create product user::
+
+ >>> product_user = User()
+ >>> product_user.name = 'Product'
+ >>> product_user.login = 'product'
+ >>> product_group, = Group.find([('name', '=', 'Product Administration')])
+ >>> product_user.groups.append(product_group)
+ >>> product_user.save()
+
+Create chart of accounts::
+
+ >>> _ = create_chart(company)
+ >>> accounts = get_accounts(company)
+ >>> revenue = accounts['revenue']
+
+Create party::
+
+ >>> Party = Model.get('party.party')
+
+ >>> customer = Party(name='Customer')
+ >>> customer.save()
+
+Create subscription recurrence rule sets::
+
+ >>> RecurrenceRuleSet = Model.get('sale.subscription.recurrence.rule.set')
+
+ >>> monthly = RecurrenceRuleSet(name='Monthly')
+ >>> rule, = monthly.rules
+ >>> rule.freq = 'monthly'
+ >>> rule.interval = 1
+ >>> monthly.save()
+
+ >>> daily = RecurrenceRuleSet(name='Daily')
+ >>> rule, = daily.rules
+ >>> rule.freq = 'daily'
+ >>> rule.interval = 1
+ >>> daily.save()
+
+Create account category::
+
+ >>> ProductCategory = Model.get('product.category')
+ >>> account_category = ProductCategory(name="Account Category")
+ >>> account_category.accounting = True
+ >>> account_category.account_revenue = revenue
+ >>> account_category.save()
+
+Create subscription service::
+
+ >>> Service = Model.get('sale.subscription.service')
+ >>> ProductTemplate = Model.get('product.template')
+ >>> Uom = Model.get('product.uom')
+
+ >>> unit, = Uom.find([('name', '=', 'Unit')])
+
+ >>> template = ProductTemplate()
+ >>> template.name = 'Rental'
+ >>> template.default_uom = unit
+ >>> template.type = 'service'
+ >>> template.list_price = Decimal('10')
+ >>> template.account_category = account_category
+ >>> template.save()
+ >>> product, = template.products
+
+ >>> service = Service()
+ >>> service.product = product
+ >>> service.consumption_recurrence = daily
+ >>> service.save()
+
+Subscribe::
+
+ >>> Subscription = Model.get('sale.subscription')
+
+ >>> subscription = Subscription()
+ >>> subscription.party = customer
+ >>> subscription.start_date = datetime.date(2016, 1, 1)
+ >>> subscription.invoice_start_date = datetime.date(2016, 2, 1)
+ >>> subscription.invoice_recurrence = monthly
+ >>> line = subscription.lines.new()
+ >>> line.service = service
+ >>> line.quantity = 10
+ >>> line.start_date == subscription.start_date
+ True
+
+ >>> subscription.click('quote')
+ >>> subscription.state
+ 'quotation'
+ >>> subscription.click('run')
+ >>> subscription.state
+ 'running'
+
+Create line consumption::
+
+ >>> LineConsumption = Model.get('sale.subscription.line.consumption')
+
+ >>> line_consumption_create = Wizard(
+ ... 'sale.subscription.line.consumption.create')
+ >>> line_consumption_create.form.date = datetime.date(2016, 1, 31)
+ >>> line_consumption_create.execute('create_')
+
+ >>> len(LineConsumption.find([]))
+ 31
+
+ >>> subscription.reload()
+ >>> line, = subscription.lines
+ >>> line.next_consumption_date
+ datetime.date(2016, 2, 1)
+
+Create subscription invoice::
+
+ >>> Invoice = Model.get('account.invoice')
+
+ >>> create_invoice = Wizard('sale.subscription.create_invoice')
+ >>> create_invoice.form.date = datetime.date(2016, 2, 1)
+ >>> create_invoice.execute('create_')
+
+ >>> invoice, = Invoice.find([])
+ >>> line, = invoice.lines
+ >>> line.quantity
+ 310.0
+ >>> line.unit_price
+ Decimal('10.0000')
+
+ >>> subscription.reload()
+ >>> subscription.next_invoice_date
+ datetime.date(2016, 3, 1)
+
+Close subscription::
+
+ >>> subscription.click('draft')
+ >>> subscription.state
+ 'draft'
+ >>> line, = subscription.lines
+ >>> line.end_date = datetime.date(2016, 1, 31)
+ >>> subscription.click('quote')
+ >>> subscription.click('run')
+ >>> subscription.state
+ 'running'
+
+ >>> line_consumption_create = Wizard(
+ ... 'sale.subscription.line.consumption.create')
+ >>> line_consumption_create.form.date = datetime.date(2016, 2, 1)
+ >>> line_consumption_create.execute('create_')
+
+ >>> len(LineConsumption.find([]))
+ 31
+
+ >>> subscription.reload()
+ >>> line, = subscription.lines
+ >>> line.next_consumption_date
+ >>> subscription.state
+ 'closed'
+
+Create final subscription invoice::
+
+ >>> create_invoice = Wizard('sale.subscription.create_invoice')
+ >>> create_invoice.form.date = datetime.date(2016, 3, 1)
+ >>> create_invoice.execute('create_')
+
+ >>> len(Invoice.find([]))
+ 1
diff --git a/modules/sale_subscription/tests/scenario_sale_subscription_advanced_invoice.rst b/modules/sale_subscription/tests/scenario_sale_subscription_advanced_invoice.rst
new file mode 100644
index 0000000000..8f0eeec684
--- /dev/null
+++ b/modules/sale_subscription/tests/scenario_sale_subscription_advanced_invoice.rst
@@ -0,0 +1,178 @@
+================================================
+Sale Subscription with Advanced Invoice Scenario
+================================================
+
+Imports::
+
+ >>> import datetime
+ >>> from decimal import Decimal
+ >>> from dateutil.relativedelta import relativedelta
+ >>> from proteus import Model, Wizard
+ >>> from trytond.tests.tools import activate_modules
+ >>> from trytond.modules.company.tests.tools import create_company, \
+ ... get_company
+ >>> from trytond.modules.account.tests.tools import create_chart, \
+ ... get_accounts
+
+Activate modules::
+
+ >>> config = activate_modules('sale_subscription')
+
+Create company::
+
+ >>> _ = create_company()
+ >>> company = get_company()
+
+Create chart of accounts::
+
+ >>> _ = create_chart(company)
+ >>> accounts = get_accounts(company)
+ >>> revenue = accounts['revenue']
+
+Create party::
+
+ >>> Party = Model.get('party.party')
+
+ >>> customer = Party(name='Customer')
+ >>> customer.save()
+
+Create subscription recurrence rule sets::
+
+ >>> RecurrenceRuleSet = Model.get('sale.subscription.recurrence.rule.set')
+
+ >>> monthly_in_advance = RecurrenceRuleSet(name='Monthly in advance')
+ >>> rule, = monthly_in_advance.rules
+ >>> rule.freq = 'monthly'
+ >>> rule.interval = 1
+ >>> rule.bymonthday = '-1'
+ >>> monthly_in_advance.save()
+
+ >>> monthly = RecurrenceRuleSet(name='Monthly')
+ >>> rule, = monthly.rules
+ >>> rule.freq = 'monthly'
+ >>> rule.interval = 1
+ >>> rule.bymonthday = '1'
+ >>> monthly.save()
+
+Create account category::
+
+ >>> ProductCategory = Model.get('product.category')
+ >>> account_category = ProductCategory(name="Account Category")
+ >>> account_category.accounting = True
+ >>> account_category.account_revenue = revenue
+ >>> account_category.save()
+
+Create subscription service::
+
+ >>> Service = Model.get('sale.subscription.service')
+ >>> ProductTemplate = Model.get('product.template')
+ >>> Uom = Model.get('product.uom')
+
+ >>> unit, = Uom.find([('name', '=', 'Unit')])
+
+ >>> template = ProductTemplate()
+ >>> template.name = 'Rental'
+ >>> template.default_uom = unit
+ >>> template.type = 'service'
+ >>> template.list_price = Decimal('10')
+ >>> template.account_category = account_category
+ >>> template.save()
+ >>> product, = template.products
+
+ >>> service = Service()
+ >>> service.product = product
+ >>> service.consumption_recurrence = monthly
+ >>> service.consumption_delay = datetime.timedelta(days=-1)
+ >>> service.save()
+
+Subscribe with start date greater than invoice start date::
+
+ >>> Subscription = Model.get('sale.subscription')
+
+ >>> subscription = Subscription()
+ >>> subscription.party = customer
+ >>> subscription.start_date = datetime.date(2016, 2, 1)
+ >>> subscription.invoice_start_date = datetime.date(2016, 1, 31)
+ >>> subscription.invoice_recurrence = monthly_in_advance
+ >>> line = subscription.lines.new()
+ >>> line.service = service
+ >>> line.quantity = 10
+
+ >>> subscription.click('quote')
+ >>> subscription.click('run')
+ >>> subscription.reload()
+ >>> subscription.next_invoice_date
+ datetime.date(2016, 1, 31)
+ >>> line, = subscription.lines
+ >>> line.next_consumption_date_delayed
+ datetime.date(2016, 1, 31)
+
+Create line consumption::
+
+ >>> LineConsumption = Model.get('sale.subscription.line.consumption')
+
+ >>> line_consumption_create = Wizard(
+ ... 'sale.subscription.line.consumption.create')
+ >>> line_consumption_create.form.date = datetime.date(2016, 1, 31)
+ >>> line_consumption_create.execute('create_')
+
+ >>> len(LineConsumption.find([]))
+ 1
+
+ >>> subscription.reload()
+ >>> subscription.next_invoice_date
+ datetime.date(2016, 1, 31)
+ >>> line, = subscription.lines
+ >>> line.next_consumption_date
+ datetime.date(2016, 3, 1)
+ >>> line.next_consumption_date_delayed
+ datetime.date(2016, 2, 29)
+
+Create subscription invoice::
+
+ >>> Invoice = Model.get('account.invoice')
+
+ >>> create_invoice = Wizard('sale.subscription.create_invoice')
+ >>> create_invoice.form.date = datetime.date(2016, 1, 31)
+ >>> create_invoice.execute('create_')
+
+ >>> invoice, = Invoice.find([])
+ >>> line, = invoice.lines
+ >>> line.quantity
+ 10.0
+
+ >>> subscription.reload()
+ >>> subscription.next_invoice_date
+ datetime.date(2016, 2, 29)
+
+Consume and invoice again::
+
+ >>> line_consumption_create = Wizard(
+ ... 'sale.subscription.line.consumption.create')
+ >>> line_consumption_create.form.date = datetime.date(2016, 2, 29)
+ >>> line_consumption_create.execute('create_')
+
+ >>> len(LineConsumption.find([]))
+ 2
+
+ >>> subscription.reload()
+ >>> subscription.next_invoice_date
+ datetime.date(2016, 2, 29)
+ >>> line, = subscription.lines
+ >>> line.next_consumption_date
+ datetime.date(2016, 4, 1)
+ >>> line.next_consumption_date_delayed
+ datetime.date(2016, 3, 31)
+
+ >>> create_invoice = Wizard('sale.subscription.create_invoice')
+ >>> create_invoice.form.date = datetime.date(2016, 2, 29)
+ >>> create_invoice.execute('create_')
+
+ >>> invoice2, = Invoice.find([('id', '!=', invoice.id)])
+ >>> line, = invoice2.lines
+ >>> line.quantity
+ 10.0
+
+ >>> subscription.reload()
+ >>> subscription.next_invoice_date
+ datetime.date(2016, 3, 31)
\ No newline at end of file
diff --git a/modules/sale_subscription/tests/scenario_sale_subscription_new_line.rst b/modules/sale_subscription/tests/scenario_sale_subscription_new_line.rst
new file mode 100644
index 0000000000..e18d5030fd
--- /dev/null
+++ b/modules/sale_subscription/tests/scenario_sale_subscription_new_line.rst
@@ -0,0 +1,164 @@
+===================================
+Sale Subscription New Line Scenario
+===================================
+
+Imports::
+
+ >>> import datetime
+ >>> from decimal import Decimal
+ >>> from dateutil.relativedelta import relativedelta
+ >>> from proteus import Model, Wizard
+ >>> from trytond.tests.tools import activate_modules
+ >>> from trytond.modules.company.tests.tools import create_company, \
+ ... get_company
+ >>> from trytond.modules.account.tests.tools import create_chart, \
+ ... get_accounts
+
+Activate modules::
+
+ >>> config = activate_modules('sale_subscription')
+
+Create company::
+
+ >>> _ = create_company()
+ >>> company = get_company()
+
+Create chart of accounts::
+
+ >>> _ = create_chart(company)
+ >>> accounts = get_accounts(company)
+ >>> revenue = accounts['revenue']
+
+Create party::
+
+ >>> Party = Model.get('party.party')
+
+ >>> customer = Party(name='Customer')
+ >>> customer.save()
+
+Create subscription recurrence rule sets::
+
+ >>> RecurrenceRuleSet = Model.get('sale.subscription.recurrence.rule.set')
+
+ >>> monthly = RecurrenceRuleSet(name='Monthly')
+ >>> rule, = monthly.rules
+ >>> rule.freq = 'monthly'
+ >>> rule.interval = 1
+ >>> monthly.save()
+
+Create account category::
+
+ >>> ProductCategory = Model.get('product.category')
+ >>> account_category = ProductCategory(name="Account Category")
+ >>> account_category.accounting = True
+ >>> account_category.account_revenue = revenue
+ >>> account_category.save()
+
+Create subscription service::
+
+ >>> Service = Model.get('sale.subscription.service')
+ >>> ProductTemplate = Model.get('product.template')
+ >>> Uom = Model.get('product.uom')
+
+ >>> unit, = Uom.find([('name', '=', 'Unit')])
+
+ >>> template = ProductTemplate()
+ >>> template.name = 'Rental'
+ >>> template.default_uom = unit
+ >>> template.type = 'service'
+ >>> template.list_price = Decimal('10')
+ >>> template.account_category = account_category
+ >>> template.save()
+ >>> product, = template.products
+
+ >>> service = Service()
+ >>> service.product = product
+ >>> service.consumption_recurrence = monthly
+ >>> service.save()
+
+Subscribe::
+
+ >>> Subscription = Model.get('sale.subscription')
+
+ >>> subscription = Subscription()
+ >>> subscription.party = customer
+ >>> subscription.start_date = datetime.date(2019, 1, 1)
+ >>> subscription.invoice_recurrence = monthly
+ >>> line = subscription.lines.new()
+ >>> line.service = service
+ >>> line.quantity = 1
+ >>> subscription.click('quote')
+ >>> subscription.state
+ 'quotation'
+ >>> subscription.click('run')
+ >>> subscription.state
+ 'running'
+
+Create consumption for next two months::
+
+ >>> LineConsumption = Model.get('sale.subscription.line.consumption')
+
+ >>> line_consumption_create = Wizard(
+ ... 'sale.subscription.line.consumption.create')
+ >>> line_consumption_create.form.date = datetime.date(2019, 2, 1)
+ >>> line_consumption_create.execute('create_')
+
+ >>> len(LineConsumption.find([]))
+ 2
+
+Create invoice for next two months::
+
+ >>> Invoice = Model.get('account.invoice')
+
+ >>> create_invoice = Wizard('sale.subscription.create_invoice')
+ >>> create_invoice.form.date = datetime.date(2019, 2, 1)
+ >>> create_invoice.execute('create_')
+
+ >>> invoice, = Invoice.find([])
+ >>> line, = invoice.lines
+ >>> line.quantity
+ 2.0
+ >>> line.unit_price
+ Decimal('10.0000')
+
+Close subscription::
+
+ >>> subscription.click('draft')
+ >>> subscription.state
+ 'draft'
+ >>> line, = subscription.lines
+ >>> line.consumed_until
+ datetime.date(2019, 2, 28)
+ >>> line.end_date = datetime.date(2019, 2, 28)
+ >>> new_line = subscription.lines.new()
+ >>> new_line.service = service
+ >>> new_line.quantity = 1
+ >>> new_line.start_date = datetime.date(2019, 3, 1)
+ >>> new_line.unit_price = Decimal('15.00')
+ >>> subscription.click('quote')
+ >>> subscription.click('run')
+ >>> subscription.state
+ 'running'
+
+ >>> line_consumption_create = Wizard(
+ ... 'sale.subscription.line.consumption.create')
+ >>> line_consumption_create.form.date = datetime.date(2019, 3, 1)
+ >>> line_consumption_create.execute('create_')
+
+ >>> len(LineConsumption.find([]))
+ 3
+
+Create next invoice::
+
+ >>> Invoice = Model.get('account.invoice')
+
+ >>> create_invoice = Wizard('sale.subscription.create_invoice')
+ >>> create_invoice.form.date = datetime.date(2019, 3, 1)
+ >>> create_invoice.execute('create_')
+
+ >>> new_invoice, = Invoice.find([('id', '!=', invoice.id)])
+ >>> line, = new_invoice.lines
+ >>> line.quantity
+ 1.0
+ >>> line.unit_price
+ Decimal('15.00')
diff --git a/modules/sale_subscription/tests/test_sale_subscription.py b/modules/sale_subscription/tests/test_sale_subscription.py
new file mode 100644
index 0000000000..688a9b2791
--- /dev/null
+++ b/modules/sale_subscription/tests/test_sale_subscription.py
@@ -0,0 +1,42 @@
+# This file is part of Tryton. The COPYRIGHT file at the top level of
+# this repository contains the full copyright notices and license terms.
+
+import unittest
+
+import doctest
+
+from trytond.tests.test_tryton import ModuleTestCase
+from trytond.tests.test_tryton import suite as test_suite
+from trytond.tests.test_tryton import doctest_teardown
+from trytond.tests.test_tryton import doctest_checker
+
+from trytond.modules.company.tests import (
+ PartyCompanyCheckEraseMixin, CompanyTestMixin)
+
+
+class SaleSubscriptionTestCase(
+ PartyCompanyCheckEraseMixin, CompanyTestMixin, ModuleTestCase):
+ 'Test Sale Subscription module'
+ module = 'sale_subscription'
+
+
+def suite():
+ suite = test_suite()
+ suite.addTests(unittest.TestLoader().loadTestsFromTestCase(
+ SaleSubscriptionTestCase))
+ suite.addTests(doctest.DocFileSuite(
+ 'scenario_sale_subscription.rst',
+ tearDown=doctest_teardown, encoding='utf-8',
+ checker=doctest_checker,
+ optionflags=doctest.REPORT_ONLY_FIRST_FAILURE))
+ suite.addTests(doctest.DocFileSuite(
+ 'scenario_sale_subscription_new_line.rst',
+ tearDown=doctest_teardown, encoding='utf-8',
+ checker=doctest_checker,
+ optionflags=doctest.REPORT_ONLY_FIRST_FAILURE))
+ suite.addTests(doctest.DocFileSuite(
+ 'scenario_sale_subscription_advanced_invoice.rst',
+ tearDown=doctest_teardown, encoding='utf-8',
+ checker=doctest_checker,
+ optionflags=doctest.REPORT_ONLY_FIRST_FAILURE))
+ return suite
diff --git a/modules/sale_subscription/tox.ini b/modules/sale_subscription/tox.ini
new file mode 100644
index 0000000000..197496c0cb
--- /dev/null
+++ b/modules/sale_subscription/tox.ini
@@ -0,0 +1,15 @@
+[tox]
+envlist = {py36,py37,py38,py39}-{sqlite,postgresql},pypy3-{sqlite,postgresql}
+
+[testenv]
+commands = {envpython} setup.py test
+deps =
+ {py36,py37,py38,py39}-postgresql: psycopg2 >= 2.5
+ pypy3-postgresql: psycopg2cffi >= 2.5
+ py36-sqlite: sqlitebck
+setenv =
+ sqlite: TRYTOND_DATABASE_URI={env:SQLITE_URI:sqlite://}
+ postgresql: TRYTOND_DATABASE_URI={env:POSTGRESQL_URI:postgresql://}
+ sqlite: DB_NAME={env:SQLITE_NAME::memory:}
+ postgresql: DB_NAME={env:POSTGRESQL_NAME:test}
+install_command = pip install --pre --find-links https://trydevpi.tryton.org/?local_version={env:CI_JOB_ID:{env:CI_BUILD_NUMBER}.{env:CI_JOB_NUMBER}} {opts} {packages}
diff --git a/modules/sale_subscription/tryton.cfg b/modules/sale_subscription/tryton.cfg
new file mode 100644
index 0000000000..f24d51b0b7
--- /dev/null
+++ b/modules/sale_subscription/tryton.cfg
@@ -0,0 +1,18 @@
+[tryton]
+version=6.0.3
+depends:
+ account
+ account_invoice
+ company
+ currency
+ ir
+ product
+ res
+ sale
+xml:
+ configuration.xml
+ recurrence.xml
+ service.xml
+ subscription.xml
+ party.xml
+ message.xml
diff --git a/modules/sale_subscription/view/configuration_form.xml b/modules/sale_subscription/view/configuration_form.xml
new file mode 100644
index 0000000000..1976dedbff
--- /dev/null
+++ b/modules/sale_subscription/view/configuration_form.xml
@@ -0,0 +1,9 @@
+
+
+
+
+
+
+
+
diff --git a/modules/sale_subscription/view/create_invoice_start_form.xml b/modules/sale_subscription/view/create_invoice_start_form.xml
new file mode 100644
index 0000000000..5c2ed431a5
--- /dev/null
+++ b/modules/sale_subscription/view/create_invoice_start_form.xml
@@ -0,0 +1,10 @@
+
+
+
diff --git a/modules/sale_subscription/view/line_consumption_create_start_form.xml b/modules/sale_subscription/view/line_consumption_create_start_form.xml
new file mode 100644
index 0000000000..e169bb7156
--- /dev/null
+++ b/modules/sale_subscription/view/line_consumption_create_start_form.xml
@@ -0,0 +1,11 @@
+
+
+
diff --git a/modules/sale_subscription/view/party_form.xml b/modules/sale_subscription/view/party_form.xml
new file mode 100644
index 0000000000..258552aa91
--- /dev/null
+++ b/modules/sale_subscription/view/party_form.xml
@@ -0,0 +1,8 @@
+
+
+
+
+
+
+
diff --git a/modules/sale_subscription/view/recurrence_rule_form.xml b/modules/sale_subscription/view/recurrence_rule_form.xml
new file mode 100644
index 0000000000..e634b6ca70
--- /dev/null
+++ b/modules/sale_subscription/view/recurrence_rule_form.xml
@@ -0,0 +1,29 @@
+
+
+
diff --git a/modules/sale_subscription/view/recurrence_rule_list.xml b/modules/sale_subscription/view/recurrence_rule_list.xml
new file mode 100644
index 0000000000..c457fd658b
--- /dev/null
+++ b/modules/sale_subscription/view/recurrence_rule_list.xml
@@ -0,0 +1,16 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/modules/sale_subscription/view/recurrence_rule_set_form.xml b/modules/sale_subscription/view/recurrence_rule_set_form.xml
new file mode 100644
index 0000000000..5cc5926d18
--- /dev/null
+++ b/modules/sale_subscription/view/recurrence_rule_set_form.xml
@@ -0,0 +1,8 @@
+
+
+
diff --git a/modules/sale_subscription/view/recurrence_rule_set_list.xml b/modules/sale_subscription/view/recurrence_rule_set_list.xml
new file mode 100644
index 0000000000..b4d89538b1
--- /dev/null
+++ b/modules/sale_subscription/view/recurrence_rule_set_list.xml
@@ -0,0 +1,6 @@
+
+
+
+
+
diff --git a/modules/sale_subscription/view/service_form.xml b/modules/sale_subscription/view/service_form.xml
new file mode 100644
index 0000000000..991031d5bf
--- /dev/null
+++ b/modules/sale_subscription/view/service_form.xml
@@ -0,0 +1,13 @@
+
+
+
diff --git a/modules/sale_subscription/view/service_list.xml b/modules/sale_subscription/view/service_list.xml
new file mode 100644
index 0000000000..722f4189d6
--- /dev/null
+++ b/modules/sale_subscription/view/service_list.xml
@@ -0,0 +1,8 @@
+
+
+
+
+
+
+
diff --git a/modules/sale_subscription/view/subscription_form.xml b/modules/sale_subscription/view/subscription_form.xml
new file mode 100644
index 0000000000..c883e6d030
--- /dev/null
+++ b/modules/sale_subscription/view/subscription_form.xml
@@ -0,0 +1,58 @@
+
+
+
diff --git a/modules/sale_subscription/view/subscription_line_consumption_form.xml b/modules/sale_subscription/view/subscription_line_consumption_form.xml
new file mode 100644
index 0000000000..648ffb17c6
--- /dev/null
+++ b/modules/sale_subscription/view/subscription_line_consumption_form.xml
@@ -0,0 +1,13 @@
+
+
+
diff --git a/modules/sale_subscription/view/subscription_line_consumption_list.xml b/modules/sale_subscription/view/subscription_line_consumption_list.xml
new file mode 100644
index 0000000000..9115206b51
--- /dev/null
+++ b/modules/sale_subscription/view/subscription_line_consumption_list.xml
@@ -0,0 +1,9 @@
+
+
+
+
+
+
+
+
diff --git a/modules/sale_subscription/view/subscription_line_form.xml b/modules/sale_subscription/view/subscription_line_form.xml
new file mode 100644
index 0000000000..e3feb40e12
--- /dev/null
+++ b/modules/sale_subscription/view/subscription_line_form.xml
@@ -0,0 +1,39 @@
+
+
+
diff --git a/modules/sale_subscription/view/subscription_line_list.xml b/modules/sale_subscription/view/subscription_line_list.xml
new file mode 100644
index 0000000000..070b98b8a8
--- /dev/null
+++ b/modules/sale_subscription/view/subscription_line_list.xml
@@ -0,0 +1,14 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/modules/sale_subscription/view/subscription_line_list_sequence.xml b/modules/sale_subscription/view/subscription_line_list_sequence.xml
new file mode 100644
index 0000000000..d19d4d9369
--- /dev/null
+++ b/modules/sale_subscription/view/subscription_line_list_sequence.xml
@@ -0,0 +1,14 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/modules/sale_subscription/view/subscription_list.xml b/modules/sale_subscription/view/subscription_list.xml
new file mode 100644
index 0000000000..eb3406bb43
--- /dev/null
+++ b/modules/sale_subscription/view/subscription_list.xml
@@ -0,0 +1,12 @@
+
+
+
+
+
+
+
+
+
+
+
diff --git a/modules/sale_subscription_asset/.drone.yml b/modules/sale_subscription_asset/.drone.yml
new file mode 100644
index 0000000000..2049d30a49
--- /dev/null
+++ b/modules/sale_subscription_asset/.drone.yml
@@ -0,0 +1,68 @@
+clone:
+ hg:
+ image: plugins/hg
+ environment:
+ - HG_SHARE_POOL=/root/.cache/hg
+ volumes:
+ - cache:/root/.cache
+
+pipeline:
+ tox:
+ image: ${IMAGE}
+ environment:
+ - CFLAGS=-O0
+ - DB_CACHE=/cache
+ - TOX_TESTENV_PASSENV=CFLAGS DB_CACHE CI_BUILD_NUMBER CI_JOB_NUMBER CI_JOB_ID
+ - POSTGRESQL_URI=postgresql://postgres@postgresql:5432/
+ commands:
+ - echo "[extensions]" >> /root/.hgrc
+ - echo "hgext.share =" >> /root/.hgrc
+ - echo "[share]" >> /root/.hgrc
+ - echo "pool = /root/.cache/hg" >> /root/.hgrc
+ - pip install tox
+ - tox -e "${TOXENV}-${DATABASE}"
+ volumes:
+ - cache:/root/.cache
+ check_dist:
+ image: ${IMAGE}
+ commands:
+ - pip install twine
+ - python setup.py sdist
+ - twine check dist/*
+
+services:
+ postgresql:
+ image: postgres
+ environment:
+ - POSTGRES_HOST_AUTH_METHOD=trust
+ command: "-c fsync=off -c synchronous_commit=off -c full_page_writes=off"
+ when:
+ matrix:
+ DATABASE: postgresql
+
+matrix:
+ include:
+ - IMAGE: python:3.6
+ TOXENV: py36
+ DATABASE: sqlite
+ - IMAGE: python:3.6
+ TOXENV: py36
+ DATABASE: postgresql
+ - IMAGE: python:3.7
+ TOXENV: py37
+ DATABASE: sqlite
+ - IMAGE: python:3.7
+ TOXENV: py37
+ DATABASE: postgresql
+ - IMAGE: python:3.8
+ TOXENV: py38
+ DATABASE: sqlite
+ - IMAGE: python:3.8
+ TOXENV: py38
+ DATABASE: postgresql
+ - IMAGE: python:3.9
+ TOXENV: py39
+ DATABASE: sqlite
+ - IMAGE: python:3.9
+ TOXENV: py39
+ DATABASE: postgresql
diff --git a/modules/sale_subscription_asset/.flake8 b/modules/sale_subscription_asset/.flake8
new file mode 100644
index 0000000000..fa6b4f66d1
--- /dev/null
+++ b/modules/sale_subscription_asset/.flake8
@@ -0,0 +1,2 @@
+[flake8]
+ignore=E123,E124,E126,E128,E741,W503
diff --git a/modules/sale_subscription_asset/CHANGELOG b/modules/sale_subscription_asset/CHANGELOG
new file mode 100644
index 0000000000..ffed949b57
--- /dev/null
+++ b/modules/sale_subscription_asset/CHANGELOG
@@ -0,0 +1,21 @@
+Version 6.0.1 - 2022-08-17
+* Bug fixes (see mercurial logs for details)
+
+Version 6.0.0 - 2021-05-03
+* Bug fixes (see mercurial logs for details)
+
+Version 5.8.0 - 2020-11-02
+* Bug fixes (see mercurial logs for details)
+* Remove support for Python 3.5
+
+Version 5.6.0 - 2020-05-04
+* Bug fixes (see mercurial logs for details)
+
+Version 5.4.0 - 2019-11-04
+* Bug fixes (see mercurial logs for details)
+
+Version 5.2.0 - 2019-05-06
+* Bug fixes (see mercurial logs for details)
+
+Version 5.0.0 - 2018-10-01
+* Initial release
diff --git a/modules/sale_subscription_asset/COPYRIGHT b/modules/sale_subscription_asset/COPYRIGHT
new file mode 100644
index 0000000000..754027a19c
--- /dev/null
+++ b/modules/sale_subscription_asset/COPYRIGHT
@@ -0,0 +1,16 @@
+Copyright (C) 2018-2022 B2CK
+Copyright (C) 2018-2022 Cédric Krier
+Copyright (C) 2018-2022 Nicolas Évrard
+
+This program is free software: you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation, either version 3 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program. If not, see .
diff --git a/modules/sale_subscription_asset/LICENSE b/modules/sale_subscription_asset/LICENSE
new file mode 100644
index 0000000000..94a9ed024d
--- /dev/null
+++ b/modules/sale_subscription_asset/LICENSE
@@ -0,0 +1,674 @@
+ GNU GENERAL PUBLIC LICENSE
+ Version 3, 29 June 2007
+
+ Copyright (C) 2007 Free Software Foundation, Inc.
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+ Preamble
+
+ The GNU General Public License is a free, copyleft license for
+software and other kinds of works.
+
+ The licenses for most software and other practical works are designed
+to take away your freedom to share and change the works. By contrast,
+the GNU General Public License is intended to guarantee your freedom to
+share and change all versions of a program--to make sure it remains free
+software for all its users. We, the Free Software Foundation, use the
+GNU General Public License for most of our software; it applies also to
+any other work released this way by its authors. You can apply it to
+your programs, too.
+
+ When we speak of free software, we are referring to freedom, not
+price. Our General Public Licenses are designed to make sure that you
+have the freedom to distribute copies of free software (and charge for
+them if you wish), that you receive source code or can get it if you
+want it, that you can change the software or use pieces of it in new
+free programs, and that you know you can do these things.
+
+ To protect your rights, we need to prevent others from denying you
+these rights or asking you to surrender the rights. Therefore, you have
+certain responsibilities if you distribute copies of the software, or if
+you modify it: responsibilities to respect the freedom of others.
+
+ For example, if you distribute copies of such a program, whether
+gratis or for a fee, you must pass on to the recipients the same
+freedoms that you received. You must make sure that they, too, receive
+or can get the source code. And you must show them these terms so they
+know their rights.
+
+ Developers that use the GNU GPL protect your rights with two steps:
+(1) assert copyright on the software, and (2) offer you this License
+giving you legal permission to copy, distribute and/or modify it.
+
+ For the developers' and authors' protection, the GPL clearly explains
+that there is no warranty for this free software. For both users' and
+authors' sake, the GPL requires that modified versions be marked as
+changed, so that their problems will not be attributed erroneously to
+authors of previous versions.
+
+ Some devices are designed to deny users access to install or run
+modified versions of the software inside them, although the manufacturer
+can do so. This is fundamentally incompatible with the aim of
+protecting users' freedom to change the software. The systematic
+pattern of such abuse occurs in the area of products for individuals to
+use, which is precisely where it is most unacceptable. Therefore, we
+have designed this version of the GPL to prohibit the practice for those
+products. If such problems arise substantially in other domains, we
+stand ready to extend this provision to those domains in future versions
+of the GPL, as needed to protect the freedom of users.
+
+ Finally, every program is threatened constantly by software patents.
+States should not allow patents to restrict development and use of
+software on general-purpose computers, but in those that do, we wish to
+avoid the special danger that patents applied to a free program could
+make it effectively proprietary. To prevent this, the GPL assures that
+patents cannot be used to render the program non-free.
+
+ The precise terms and conditions for copying, distribution and
+modification follow.
+
+ TERMS AND CONDITIONS
+
+ 0. Definitions.
+
+ "This License" refers to version 3 of the GNU General Public License.
+
+ "Copyright" also means copyright-like laws that apply to other kinds of
+works, such as semiconductor masks.
+
+ "The Program" refers to any copyrightable work licensed under this
+License. Each licensee is addressed as "you". "Licensees" and
+"recipients" may be individuals or organizations.
+
+ To "modify" a work means to copy from or adapt all or part of the work
+in a fashion requiring copyright permission, other than the making of an
+exact copy. The resulting work is called a "modified version" of the
+earlier work or a work "based on" the earlier work.
+
+ A "covered work" means either the unmodified Program or a work based
+on the Program.
+
+ To "propagate" a work means to do anything with it that, without
+permission, would make you directly or secondarily liable for
+infringement under applicable copyright law, except executing it on a
+computer or modifying a private copy. Propagation includes copying,
+distribution (with or without modification), making available to the
+public, and in some countries other activities as well.
+
+ To "convey" a work means any kind of propagation that enables other
+parties to make or receive copies. Mere interaction with a user through
+a computer network, with no transfer of a copy, is not conveying.
+
+ An interactive user interface displays "Appropriate Legal Notices"
+to the extent that it includes a convenient and prominently visible
+feature that (1) displays an appropriate copyright notice, and (2)
+tells the user that there is no warranty for the work (except to the
+extent that warranties are provided), that licensees may convey the
+work under this License, and how to view a copy of this License. If
+the interface presents a list of user commands or options, such as a
+menu, a prominent item in the list meets this criterion.
+
+ 1. Source Code.
+
+ The "source code" for a work means the preferred form of the work
+for making modifications to it. "Object code" means any non-source
+form of a work.
+
+ A "Standard Interface" means an interface that either is an official
+standard defined by a recognized standards body, or, in the case of
+interfaces specified for a particular programming language, one that
+is widely used among developers working in that language.
+
+ The "System Libraries" of an executable work include anything, other
+than the work as a whole, that (a) is included in the normal form of
+packaging a Major Component, but which is not part of that Major
+Component, and (b) serves only to enable use of the work with that
+Major Component, or to implement a Standard Interface for which an
+implementation is available to the public in source code form. A
+"Major Component", in this context, means a major essential component
+(kernel, window system, and so on) of the specific operating system
+(if any) on which the executable work runs, or a compiler used to
+produce the work, or an object code interpreter used to run it.
+
+ The "Corresponding Source" for a work in object code form means all
+the source code needed to generate, install, and (for an executable
+work) run the object code and to modify the work, including scripts to
+control those activities. However, it does not include the work's
+System Libraries, or general-purpose tools or generally available free
+programs which are used unmodified in performing those activities but
+which are not part of the work. For example, Corresponding Source
+includes interface definition files associated with source files for
+the work, and the source code for shared libraries and dynamically
+linked subprograms that the work is specifically designed to require,
+such as by intimate data communication or control flow between those
+subprograms and other parts of the work.
+
+ The Corresponding Source need not include anything that users
+can regenerate automatically from other parts of the Corresponding
+Source.
+
+ The Corresponding Source for a work in source code form is that
+same work.
+
+ 2. Basic Permissions.
+
+ All rights granted under this License are granted for the term of
+copyright on the Program, and are irrevocable provided the stated
+conditions are met. This License explicitly affirms your unlimited
+permission to run the unmodified Program. The output from running a
+covered work is covered by this License only if the output, given its
+content, constitutes a covered work. This License acknowledges your
+rights of fair use or other equivalent, as provided by copyright law.
+
+ You may make, run and propagate covered works that you do not
+convey, without conditions so long as your license otherwise remains
+in force. You may convey covered works to others for the sole purpose
+of having them make modifications exclusively for you, or provide you
+with facilities for running those works, provided that you comply with
+the terms of this License in conveying all material for which you do
+not control copyright. Those thus making or running the covered works
+for you must do so exclusively on your behalf, under your direction
+and control, on terms that prohibit them from making any copies of
+your copyrighted material outside their relationship with you.
+
+ Conveying under any other circumstances is permitted solely under
+the conditions stated below. Sublicensing is not allowed; section 10
+makes it unnecessary.
+
+ 3. Protecting Users' Legal Rights From Anti-Circumvention Law.
+
+ No covered work shall be deemed part of an effective technological
+measure under any applicable law fulfilling obligations under article
+11 of the WIPO copyright treaty adopted on 20 December 1996, or
+similar laws prohibiting or restricting circumvention of such
+measures.
+
+ When you convey a covered work, you waive any legal power to forbid
+circumvention of technological measures to the extent such circumvention
+is effected by exercising rights under this License with respect to
+the covered work, and you disclaim any intention to limit operation or
+modification of the work as a means of enforcing, against the work's
+users, your or third parties' legal rights to forbid circumvention of
+technological measures.
+
+ 4. Conveying Verbatim Copies.
+
+ You may convey verbatim copies of the Program's source code as you
+receive it, in any medium, provided that you conspicuously and
+appropriately publish on each copy an appropriate copyright notice;
+keep intact all notices stating that this License and any
+non-permissive terms added in accord with section 7 apply to the code;
+keep intact all notices of the absence of any warranty; and give all
+recipients a copy of this License along with the Program.
+
+ You may charge any price or no price for each copy that you convey,
+and you may offer support or warranty protection for a fee.
+
+ 5. Conveying Modified Source Versions.
+
+ You may convey a work based on the Program, or the modifications to
+produce it from the Program, in the form of source code under the
+terms of section 4, provided that you also meet all of these conditions:
+
+ a) The work must carry prominent notices stating that you modified
+ it, and giving a relevant date.
+
+ b) The work must carry prominent notices stating that it is
+ released under this License and any conditions added under section
+ 7. This requirement modifies the requirement in section 4 to
+ "keep intact all notices".
+
+ c) You must license the entire work, as a whole, under this
+ License to anyone who comes into possession of a copy. This
+ License will therefore apply, along with any applicable section 7
+ additional terms, to the whole of the work, and all its parts,
+ regardless of how they are packaged. This License gives no
+ permission to license the work in any other way, but it does not
+ invalidate such permission if you have separately received it.
+
+ d) If the work has interactive user interfaces, each must display
+ Appropriate Legal Notices; however, if the Program has interactive
+ interfaces that do not display Appropriate Legal Notices, your
+ work need not make them do so.
+
+ A compilation of a covered work with other separate and independent
+works, which are not by their nature extensions of the covered work,
+and which are not combined with it such as to form a larger program,
+in or on a volume of a storage or distribution medium, is called an
+"aggregate" if the compilation and its resulting copyright are not
+used to limit the access or legal rights of the compilation's users
+beyond what the individual works permit. Inclusion of a covered work
+in an aggregate does not cause this License to apply to the other
+parts of the aggregate.
+
+ 6. Conveying Non-Source Forms.
+
+ You may convey a covered work in object code form under the terms
+of sections 4 and 5, provided that you also convey the
+machine-readable Corresponding Source under the terms of this License,
+in one of these ways:
+
+ a) Convey the object code in, or embodied in, a physical product
+ (including a physical distribution medium), accompanied by the
+ Corresponding Source fixed on a durable physical medium
+ customarily used for software interchange.
+
+ b) Convey the object code in, or embodied in, a physical product
+ (including a physical distribution medium), accompanied by a
+ written offer, valid for at least three years and valid for as
+ long as you offer spare parts or customer support for that product
+ model, to give anyone who possesses the object code either (1) a
+ copy of the Corresponding Source for all the software in the
+ product that is covered by this License, on a durable physical
+ medium customarily used for software interchange, for a price no
+ more than your reasonable cost of physically performing this
+ conveying of source, or (2) access to copy the
+ Corresponding Source from a network server at no charge.
+
+ c) Convey individual copies of the object code with a copy of the
+ written offer to provide the Corresponding Source. This
+ alternative is allowed only occasionally and noncommercially, and
+ only if you received the object code with such an offer, in accord
+ with subsection 6b.
+
+ d) Convey the object code by offering access from a designated
+ place (gratis or for a charge), and offer equivalent access to the
+ Corresponding Source in the same way through the same place at no
+ further charge. You need not require recipients to copy the
+ Corresponding Source along with the object code. If the place to
+ copy the object code is a network server, the Corresponding Source
+ may be on a different server (operated by you or a third party)
+ that supports equivalent copying facilities, provided you maintain
+ clear directions next to the object code saying where to find the
+ Corresponding Source. Regardless of what server hosts the
+ Corresponding Source, you remain obligated to ensure that it is
+ available for as long as needed to satisfy these requirements.
+
+ e) Convey the object code using peer-to-peer transmission, provided
+ you inform other peers where the object code and Corresponding
+ Source of the work are being offered to the general public at no
+ charge under subsection 6d.
+
+ A separable portion of the object code, whose source code is excluded
+from the Corresponding Source as a System Library, need not be
+included in conveying the object code work.
+
+ A "User Product" is either (1) a "consumer product", which means any
+tangible personal property which is normally used for personal, family,
+or household purposes, or (2) anything designed or sold for incorporation
+into a dwelling. In determining whether a product is a consumer product,
+doubtful cases shall be resolved in favor of coverage. For a particular
+product received by a particular user, "normally used" refers to a
+typical or common use of that class of product, regardless of the status
+of the particular user or of the way in which the particular user
+actually uses, or expects or is expected to use, the product. A product
+is a consumer product regardless of whether the product has substantial
+commercial, industrial or non-consumer uses, unless such uses represent
+the only significant mode of use of the product.
+
+ "Installation Information" for a User Product means any methods,
+procedures, authorization keys, or other information required to install
+and execute modified versions of a covered work in that User Product from
+a modified version of its Corresponding Source. The information must
+suffice to ensure that the continued functioning of the modified object
+code is in no case prevented or interfered with solely because
+modification has been made.
+
+ If you convey an object code work under this section in, or with, or
+specifically for use in, a User Product, and the conveying occurs as
+part of a transaction in which the right of possession and use of the
+User Product is transferred to the recipient in perpetuity or for a
+fixed term (regardless of how the transaction is characterized), the
+Corresponding Source conveyed under this section must be accompanied
+by the Installation Information. But this requirement does not apply
+if neither you nor any third party retains the ability to install
+modified object code on the User Product (for example, the work has
+been installed in ROM).
+
+ The requirement to provide Installation Information does not include a
+requirement to continue to provide support service, warranty, or updates
+for a work that has been modified or installed by the recipient, or for
+the User Product in which it has been modified or installed. Access to a
+network may be denied when the modification itself materially and
+adversely affects the operation of the network or violates the rules and
+protocols for communication across the network.
+
+ Corresponding Source conveyed, and Installation Information provided,
+in accord with this section must be in a format that is publicly
+documented (and with an implementation available to the public in
+source code form), and must require no special password or key for
+unpacking, reading or copying.
+
+ 7. Additional Terms.
+
+ "Additional permissions" are terms that supplement the terms of this
+License by making exceptions from one or more of its conditions.
+Additional permissions that are applicable to the entire Program shall
+be treated as though they were included in this License, to the extent
+that they are valid under applicable law. If additional permissions
+apply only to part of the Program, that part may be used separately
+under those permissions, but the entire Program remains governed by
+this License without regard to the additional permissions.
+
+ When you convey a copy of a covered work, you may at your option
+remove any additional permissions from that copy, or from any part of
+it. (Additional permissions may be written to require their own
+removal in certain cases when you modify the work.) You may place
+additional permissions on material, added by you to a covered work,
+for which you have or can give appropriate copyright permission.
+
+ Notwithstanding any other provision of this License, for material you
+add to a covered work, you may (if authorized by the copyright holders of
+that material) supplement the terms of this License with terms:
+
+ a) Disclaiming warranty or limiting liability differently from the
+ terms of sections 15 and 16 of this License; or
+
+ b) Requiring preservation of specified reasonable legal notices or
+ author attributions in that material or in the Appropriate Legal
+ Notices displayed by works containing it; or
+
+ c) Prohibiting misrepresentation of the origin of that material, or
+ requiring that modified versions of such material be marked in
+ reasonable ways as different from the original version; or
+
+ d) Limiting the use for publicity purposes of names of licensors or
+ authors of the material; or
+
+ e) Declining to grant rights under trademark law for use of some
+ trade names, trademarks, or service marks; or
+
+ f) Requiring indemnification of licensors and authors of that
+ material by anyone who conveys the material (or modified versions of
+ it) with contractual assumptions of liability to the recipient, for
+ any liability that these contractual assumptions directly impose on
+ those licensors and authors.
+
+ All other non-permissive additional terms are considered "further
+restrictions" within the meaning of section 10. If the Program as you
+received it, or any part of it, contains a notice stating that it is
+governed by this License along with a term that is a further
+restriction, you may remove that term. If a license document contains
+a further restriction but permits relicensing or conveying under this
+License, you may add to a covered work material governed by the terms
+of that license document, provided that the further restriction does
+not survive such relicensing or conveying.
+
+ If you add terms to a covered work in accord with this section, you
+must place, in the relevant source files, a statement of the
+additional terms that apply to those files, or a notice indicating
+where to find the applicable terms.
+
+ Additional terms, permissive or non-permissive, may be stated in the
+form of a separately written license, or stated as exceptions;
+the above requirements apply either way.
+
+ 8. Termination.
+
+ You may not propagate or modify a covered work except as expressly
+provided under this License. Any attempt otherwise to propagate or
+modify it is void, and will automatically terminate your rights under
+this License (including any patent licenses granted under the third
+paragraph of section 11).
+
+ However, if you cease all violation of this License, then your
+license from a particular copyright holder is reinstated (a)
+provisionally, unless and until the copyright holder explicitly and
+finally terminates your license, and (b) permanently, if the copyright
+holder fails to notify you of the violation by some reasonable means
+prior to 60 days after the cessation.
+
+ Moreover, your license from a particular copyright holder is
+reinstated permanently if the copyright holder notifies you of the
+violation by some reasonable means, this is the first time you have
+received notice of violation of this License (for any work) from that
+copyright holder, and you cure the violation prior to 30 days after
+your receipt of the notice.
+
+ Termination of your rights under this section does not terminate the
+licenses of parties who have received copies or rights from you under
+this License. If your rights have been terminated and not permanently
+reinstated, you do not qualify to receive new licenses for the same
+material under section 10.
+
+ 9. Acceptance Not Required for Having Copies.
+
+ You are not required to accept this License in order to receive or
+run a copy of the Program. Ancillary propagation of a covered work
+occurring solely as a consequence of using peer-to-peer transmission
+to receive a copy likewise does not require acceptance. However,
+nothing other than this License grants you permission to propagate or
+modify any covered work. These actions infringe copyright if you do
+not accept this License. Therefore, by modifying or propagating a
+covered work, you indicate your acceptance of this License to do so.
+
+ 10. Automatic Licensing of Downstream Recipients.
+
+ Each time you convey a covered work, the recipient automatically
+receives a license from the original licensors, to run, modify and
+propagate that work, subject to this License. You are not responsible
+for enforcing compliance by third parties with this License.
+
+ An "entity transaction" is a transaction transferring control of an
+organization, or substantially all assets of one, or subdividing an
+organization, or merging organizations. If propagation of a covered
+work results from an entity transaction, each party to that
+transaction who receives a copy of the work also receives whatever
+licenses to the work the party's predecessor in interest had or could
+give under the previous paragraph, plus a right to possession of the
+Corresponding Source of the work from the predecessor in interest, if
+the predecessor has it or can get it with reasonable efforts.
+
+ You may not impose any further restrictions on the exercise of the
+rights granted or affirmed under this License. For example, you may
+not impose a license fee, royalty, or other charge for exercise of
+rights granted under this License, and you may not initiate litigation
+(including a cross-claim or counterclaim in a lawsuit) alleging that
+any patent claim is infringed by making, using, selling, offering for
+sale, or importing the Program or any portion of it.
+
+ 11. Patents.
+
+ A "contributor" is a copyright holder who authorizes use under this
+License of the Program or a work on which the Program is based. The
+work thus licensed is called the contributor's "contributor version".
+
+ A contributor's "essential patent claims" are all patent claims
+owned or controlled by the contributor, whether already acquired or
+hereafter acquired, that would be infringed by some manner, permitted
+by this License, of making, using, or selling its contributor version,
+but do not include claims that would be infringed only as a
+consequence of further modification of the contributor version. For
+purposes of this definition, "control" includes the right to grant
+patent sublicenses in a manner consistent with the requirements of
+this License.
+
+ Each contributor grants you a non-exclusive, worldwide, royalty-free
+patent license under the contributor's essential patent claims, to
+make, use, sell, offer for sale, import and otherwise run, modify and
+propagate the contents of its contributor version.
+
+ In the following three paragraphs, a "patent license" is any express
+agreement or commitment, however denominated, not to enforce a patent
+(such as an express permission to practice a patent or covenant not to
+sue for patent infringement). To "grant" such a patent license to a
+party means to make such an agreement or commitment not to enforce a
+patent against the party.
+
+ If you convey a covered work, knowingly relying on a patent license,
+and the Corresponding Source of the work is not available for anyone
+to copy, free of charge and under the terms of this License, through a
+publicly available network server or other readily accessible means,
+then you must either (1) cause the Corresponding Source to be so
+available, or (2) arrange to deprive yourself of the benefit of the
+patent license for this particular work, or (3) arrange, in a manner
+consistent with the requirements of this License, to extend the patent
+license to downstream recipients. "Knowingly relying" means you have
+actual knowledge that, but for the patent license, your conveying the
+covered work in a country, or your recipient's use of the covered work
+in a country, would infringe one or more identifiable patents in that
+country that you have reason to believe are valid.
+
+ If, pursuant to or in connection with a single transaction or
+arrangement, you convey, or propagate by procuring conveyance of, a
+covered work, and grant a patent license to some of the parties
+receiving the covered work authorizing them to use, propagate, modify
+or convey a specific copy of the covered work, then the patent license
+you grant is automatically extended to all recipients of the covered
+work and works based on it.
+
+ A patent license is "discriminatory" if it does not include within
+the scope of its coverage, prohibits the exercise of, or is
+conditioned on the non-exercise of one or more of the rights that are
+specifically granted under this License. You may not convey a covered
+work if you are a party to an arrangement with a third party that is
+in the business of distributing software, under which you make payment
+to the third party based on the extent of your activity of conveying
+the work, and under which the third party grants, to any of the
+parties who would receive the covered work from you, a discriminatory
+patent license (a) in connection with copies of the covered work
+conveyed by you (or copies made from those copies), or (b) primarily
+for and in connection with specific products or compilations that
+contain the covered work, unless you entered into that arrangement,
+or that patent license was granted, prior to 28 March 2007.
+
+ Nothing in this License shall be construed as excluding or limiting
+any implied license or other defenses to infringement that may
+otherwise be available to you under applicable patent law.
+
+ 12. No Surrender of Others' Freedom.
+
+ If conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License. If you cannot convey a
+covered work so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you may
+not convey it at all. For example, if you agree to terms that obligate you
+to collect a royalty for further conveying from those to whom you convey
+the Program, the only way you could satisfy both those terms and this
+License would be to refrain entirely from conveying the Program.
+
+ 13. Use with the GNU Affero General Public License.
+
+ Notwithstanding any other provision of this License, you have
+permission to link or combine any covered work with a work licensed
+under version 3 of the GNU Affero General Public License into a single
+combined work, and to convey the resulting work. The terms of this
+License will continue to apply to the part which is the covered work,
+but the special requirements of the GNU Affero General Public License,
+section 13, concerning interaction through a network will apply to the
+combination as such.
+
+ 14. Revised Versions of this License.
+
+ The Free Software Foundation may publish revised and/or new versions of
+the GNU General Public License from time to time. Such new versions will
+be similar in spirit to the present version, but may differ in detail to
+address new problems or concerns.
+
+ Each version is given a distinguishing version number. If the
+Program specifies that a certain numbered version of the GNU General
+Public License "or any later version" applies to it, you have the
+option of following the terms and conditions either of that numbered
+version or of any later version published by the Free Software
+Foundation. If the Program does not specify a version number of the
+GNU General Public License, you may choose any version ever published
+by the Free Software Foundation.
+
+ If the Program specifies that a proxy can decide which future
+versions of the GNU General Public License can be used, that proxy's
+public statement of acceptance of a version permanently authorizes you
+to choose that version for the Program.
+
+ Later license versions may give you additional or different
+permissions. However, no additional obligations are imposed on any
+author or copyright holder as a result of your choosing to follow a
+later version.
+
+ 15. Disclaimer of Warranty.
+
+ THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY
+APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT
+HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY
+OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO,
+THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM
+IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF
+ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
+
+ 16. Limitation of Liability.
+
+ IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS
+THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY
+GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE
+USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF
+DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD
+PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS),
+EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF
+SUCH DAMAGES.
+
+ 17. Interpretation of Sections 15 and 16.
+
+ If the disclaimer of warranty and limitation of liability provided
+above cannot be given local legal effect according to their terms,
+reviewing courts shall apply local law that most closely approximates
+an absolute waiver of all civil liability in connection with the
+Program, unless a warranty or assumption of liability accompanies a
+copy of the Program in return for a fee.
+
+ END OF TERMS AND CONDITIONS
+
+ How to Apply These Terms to Your New Programs
+
+ If you develop a new program, and you want it to be of the greatest
+possible use to the public, the best way to achieve this is to make it
+free software which everyone can redistribute and change under these terms.
+
+ To do so, attach the following notices to the program. It is safest
+to attach them to the start of each source file to most effectively
+state the exclusion of warranty; and each file should have at least
+the "copyright" line and a pointer to where the full notice is found.
+
+
+ Copyright (C)
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see .
+
+Also add information on how to contact you by electronic and paper mail.
+
+ If the program does terminal interaction, make it output a short
+notice like this when it starts in an interactive mode:
+
+ Copyright (C)
+ This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
+ This is free software, and you are welcome to redistribute it
+ under certain conditions; type `show c' for details.
+
+The hypothetical commands `show w' and `show c' should show the appropriate
+parts of the General Public License. Of course, your program's commands
+might be different; for a GUI interface, you would use an "about box".
+
+ You should also get your employer (if you work as a programmer) or school,
+if any, to sign a "copyright disclaimer" for the program, if necessary.
+For more information on this, and how to apply and follow the GNU GPL, see
+.
+
+ The GNU General Public License does not permit incorporating your program
+into proprietary programs. If your program is a subroutine library, you
+may consider it more useful to permit linking proprietary applications with
+the library. If this is what you want to do, use the GNU Lesser General
+Public License instead of this License. But first, please read
+.
diff --git a/modules/sale_subscription_asset/MANIFEST.in b/modules/sale_subscription_asset/MANIFEST.in
new file mode 100644
index 0000000000..e88b2348a3
--- /dev/null
+++ b/modules/sale_subscription_asset/MANIFEST.in
@@ -0,0 +1,5 @@
+include CHANGELOG
+include COPYRIGHT
+include LICENSE
+include README.rst
+include doc/*
diff --git a/modules/sale_subscription_asset/README.rst b/modules/sale_subscription_asset/README.rst
new file mode 120000
index 0000000000..176d9c2695
--- /dev/null
+++ b/modules/sale_subscription_asset/README.rst
@@ -0,0 +1 @@
+doc/index.rst
\ No newline at end of file
diff --git a/modules/sale_subscription_asset/__init__.py b/modules/sale_subscription_asset/__init__.py
new file mode 100644
index 0000000000..bc81d3508e
--- /dev/null
+++ b/modules/sale_subscription_asset/__init__.py
@@ -0,0 +1,19 @@
+# This file is part of Tryton. The COPYRIGHT file at the top level of
+# this repository contains the full copyright notices and license terms.
+
+from trytond.pool import Pool
+
+from . import sale
+from . import stock
+
+__all__ = ['register']
+
+
+def register():
+ Pool.register(
+ sale.SubscriptionServiceStockLot,
+ sale.SubscriptionService,
+ sale.Subscription,
+ sale.SubscriptionLine,
+ stock.Lot,
+ module='sale_subscription_asset', type_='model')
diff --git a/modules/sale_subscription_asset/doc/index.rst b/modules/sale_subscription_asset/doc/index.rst
new file mode 100644
index 0000000000..546541b63c
--- /dev/null
+++ b/modules/sale_subscription_asset/doc/index.rst
@@ -0,0 +1,18 @@
+Sale Subscription Asset Module
+##############################
+
+The sale subscription asset module adds the notion of asset to the sale
+subscription module.
+
+Two fields are added to the *Service*:
+
+ - *Lots*: All the lots that can be used when providing this service
+ - *Available Lots*: A subset of the preceding field displaying the
+ available lots
+
+On the *Subscription Line*, it is possible to specify the lot to use. When the
+subscription will be running this field will become required for service with
+lots.
+
+On the *Lot*, the field *Subscribed* will point to the line of the subscription
+currently using this lot.
diff --git a/modules/sale_subscription_asset/locale/bg.po b/modules/sale_subscription_asset/locale/bg.po
new file mode 100644
index 0000000000..27d8d0d55f
--- /dev/null
+++ b/modules/sale_subscription_asset/locale/bg.po
@@ -0,0 +1,49 @@
+#
+msgid ""
+msgstr "Content-Type: text/plain; charset=utf-8\n"
+
+msgctxt "field:sale.subscription.line,asset_lot:"
+msgid "Asset Lot"
+msgstr ""
+
+msgctxt "field:sale.subscription.line,asset_lot_required:"
+msgid "Asset Lot Required"
+msgstr ""
+
+msgctxt "field:sale.subscription.service,asset_lots:"
+msgid "Asset Lots"
+msgstr ""
+
+msgctxt "field:sale.subscription.service,asset_lots_available:"
+msgid "Available Asset Lots"
+msgstr ""
+
+msgctxt "field:sale.subscription.service-stock.lot.asset,lot:"
+msgid "Lot"
+msgstr ""
+
+msgctxt "field:sale.subscription.service-stock.lot.asset,service:"
+msgid "Service"
+msgstr ""
+
+msgctxt "field:stock.lot,subscribed:"
+msgid "Subscribed"
+msgstr ""
+
+msgctxt "field:stock.lot,subscription_lines:"
+msgid "Subscription Lines"
+msgstr ""
+
+msgctxt "field:stock.lot,subscription_services:"
+msgid "Services"
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_asset_line_overlap"
+msgid ""
+"The lines \"%(line1)s\" and \"%(line2)s\" overlap, you must use different "
+"dates."
+msgstr ""
+
+msgctxt "model:sale.subscription.service-stock.lot.asset,name:"
+msgid "Subscription Service - Stock Lot Asset"
+msgstr ""
diff --git a/modules/sale_subscription_asset/locale/ca.po b/modules/sale_subscription_asset/locale/ca.po
new file mode 100644
index 0000000000..d4083f83b2
--- /dev/null
+++ b/modules/sale_subscription_asset/locale/ca.po
@@ -0,0 +1,51 @@
+#
+msgid ""
+msgstr "Content-Type: text/plain; charset=utf-8\n"
+
+msgctxt "field:sale.subscription.line,asset_lot:"
+msgid "Asset Lot"
+msgstr "Lot de l'actiu"
+
+msgctxt "field:sale.subscription.line,asset_lot_required:"
+msgid "Asset Lot Required"
+msgstr "Lot de l'actiu obligatori"
+
+msgctxt "field:sale.subscription.service,asset_lots:"
+msgid "Asset Lots"
+msgstr "Lots de l'actiu"
+
+msgctxt "field:sale.subscription.service,asset_lots_available:"
+msgid "Available Asset Lots"
+msgstr "Lots de l'actiu disponibles"
+
+msgctxt "field:sale.subscription.service-stock.lot.asset,lot:"
+msgid "Lot"
+msgstr "Lot"
+
+msgctxt "field:sale.subscription.service-stock.lot.asset,service:"
+msgid "Service"
+msgstr "Servei"
+
+msgctxt "field:stock.lot,subscribed:"
+msgid "Subscribed"
+msgstr "Subscripció"
+
+msgctxt "field:stock.lot,subscription_lines:"
+msgid "Subscription Lines"
+msgstr "Línies de subscripció"
+
+msgctxt "field:stock.lot,subscription_services:"
+msgid "Services"
+msgstr "Serveis"
+
+msgctxt "model:ir.message,text:msg_asset_line_overlap"
+msgid ""
+"The lines \"%(line1)s\" and \"%(line2)s\" overlap, you must use different "
+"dates."
+msgstr ""
+"Les línies \"%(line1)s\" i \"%(line2)s\" es sobreposen, heu d'utilitzar "
+"dates diferents."
+
+msgctxt "model:sale.subscription.service-stock.lot.asset,name:"
+msgid "Subscription Service - Stock Lot Asset"
+msgstr "Servei de subscripció - Lot del actiu"
diff --git a/modules/sale_subscription_asset/locale/cs.po b/modules/sale_subscription_asset/locale/cs.po
new file mode 100644
index 0000000000..27d8d0d55f
--- /dev/null
+++ b/modules/sale_subscription_asset/locale/cs.po
@@ -0,0 +1,49 @@
+#
+msgid ""
+msgstr "Content-Type: text/plain; charset=utf-8\n"
+
+msgctxt "field:sale.subscription.line,asset_lot:"
+msgid "Asset Lot"
+msgstr ""
+
+msgctxt "field:sale.subscription.line,asset_lot_required:"
+msgid "Asset Lot Required"
+msgstr ""
+
+msgctxt "field:sale.subscription.service,asset_lots:"
+msgid "Asset Lots"
+msgstr ""
+
+msgctxt "field:sale.subscription.service,asset_lots_available:"
+msgid "Available Asset Lots"
+msgstr ""
+
+msgctxt "field:sale.subscription.service-stock.lot.asset,lot:"
+msgid "Lot"
+msgstr ""
+
+msgctxt "field:sale.subscription.service-stock.lot.asset,service:"
+msgid "Service"
+msgstr ""
+
+msgctxt "field:stock.lot,subscribed:"
+msgid "Subscribed"
+msgstr ""
+
+msgctxt "field:stock.lot,subscription_lines:"
+msgid "Subscription Lines"
+msgstr ""
+
+msgctxt "field:stock.lot,subscription_services:"
+msgid "Services"
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_asset_line_overlap"
+msgid ""
+"The lines \"%(line1)s\" and \"%(line2)s\" overlap, you must use different "
+"dates."
+msgstr ""
+
+msgctxt "model:sale.subscription.service-stock.lot.asset,name:"
+msgid "Subscription Service - Stock Lot Asset"
+msgstr ""
diff --git a/modules/sale_subscription_asset/locale/de.po b/modules/sale_subscription_asset/locale/de.po
new file mode 100644
index 0000000000..67d2f63fcb
--- /dev/null
+++ b/modules/sale_subscription_asset/locale/de.po
@@ -0,0 +1,51 @@
+#
+msgid ""
+msgstr "Content-Type: text/plain; charset=utf-8\n"
+
+msgctxt "field:sale.subscription.line,asset_lot:"
+msgid "Asset Lot"
+msgstr "Charge Abonnement Objekt"
+
+msgctxt "field:sale.subscription.line,asset_lot_required:"
+msgid "Asset Lot Required"
+msgstr "Anlage Charge erforderlich"
+
+msgctxt "field:sale.subscription.service,asset_lots:"
+msgid "Asset Lots"
+msgstr "Anlage Charge"
+
+msgctxt "field:sale.subscription.service,asset_lots_available:"
+msgid "Available Asset Lots"
+msgstr "Verfügbare Abonnement Objekte"
+
+msgctxt "field:sale.subscription.service-stock.lot.asset,lot:"
+msgid "Lot"
+msgstr "Charge"
+
+msgctxt "field:sale.subscription.service-stock.lot.asset,service:"
+msgid "Service"
+msgstr "Dienstleistung"
+
+msgctxt "field:stock.lot,subscribed:"
+msgid "Subscribed"
+msgstr "Abonniert"
+
+msgctxt "field:stock.lot,subscription_lines:"
+msgid "Subscription Lines"
+msgstr "Abonnementpositionen"
+
+msgctxt "field:stock.lot,subscription_services:"
+msgid "Services"
+msgstr "Dienstleistungen"
+
+msgctxt "model:ir.message,text:msg_asset_line_overlap"
+msgid ""
+"The lines \"%(line1)s\" and \"%(line2)s\" overlap, you must use different "
+"dates."
+msgstr ""
+"Die Positionen \"%(line1)s\" und \"%(line2)s\" überschneiden sich. Es müssen"
+" unterschiedliche Daten verwendet werden."
+
+msgctxt "model:sale.subscription.service-stock.lot.asset,name:"
+msgid "Subscription Service - Stock Lot Asset"
+msgstr "Abonnement Dienstleistung - Charge Abonnement Objekt"
diff --git a/modules/sale_subscription_asset/locale/es.po b/modules/sale_subscription_asset/locale/es.po
new file mode 100644
index 0000000000..27cd216698
--- /dev/null
+++ b/modules/sale_subscription_asset/locale/es.po
@@ -0,0 +1,51 @@
+#
+msgid ""
+msgstr "Content-Type: text/plain; charset=utf-8\n"
+
+msgctxt "field:sale.subscription.line,asset_lot:"
+msgid "Asset Lot"
+msgstr "Lote del activo"
+
+msgctxt "field:sale.subscription.line,asset_lot_required:"
+msgid "Asset Lot Required"
+msgstr "Lote del activo obligatorio"
+
+msgctxt "field:sale.subscription.service,asset_lots:"
+msgid "Asset Lots"
+msgstr "Lotes del activo"
+
+msgctxt "field:sale.subscription.service,asset_lots_available:"
+msgid "Available Asset Lots"
+msgstr "Lotes del activo disponibles"
+
+msgctxt "field:sale.subscription.service-stock.lot.asset,lot:"
+msgid "Lot"
+msgstr "Lote"
+
+msgctxt "field:sale.subscription.service-stock.lot.asset,service:"
+msgid "Service"
+msgstr "Servicio"
+
+msgctxt "field:stock.lot,subscribed:"
+msgid "Subscribed"
+msgstr "Suscripción"
+
+msgctxt "field:stock.lot,subscription_lines:"
+msgid "Subscription Lines"
+msgstr "Lineas de suscripción"
+
+msgctxt "field:stock.lot,subscription_services:"
+msgid "Services"
+msgstr "Servicios"
+
+msgctxt "model:ir.message,text:msg_asset_line_overlap"
+msgid ""
+"The lines \"%(line1)s\" and \"%(line2)s\" overlap, you must use different "
+"dates."
+msgstr ""
+"Las líneas \"%(line1)s\" y \"%(line2)s\" se solapan, debe usar fechas "
+"diferentes."
+
+msgctxt "model:sale.subscription.service-stock.lot.asset,name:"
+msgid "Subscription Service - Stock Lot Asset"
+msgstr "Servicio de suscripción - Lote del activo"
diff --git a/modules/sale_subscription_asset/locale/es_419.po b/modules/sale_subscription_asset/locale/es_419.po
new file mode 100644
index 0000000000..27d8d0d55f
--- /dev/null
+++ b/modules/sale_subscription_asset/locale/es_419.po
@@ -0,0 +1,49 @@
+#
+msgid ""
+msgstr "Content-Type: text/plain; charset=utf-8\n"
+
+msgctxt "field:sale.subscription.line,asset_lot:"
+msgid "Asset Lot"
+msgstr ""
+
+msgctxt "field:sale.subscription.line,asset_lot_required:"
+msgid "Asset Lot Required"
+msgstr ""
+
+msgctxt "field:sale.subscription.service,asset_lots:"
+msgid "Asset Lots"
+msgstr ""
+
+msgctxt "field:sale.subscription.service,asset_lots_available:"
+msgid "Available Asset Lots"
+msgstr ""
+
+msgctxt "field:sale.subscription.service-stock.lot.asset,lot:"
+msgid "Lot"
+msgstr ""
+
+msgctxt "field:sale.subscription.service-stock.lot.asset,service:"
+msgid "Service"
+msgstr ""
+
+msgctxt "field:stock.lot,subscribed:"
+msgid "Subscribed"
+msgstr ""
+
+msgctxt "field:stock.lot,subscription_lines:"
+msgid "Subscription Lines"
+msgstr ""
+
+msgctxt "field:stock.lot,subscription_services:"
+msgid "Services"
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_asset_line_overlap"
+msgid ""
+"The lines \"%(line1)s\" and \"%(line2)s\" overlap, you must use different "
+"dates."
+msgstr ""
+
+msgctxt "model:sale.subscription.service-stock.lot.asset,name:"
+msgid "Subscription Service - Stock Lot Asset"
+msgstr ""
diff --git a/modules/sale_subscription_asset/locale/et.po b/modules/sale_subscription_asset/locale/et.po
new file mode 100644
index 0000000000..27d8d0d55f
--- /dev/null
+++ b/modules/sale_subscription_asset/locale/et.po
@@ -0,0 +1,49 @@
+#
+msgid ""
+msgstr "Content-Type: text/plain; charset=utf-8\n"
+
+msgctxt "field:sale.subscription.line,asset_lot:"
+msgid "Asset Lot"
+msgstr ""
+
+msgctxt "field:sale.subscription.line,asset_lot_required:"
+msgid "Asset Lot Required"
+msgstr ""
+
+msgctxt "field:sale.subscription.service,asset_lots:"
+msgid "Asset Lots"
+msgstr ""
+
+msgctxt "field:sale.subscription.service,asset_lots_available:"
+msgid "Available Asset Lots"
+msgstr ""
+
+msgctxt "field:sale.subscription.service-stock.lot.asset,lot:"
+msgid "Lot"
+msgstr ""
+
+msgctxt "field:sale.subscription.service-stock.lot.asset,service:"
+msgid "Service"
+msgstr ""
+
+msgctxt "field:stock.lot,subscribed:"
+msgid "Subscribed"
+msgstr ""
+
+msgctxt "field:stock.lot,subscription_lines:"
+msgid "Subscription Lines"
+msgstr ""
+
+msgctxt "field:stock.lot,subscription_services:"
+msgid "Services"
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_asset_line_overlap"
+msgid ""
+"The lines \"%(line1)s\" and \"%(line2)s\" overlap, you must use different "
+"dates."
+msgstr ""
+
+msgctxt "model:sale.subscription.service-stock.lot.asset,name:"
+msgid "Subscription Service - Stock Lot Asset"
+msgstr ""
diff --git a/modules/sale_subscription_asset/locale/fa.po b/modules/sale_subscription_asset/locale/fa.po
new file mode 100644
index 0000000000..ff71e6d32d
--- /dev/null
+++ b/modules/sale_subscription_asset/locale/fa.po
@@ -0,0 +1,51 @@
+#
+msgid ""
+msgstr "Content-Type: text/plain; charset=utf-8\n"
+
+msgctxt "field:sale.subscription.line,asset_lot:"
+msgid "Asset Lot"
+msgstr "قطعه دارایی"
+
+msgctxt "field:sale.subscription.line,asset_lot_required:"
+msgid "Asset Lot Required"
+msgstr "قطعه دارایی مورد نیاز"
+
+msgctxt "field:sale.subscription.service,asset_lots:"
+msgid "Asset Lots"
+msgstr "قطعات دارایی"
+
+msgctxt "field:sale.subscription.service,asset_lots_available:"
+msgid "Available Asset Lots"
+msgstr "قطعات دارایی دردسترس"
+
+msgctxt "field:sale.subscription.service-stock.lot.asset,lot:"
+msgid "Lot"
+msgstr "قطعه"
+
+msgctxt "field:sale.subscription.service-stock.lot.asset,service:"
+msgid "Service"
+msgstr "خدمات"
+
+msgctxt "field:stock.lot,subscribed:"
+msgid "Subscribed"
+msgstr "مشترک شده است"
+
+msgctxt "field:stock.lot,subscription_lines:"
+msgid "Subscription Lines"
+msgstr "سطرهای اشتراک"
+
+msgctxt "field:stock.lot,subscription_services:"
+msgid "Services"
+msgstr "خدمات"
+
+msgctxt "model:ir.message,text:msg_asset_line_overlap"
+msgid ""
+"The lines \"%(line1)s\" and \"%(line2)s\" overlap, you must use different "
+"dates."
+msgstr ""
+"سطرهای \"%(line1)s\" و \"%(line2)s\" همپوشانی دارند، شما باید از تاریخ های "
+"متفاوت استفاده کنید."
+
+msgctxt "model:sale.subscription.service-stock.lot.asset,name:"
+msgid "Subscription Service - Stock Lot Asset"
+msgstr "قطعه موجودی دارایی - خدمات اشتراک"
diff --git a/modules/sale_subscription_asset/locale/fi.po b/modules/sale_subscription_asset/locale/fi.po
new file mode 100644
index 0000000000..27d8d0d55f
--- /dev/null
+++ b/modules/sale_subscription_asset/locale/fi.po
@@ -0,0 +1,49 @@
+#
+msgid ""
+msgstr "Content-Type: text/plain; charset=utf-8\n"
+
+msgctxt "field:sale.subscription.line,asset_lot:"
+msgid "Asset Lot"
+msgstr ""
+
+msgctxt "field:sale.subscription.line,asset_lot_required:"
+msgid "Asset Lot Required"
+msgstr ""
+
+msgctxt "field:sale.subscription.service,asset_lots:"
+msgid "Asset Lots"
+msgstr ""
+
+msgctxt "field:sale.subscription.service,asset_lots_available:"
+msgid "Available Asset Lots"
+msgstr ""
+
+msgctxt "field:sale.subscription.service-stock.lot.asset,lot:"
+msgid "Lot"
+msgstr ""
+
+msgctxt "field:sale.subscription.service-stock.lot.asset,service:"
+msgid "Service"
+msgstr ""
+
+msgctxt "field:stock.lot,subscribed:"
+msgid "Subscribed"
+msgstr ""
+
+msgctxt "field:stock.lot,subscription_lines:"
+msgid "Subscription Lines"
+msgstr ""
+
+msgctxt "field:stock.lot,subscription_services:"
+msgid "Services"
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_asset_line_overlap"
+msgid ""
+"The lines \"%(line1)s\" and \"%(line2)s\" overlap, you must use different "
+"dates."
+msgstr ""
+
+msgctxt "model:sale.subscription.service-stock.lot.asset,name:"
+msgid "Subscription Service - Stock Lot Asset"
+msgstr ""
diff --git a/modules/sale_subscription_asset/locale/fr.po b/modules/sale_subscription_asset/locale/fr.po
new file mode 100644
index 0000000000..a4e353f2da
--- /dev/null
+++ b/modules/sale_subscription_asset/locale/fr.po
@@ -0,0 +1,51 @@
+#
+msgid ""
+msgstr "Content-Type: text/plain; charset=utf-8\n"
+
+msgctxt "field:sale.subscription.line,asset_lot:"
+msgid "Asset Lot"
+msgstr "Lot d'actif"
+
+msgctxt "field:sale.subscription.line,asset_lot_required:"
+msgid "Asset Lot Required"
+msgstr "Lot d'actif requis"
+
+msgctxt "field:sale.subscription.service,asset_lots:"
+msgid "Asset Lots"
+msgstr "Lots d'actif"
+
+msgctxt "field:sale.subscription.service,asset_lots_available:"
+msgid "Available Asset Lots"
+msgstr "Lot d'actif disponible"
+
+msgctxt "field:sale.subscription.service-stock.lot.asset,lot:"
+msgid "Lot"
+msgstr "Lot"
+
+msgctxt "field:sale.subscription.service-stock.lot.asset,service:"
+msgid "Service"
+msgstr "Service"
+
+msgctxt "field:stock.lot,subscribed:"
+msgid "Subscribed"
+msgstr "Abonné"
+
+msgctxt "field:stock.lot,subscription_lines:"
+msgid "Subscription Lines"
+msgstr "Lignes d'abonnement"
+
+msgctxt "field:stock.lot,subscription_services:"
+msgid "Services"
+msgstr "Services"
+
+msgctxt "model:ir.message,text:msg_asset_line_overlap"
+msgid ""
+"The lines \"%(line1)s\" and \"%(line2)s\" overlap, you must use different "
+"dates."
+msgstr ""
+"Les lignes « %(line1)s » et « %(line2)s » se chevauchent, vous devez "
+"utiliser des dates différentes."
+
+msgctxt "model:sale.subscription.service-stock.lot.asset,name:"
+msgid "Subscription Service - Stock Lot Asset"
+msgstr "Service d'abonnement - Lot d'actif"
diff --git a/modules/sale_subscription_asset/locale/hu.po b/modules/sale_subscription_asset/locale/hu.po
new file mode 100644
index 0000000000..27d8d0d55f
--- /dev/null
+++ b/modules/sale_subscription_asset/locale/hu.po
@@ -0,0 +1,49 @@
+#
+msgid ""
+msgstr "Content-Type: text/plain; charset=utf-8\n"
+
+msgctxt "field:sale.subscription.line,asset_lot:"
+msgid "Asset Lot"
+msgstr ""
+
+msgctxt "field:sale.subscription.line,asset_lot_required:"
+msgid "Asset Lot Required"
+msgstr ""
+
+msgctxt "field:sale.subscription.service,asset_lots:"
+msgid "Asset Lots"
+msgstr ""
+
+msgctxt "field:sale.subscription.service,asset_lots_available:"
+msgid "Available Asset Lots"
+msgstr ""
+
+msgctxt "field:sale.subscription.service-stock.lot.asset,lot:"
+msgid "Lot"
+msgstr ""
+
+msgctxt "field:sale.subscription.service-stock.lot.asset,service:"
+msgid "Service"
+msgstr ""
+
+msgctxt "field:stock.lot,subscribed:"
+msgid "Subscribed"
+msgstr ""
+
+msgctxt "field:stock.lot,subscription_lines:"
+msgid "Subscription Lines"
+msgstr ""
+
+msgctxt "field:stock.lot,subscription_services:"
+msgid "Services"
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_asset_line_overlap"
+msgid ""
+"The lines \"%(line1)s\" and \"%(line2)s\" overlap, you must use different "
+"dates."
+msgstr ""
+
+msgctxt "model:sale.subscription.service-stock.lot.asset,name:"
+msgid "Subscription Service - Stock Lot Asset"
+msgstr ""
diff --git a/modules/sale_subscription_asset/locale/id.po b/modules/sale_subscription_asset/locale/id.po
new file mode 100644
index 0000000000..e99e13c1f0
--- /dev/null
+++ b/modules/sale_subscription_asset/locale/id.po
@@ -0,0 +1,49 @@
+#
+msgid ""
+msgstr "Content-Type: text/plain; charset=utf-8\n"
+
+msgctxt "field:sale.subscription.line,asset_lot:"
+msgid "Asset Lot"
+msgstr ""
+
+msgctxt "field:sale.subscription.line,asset_lot_required:"
+msgid "Asset Lot Required"
+msgstr ""
+
+msgctxt "field:sale.subscription.service,asset_lots:"
+msgid "Asset Lots"
+msgstr ""
+
+msgctxt "field:sale.subscription.service,asset_lots_available:"
+msgid "Available Asset Lots"
+msgstr ""
+
+msgctxt "field:sale.subscription.service-stock.lot.asset,lot:"
+msgid "Lot"
+msgstr ""
+
+msgctxt "field:sale.subscription.service-stock.lot.asset,service:"
+msgid "Service"
+msgstr "Jasa"
+
+msgctxt "field:stock.lot,subscribed:"
+msgid "Subscribed"
+msgstr ""
+
+msgctxt "field:stock.lot,subscription_lines:"
+msgid "Subscription Lines"
+msgstr ""
+
+msgctxt "field:stock.lot,subscription_services:"
+msgid "Services"
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_asset_line_overlap"
+msgid ""
+"The lines \"%(line1)s\" and \"%(line2)s\" overlap, you must use different "
+"dates."
+msgstr ""
+
+msgctxt "model:sale.subscription.service-stock.lot.asset,name:"
+msgid "Subscription Service - Stock Lot Asset"
+msgstr ""
diff --git a/modules/sale_subscription_asset/locale/it.po b/modules/sale_subscription_asset/locale/it.po
new file mode 100644
index 0000000000..cbf3928679
--- /dev/null
+++ b/modules/sale_subscription_asset/locale/it.po
@@ -0,0 +1,51 @@
+#
+msgid ""
+msgstr "Content-Type: text/plain; charset=utf-8\n"
+
+msgctxt "field:sale.subscription.line,asset_lot:"
+msgid "Asset Lot"
+msgstr "Lotto cespiti"
+
+msgctxt "field:sale.subscription.line,asset_lot_required:"
+msgid "Asset Lot Required"
+msgstr "Lotto cespiti richiesto"
+
+msgctxt "field:sale.subscription.service,asset_lots:"
+msgid "Asset Lots"
+msgstr "Lotti di cespito"
+
+msgctxt "field:sale.subscription.service,asset_lots_available:"
+msgid "Available Asset Lots"
+msgstr "Lotti di cespiti disponibili"
+
+msgctxt "field:sale.subscription.service-stock.lot.asset,lot:"
+msgid "Lot"
+msgstr "Lotto"
+
+msgctxt "field:sale.subscription.service-stock.lot.asset,service:"
+msgid "Service"
+msgstr "Servizio"
+
+msgctxt "field:stock.lot,subscribed:"
+msgid "Subscribed"
+msgstr "Abbonato"
+
+msgctxt "field:stock.lot,subscription_lines:"
+msgid "Subscription Lines"
+msgstr "Righe di abbonamento"
+
+msgctxt "field:stock.lot,subscription_services:"
+msgid "Services"
+msgstr "Servizi"
+
+msgctxt "model:ir.message,text:msg_asset_line_overlap"
+msgid ""
+"The lines \"%(line1)s\" and \"%(line2)s\" overlap, you must use different "
+"dates."
+msgstr ""
+"Le linee \"%(line1)s\" e \"%(line2)s\" si sovrappongono, è necessario "
+"utilizzare date diverse."
+
+msgctxt "model:sale.subscription.service-stock.lot.asset,name:"
+msgid "Subscription Service - Stock Lot Asset"
+msgstr "Servizio in abbonamento - Stock lotto cespiti"
diff --git a/modules/sale_subscription_asset/locale/lo.po b/modules/sale_subscription_asset/locale/lo.po
new file mode 100644
index 0000000000..27d8d0d55f
--- /dev/null
+++ b/modules/sale_subscription_asset/locale/lo.po
@@ -0,0 +1,49 @@
+#
+msgid ""
+msgstr "Content-Type: text/plain; charset=utf-8\n"
+
+msgctxt "field:sale.subscription.line,asset_lot:"
+msgid "Asset Lot"
+msgstr ""
+
+msgctxt "field:sale.subscription.line,asset_lot_required:"
+msgid "Asset Lot Required"
+msgstr ""
+
+msgctxt "field:sale.subscription.service,asset_lots:"
+msgid "Asset Lots"
+msgstr ""
+
+msgctxt "field:sale.subscription.service,asset_lots_available:"
+msgid "Available Asset Lots"
+msgstr ""
+
+msgctxt "field:sale.subscription.service-stock.lot.asset,lot:"
+msgid "Lot"
+msgstr ""
+
+msgctxt "field:sale.subscription.service-stock.lot.asset,service:"
+msgid "Service"
+msgstr ""
+
+msgctxt "field:stock.lot,subscribed:"
+msgid "Subscribed"
+msgstr ""
+
+msgctxt "field:stock.lot,subscription_lines:"
+msgid "Subscription Lines"
+msgstr ""
+
+msgctxt "field:stock.lot,subscription_services:"
+msgid "Services"
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_asset_line_overlap"
+msgid ""
+"The lines \"%(line1)s\" and \"%(line2)s\" overlap, you must use different "
+"dates."
+msgstr ""
+
+msgctxt "model:sale.subscription.service-stock.lot.asset,name:"
+msgid "Subscription Service - Stock Lot Asset"
+msgstr ""
diff --git a/modules/sale_subscription_asset/locale/lt.po b/modules/sale_subscription_asset/locale/lt.po
new file mode 100644
index 0000000000..27d8d0d55f
--- /dev/null
+++ b/modules/sale_subscription_asset/locale/lt.po
@@ -0,0 +1,49 @@
+#
+msgid ""
+msgstr "Content-Type: text/plain; charset=utf-8\n"
+
+msgctxt "field:sale.subscription.line,asset_lot:"
+msgid "Asset Lot"
+msgstr ""
+
+msgctxt "field:sale.subscription.line,asset_lot_required:"
+msgid "Asset Lot Required"
+msgstr ""
+
+msgctxt "field:sale.subscription.service,asset_lots:"
+msgid "Asset Lots"
+msgstr ""
+
+msgctxt "field:sale.subscription.service,asset_lots_available:"
+msgid "Available Asset Lots"
+msgstr ""
+
+msgctxt "field:sale.subscription.service-stock.lot.asset,lot:"
+msgid "Lot"
+msgstr ""
+
+msgctxt "field:sale.subscription.service-stock.lot.asset,service:"
+msgid "Service"
+msgstr ""
+
+msgctxt "field:stock.lot,subscribed:"
+msgid "Subscribed"
+msgstr ""
+
+msgctxt "field:stock.lot,subscription_lines:"
+msgid "Subscription Lines"
+msgstr ""
+
+msgctxt "field:stock.lot,subscription_services:"
+msgid "Services"
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_asset_line_overlap"
+msgid ""
+"The lines \"%(line1)s\" and \"%(line2)s\" overlap, you must use different "
+"dates."
+msgstr ""
+
+msgctxt "model:sale.subscription.service-stock.lot.asset,name:"
+msgid "Subscription Service - Stock Lot Asset"
+msgstr ""
diff --git a/modules/sale_subscription_asset/locale/nl.po b/modules/sale_subscription_asset/locale/nl.po
new file mode 100644
index 0000000000..c422cb9580
--- /dev/null
+++ b/modules/sale_subscription_asset/locale/nl.po
@@ -0,0 +1,51 @@
+#
+msgid ""
+msgstr "Content-Type: text/plain; charset=utf-8\n"
+
+msgctxt "field:sale.subscription.line,asset_lot:"
+msgid "Asset Lot"
+msgstr "Activa lot"
+
+msgctxt "field:sale.subscription.line,asset_lot_required:"
+msgid "Asset Lot Required"
+msgstr "Activa lot vereist"
+
+msgctxt "field:sale.subscription.service,asset_lots:"
+msgid "Asset Lots"
+msgstr "Activa loten"
+
+msgctxt "field:sale.subscription.service,asset_lots_available:"
+msgid "Available Asset Lots"
+msgstr "Beschikbare activa loten"
+
+msgctxt "field:sale.subscription.service-stock.lot.asset,lot:"
+msgid "Lot"
+msgstr "Lot"
+
+msgctxt "field:sale.subscription.service-stock.lot.asset,service:"
+msgid "Service"
+msgstr "Dienst"
+
+msgctxt "field:stock.lot,subscribed:"
+msgid "Subscribed"
+msgstr "geabonneerd"
+
+msgctxt "field:stock.lot,subscription_lines:"
+msgid "Subscription Lines"
+msgstr "Abonnementsregel"
+
+msgctxt "field:stock.lot,subscription_services:"
+msgid "Services"
+msgstr "Diensten"
+
+msgctxt "model:ir.message,text:msg_asset_line_overlap"
+msgid ""
+"The lines \"%(line1)s\" and \"%(line2)s\" overlap, you must use different "
+"dates."
+msgstr ""
+"De regels \"%(line1)s\" en \"%(line2)s\" overlappen elkaar, u moet "
+"verschillende datums gebruiken."
+
+msgctxt "model:sale.subscription.service-stock.lot.asset,name:"
+msgid "Subscription Service - Stock Lot Asset"
+msgstr "Abonnementsdienst - Voorraadpartijactiva"
diff --git a/modules/sale_subscription_asset/locale/pl.po b/modules/sale_subscription_asset/locale/pl.po
new file mode 100644
index 0000000000..27d8d0d55f
--- /dev/null
+++ b/modules/sale_subscription_asset/locale/pl.po
@@ -0,0 +1,49 @@
+#
+msgid ""
+msgstr "Content-Type: text/plain; charset=utf-8\n"
+
+msgctxt "field:sale.subscription.line,asset_lot:"
+msgid "Asset Lot"
+msgstr ""
+
+msgctxt "field:sale.subscription.line,asset_lot_required:"
+msgid "Asset Lot Required"
+msgstr ""
+
+msgctxt "field:sale.subscription.service,asset_lots:"
+msgid "Asset Lots"
+msgstr ""
+
+msgctxt "field:sale.subscription.service,asset_lots_available:"
+msgid "Available Asset Lots"
+msgstr ""
+
+msgctxt "field:sale.subscription.service-stock.lot.asset,lot:"
+msgid "Lot"
+msgstr ""
+
+msgctxt "field:sale.subscription.service-stock.lot.asset,service:"
+msgid "Service"
+msgstr ""
+
+msgctxt "field:stock.lot,subscribed:"
+msgid "Subscribed"
+msgstr ""
+
+msgctxt "field:stock.lot,subscription_lines:"
+msgid "Subscription Lines"
+msgstr ""
+
+msgctxt "field:stock.lot,subscription_services:"
+msgid "Services"
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_asset_line_overlap"
+msgid ""
+"The lines \"%(line1)s\" and \"%(line2)s\" overlap, you must use different "
+"dates."
+msgstr ""
+
+msgctxt "model:sale.subscription.service-stock.lot.asset,name:"
+msgid "Subscription Service - Stock Lot Asset"
+msgstr ""
diff --git a/modules/sale_subscription_asset/locale/pt.po b/modules/sale_subscription_asset/locale/pt.po
new file mode 100644
index 0000000000..27d8d0d55f
--- /dev/null
+++ b/modules/sale_subscription_asset/locale/pt.po
@@ -0,0 +1,49 @@
+#
+msgid ""
+msgstr "Content-Type: text/plain; charset=utf-8\n"
+
+msgctxt "field:sale.subscription.line,asset_lot:"
+msgid "Asset Lot"
+msgstr ""
+
+msgctxt "field:sale.subscription.line,asset_lot_required:"
+msgid "Asset Lot Required"
+msgstr ""
+
+msgctxt "field:sale.subscription.service,asset_lots:"
+msgid "Asset Lots"
+msgstr ""
+
+msgctxt "field:sale.subscription.service,asset_lots_available:"
+msgid "Available Asset Lots"
+msgstr ""
+
+msgctxt "field:sale.subscription.service-stock.lot.asset,lot:"
+msgid "Lot"
+msgstr ""
+
+msgctxt "field:sale.subscription.service-stock.lot.asset,service:"
+msgid "Service"
+msgstr ""
+
+msgctxt "field:stock.lot,subscribed:"
+msgid "Subscribed"
+msgstr ""
+
+msgctxt "field:stock.lot,subscription_lines:"
+msgid "Subscription Lines"
+msgstr ""
+
+msgctxt "field:stock.lot,subscription_services:"
+msgid "Services"
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_asset_line_overlap"
+msgid ""
+"The lines \"%(line1)s\" and \"%(line2)s\" overlap, you must use different "
+"dates."
+msgstr ""
+
+msgctxt "model:sale.subscription.service-stock.lot.asset,name:"
+msgid "Subscription Service - Stock Lot Asset"
+msgstr ""
diff --git a/modules/sale_subscription_asset/locale/ro.po b/modules/sale_subscription_asset/locale/ro.po
new file mode 100644
index 0000000000..27d8d0d55f
--- /dev/null
+++ b/modules/sale_subscription_asset/locale/ro.po
@@ -0,0 +1,49 @@
+#
+msgid ""
+msgstr "Content-Type: text/plain; charset=utf-8\n"
+
+msgctxt "field:sale.subscription.line,asset_lot:"
+msgid "Asset Lot"
+msgstr ""
+
+msgctxt "field:sale.subscription.line,asset_lot_required:"
+msgid "Asset Lot Required"
+msgstr ""
+
+msgctxt "field:sale.subscription.service,asset_lots:"
+msgid "Asset Lots"
+msgstr ""
+
+msgctxt "field:sale.subscription.service,asset_lots_available:"
+msgid "Available Asset Lots"
+msgstr ""
+
+msgctxt "field:sale.subscription.service-stock.lot.asset,lot:"
+msgid "Lot"
+msgstr ""
+
+msgctxt "field:sale.subscription.service-stock.lot.asset,service:"
+msgid "Service"
+msgstr ""
+
+msgctxt "field:stock.lot,subscribed:"
+msgid "Subscribed"
+msgstr ""
+
+msgctxt "field:stock.lot,subscription_lines:"
+msgid "Subscription Lines"
+msgstr ""
+
+msgctxt "field:stock.lot,subscription_services:"
+msgid "Services"
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_asset_line_overlap"
+msgid ""
+"The lines \"%(line1)s\" and \"%(line2)s\" overlap, you must use different "
+"dates."
+msgstr ""
+
+msgctxt "model:sale.subscription.service-stock.lot.asset,name:"
+msgid "Subscription Service - Stock Lot Asset"
+msgstr ""
diff --git a/modules/sale_subscription_asset/locale/ru.po b/modules/sale_subscription_asset/locale/ru.po
new file mode 100644
index 0000000000..27d8d0d55f
--- /dev/null
+++ b/modules/sale_subscription_asset/locale/ru.po
@@ -0,0 +1,49 @@
+#
+msgid ""
+msgstr "Content-Type: text/plain; charset=utf-8\n"
+
+msgctxt "field:sale.subscription.line,asset_lot:"
+msgid "Asset Lot"
+msgstr ""
+
+msgctxt "field:sale.subscription.line,asset_lot_required:"
+msgid "Asset Lot Required"
+msgstr ""
+
+msgctxt "field:sale.subscription.service,asset_lots:"
+msgid "Asset Lots"
+msgstr ""
+
+msgctxt "field:sale.subscription.service,asset_lots_available:"
+msgid "Available Asset Lots"
+msgstr ""
+
+msgctxt "field:sale.subscription.service-stock.lot.asset,lot:"
+msgid "Lot"
+msgstr ""
+
+msgctxt "field:sale.subscription.service-stock.lot.asset,service:"
+msgid "Service"
+msgstr ""
+
+msgctxt "field:stock.lot,subscribed:"
+msgid "Subscribed"
+msgstr ""
+
+msgctxt "field:stock.lot,subscription_lines:"
+msgid "Subscription Lines"
+msgstr ""
+
+msgctxt "field:stock.lot,subscription_services:"
+msgid "Services"
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_asset_line_overlap"
+msgid ""
+"The lines \"%(line1)s\" and \"%(line2)s\" overlap, you must use different "
+"dates."
+msgstr ""
+
+msgctxt "model:sale.subscription.service-stock.lot.asset,name:"
+msgid "Subscription Service - Stock Lot Asset"
+msgstr ""
diff --git a/modules/sale_subscription_asset/locale/sl.po b/modules/sale_subscription_asset/locale/sl.po
new file mode 100644
index 0000000000..27d8d0d55f
--- /dev/null
+++ b/modules/sale_subscription_asset/locale/sl.po
@@ -0,0 +1,49 @@
+#
+msgid ""
+msgstr "Content-Type: text/plain; charset=utf-8\n"
+
+msgctxt "field:sale.subscription.line,asset_lot:"
+msgid "Asset Lot"
+msgstr ""
+
+msgctxt "field:sale.subscription.line,asset_lot_required:"
+msgid "Asset Lot Required"
+msgstr ""
+
+msgctxt "field:sale.subscription.service,asset_lots:"
+msgid "Asset Lots"
+msgstr ""
+
+msgctxt "field:sale.subscription.service,asset_lots_available:"
+msgid "Available Asset Lots"
+msgstr ""
+
+msgctxt "field:sale.subscription.service-stock.lot.asset,lot:"
+msgid "Lot"
+msgstr ""
+
+msgctxt "field:sale.subscription.service-stock.lot.asset,service:"
+msgid "Service"
+msgstr ""
+
+msgctxt "field:stock.lot,subscribed:"
+msgid "Subscribed"
+msgstr ""
+
+msgctxt "field:stock.lot,subscription_lines:"
+msgid "Subscription Lines"
+msgstr ""
+
+msgctxt "field:stock.lot,subscription_services:"
+msgid "Services"
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_asset_line_overlap"
+msgid ""
+"The lines \"%(line1)s\" and \"%(line2)s\" overlap, you must use different "
+"dates."
+msgstr ""
+
+msgctxt "model:sale.subscription.service-stock.lot.asset,name:"
+msgid "Subscription Service - Stock Lot Asset"
+msgstr ""
diff --git a/modules/sale_subscription_asset/locale/tr.po b/modules/sale_subscription_asset/locale/tr.po
new file mode 100644
index 0000000000..27d8d0d55f
--- /dev/null
+++ b/modules/sale_subscription_asset/locale/tr.po
@@ -0,0 +1,49 @@
+#
+msgid ""
+msgstr "Content-Type: text/plain; charset=utf-8\n"
+
+msgctxt "field:sale.subscription.line,asset_lot:"
+msgid "Asset Lot"
+msgstr ""
+
+msgctxt "field:sale.subscription.line,asset_lot_required:"
+msgid "Asset Lot Required"
+msgstr ""
+
+msgctxt "field:sale.subscription.service,asset_lots:"
+msgid "Asset Lots"
+msgstr ""
+
+msgctxt "field:sale.subscription.service,asset_lots_available:"
+msgid "Available Asset Lots"
+msgstr ""
+
+msgctxt "field:sale.subscription.service-stock.lot.asset,lot:"
+msgid "Lot"
+msgstr ""
+
+msgctxt "field:sale.subscription.service-stock.lot.asset,service:"
+msgid "Service"
+msgstr ""
+
+msgctxt "field:stock.lot,subscribed:"
+msgid "Subscribed"
+msgstr ""
+
+msgctxt "field:stock.lot,subscription_lines:"
+msgid "Subscription Lines"
+msgstr ""
+
+msgctxt "field:stock.lot,subscription_services:"
+msgid "Services"
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_asset_line_overlap"
+msgid ""
+"The lines \"%(line1)s\" and \"%(line2)s\" overlap, you must use different "
+"dates."
+msgstr ""
+
+msgctxt "model:sale.subscription.service-stock.lot.asset,name:"
+msgid "Subscription Service - Stock Lot Asset"
+msgstr ""
diff --git a/modules/sale_subscription_asset/locale/zh_CN.po b/modules/sale_subscription_asset/locale/zh_CN.po
new file mode 100644
index 0000000000..27d8d0d55f
--- /dev/null
+++ b/modules/sale_subscription_asset/locale/zh_CN.po
@@ -0,0 +1,49 @@
+#
+msgid ""
+msgstr "Content-Type: text/plain; charset=utf-8\n"
+
+msgctxt "field:sale.subscription.line,asset_lot:"
+msgid "Asset Lot"
+msgstr ""
+
+msgctxt "field:sale.subscription.line,asset_lot_required:"
+msgid "Asset Lot Required"
+msgstr ""
+
+msgctxt "field:sale.subscription.service,asset_lots:"
+msgid "Asset Lots"
+msgstr ""
+
+msgctxt "field:sale.subscription.service,asset_lots_available:"
+msgid "Available Asset Lots"
+msgstr ""
+
+msgctxt "field:sale.subscription.service-stock.lot.asset,lot:"
+msgid "Lot"
+msgstr ""
+
+msgctxt "field:sale.subscription.service-stock.lot.asset,service:"
+msgid "Service"
+msgstr ""
+
+msgctxt "field:stock.lot,subscribed:"
+msgid "Subscribed"
+msgstr ""
+
+msgctxt "field:stock.lot,subscription_lines:"
+msgid "Subscription Lines"
+msgstr ""
+
+msgctxt "field:stock.lot,subscription_services:"
+msgid "Services"
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_asset_line_overlap"
+msgid ""
+"The lines \"%(line1)s\" and \"%(line2)s\" overlap, you must use different "
+"dates."
+msgstr ""
+
+msgctxt "model:sale.subscription.service-stock.lot.asset,name:"
+msgid "Subscription Service - Stock Lot Asset"
+msgstr ""
diff --git a/modules/sale_subscription_asset/message.xml b/modules/sale_subscription_asset/message.xml
new file mode 100644
index 0000000000..e63b6a8c49
--- /dev/null
+++ b/modules/sale_subscription_asset/message.xml
@@ -0,0 +1,10 @@
+
+
+
+
+
+ The lines "%(line1)s" and "%(line2)s" overlap, you must use different dates.
+
+
+
diff --git a/modules/sale_subscription_asset/sale.py b/modules/sale_subscription_asset/sale.py
new file mode 100644
index 0000000000..64d18bee84
--- /dev/null
+++ b/modules/sale_subscription_asset/sale.py
@@ -0,0 +1,165 @@
+# This file is part of Tryton. The COPYRIGHT file at the top level of
+# this repository contains the full copyright notices and license terms.
+from sql import Null
+
+from trytond.i18n import gettext
+from trytond.model import fields, ModelSQL, ModelView, Workflow
+from trytond.model.exceptions import ValidationError
+from trytond.pool import PoolMeta, Pool
+from trytond.pyson import Eval, If, Bool
+from trytond.tools import grouped_slice, reduce_ids
+from trytond.transaction import Transaction
+
+
+class SubscriptionService(metaclass=PoolMeta):
+ __name__ = 'sale.subscription.service'
+
+ asset_lots = fields.Many2Many(
+ 'sale.subscription.service-stock.lot.asset',
+ 'service', 'lot', "Asset Lots",
+ domain=[
+ ('product.type', '=', 'assets'),
+ ])
+ asset_lots_available = fields.Many2Many(
+ 'sale.subscription.service-stock.lot.asset',
+ 'service', 'lot', "Available Asset Lots", readonly=True,
+ domain=[
+ ('product.type', '=', 'assets'),
+ ],
+ filter=[
+ ('subscribed', '=', None),
+ ])
+
+
+class SubscriptionServiceStockLot(ModelSQL):
+ "Subscription Service - Stock Lot Asset"
+ __name__ = 'sale.subscription.service-stock.lot.asset'
+
+ service = fields.Many2One(
+ 'sale.subscription.service', "Service",
+ ondelete='CASCADE', select=True, required=True)
+ lot = fields.Many2One(
+ 'stock.lot', "Lot", ondelete='CASCADE', select=True, required=True,
+ domain=[
+ ('product.type', '=', 'assets'),
+ ])
+
+
+class Subscription(metaclass=PoolMeta):
+ __name__ = 'sale.subscription'
+
+ @classmethod
+ @ModelView.button
+ @Workflow.transition('cancelled')
+ def cancel(cls, subscriptions):
+ pool = Pool()
+ SubscriptionLine = pool.get('sale.subscription.line')
+
+ sub_lines = [l for s in subscriptions for l in s.lines if l.asset_lot]
+ SubscriptionLine.write(sub_lines, {'asset_lot': None})
+
+ super(Subscription, cls).cancel(subscriptions)
+
+ @classmethod
+ @ModelView.button
+ @Workflow.transition('running')
+ def run(cls, subscriptions):
+ pool = Pool()
+ Line = pool.get('sale.subscription.line')
+ super(Subscription, cls).run(subscriptions)
+ lines = [l for s in subscriptions for l in s.lines]
+ Line._validate(lines, ['asset_lot'])
+
+
+class SubscriptionLine(metaclass=PoolMeta):
+ __name__ = 'sale.subscription.line'
+
+ asset_lot = fields.Many2One('stock.lot', "Asset Lot",
+ domain=[
+ ('subscription_services', '=', Eval('service')),
+ ],
+ states={
+ 'required': ((Eval('subscription_state') == 'running')
+ & Eval('asset_lot_required')),
+ 'invisible': ~Eval('asset_lot_required'),
+ 'readonly': Eval('subscription_state') != 'draft',
+ },
+ depends=['service', 'subscription_state', 'asset_lot_required'])
+ asset_lot_required = fields.Function(
+ fields.Boolean("Asset Lot Required"),
+ 'on_change_with_asset_lot_required')
+
+ @classmethod
+ def __setup__(cls):
+ super(SubscriptionLine, cls).__setup__()
+
+ cls.quantity.domain = [
+ cls.quantity.domain,
+ If(Bool(Eval('asset_lot')),
+ ('quantity', '=', 1),
+ ()),
+ ]
+ cls.quantity.depends.append('asset_lot')
+
+ @fields.depends('service')
+ def on_change_with_asset_lot_required(self, name=None):
+ if not self.service:
+ return False
+ return bool(self.service.asset_lots)
+
+ @classmethod
+ def copy(cls, lines, default=None):
+ if default is None:
+ default = {}
+ else:
+ default = default.copy()
+ default.setdefault('lot')
+ return super(SubscriptionLine, cls).copy(lines, default)
+
+ @classmethod
+ def validate(cls, lines):
+ super(SubscriptionLine, cls).validate(lines)
+ cls._validate_dates(lines)
+
+ @classmethod
+ def _validate_dates(cls, lines):
+ transaction = Transaction()
+ connection = transaction.connection
+ cursor = connection.cursor()
+
+ transaction.database.lock(connection, cls._table)
+
+ line = cls.__table__()
+ other = cls.__table__()
+ overlap_where = (
+ ((line.end_date == Null)
+ & ((other.end_date == Null)
+ | (other.start_date > line.start_date)
+ | (other.end_date > line.start_date)))
+ | ((line.end_date != Null)
+ & ((
+ (other.end_date == Null)
+ & (other.start_date < line.end_date))
+ | ((other.end_date != Null)
+ & ((
+ (other.end_date >= line.start_date)
+ & (other.end_date < line.end_date))
+ | ((other.start_date >= line.start_date)
+ & (other.start_date < line.end_date)))))))
+ for sub_lines in grouped_slice(lines):
+ sub_ids = [l.id for l in sub_lines]
+ cursor.execute(*line.join(other,
+ condition=((line.id != other.id)
+ & (line.asset_lot == other.asset_lot))
+ ).select(line.id, other.id,
+ where=((line.asset_lot != Null)
+ & reduce_ids(line.id, sub_ids)
+ & overlap_where),
+ limit=1))
+ overlapping = cursor.fetchone()
+ if overlapping:
+ sline1, sline2 = cls.browse(overlapping)
+ raise ValidationError(
+ gettext('sale_subscription_asset.msg_asset_line_overlap',
+ line1=sline1.rec_name,
+ line2=sline2.rec_name))
diff --git a/modules/sale_subscription_asset/sale.xml b/modules/sale_subscription_asset/sale.xml
new file mode 100644
index 0000000000..6c58e69191
--- /dev/null
+++ b/modules/sale_subscription_asset/sale.xml
@@ -0,0 +1,23 @@
+
+
+
+
+
+ sale.subscription.service
+
+ subscription_service_form
+
+
+
+ sale.subscription.line
+
+ subscription_line_form
+
+
+ sale.subscription.line
+
+ subscription_line_list
+
+
+
diff --git a/modules/sale_subscription_asset/setup.py b/modules/sale_subscription_asset/setup.py
new file mode 100755
index 0000000000..c14fc14ffc
--- /dev/null
+++ b/modules/sale_subscription_asset/setup.py
@@ -0,0 +1,150 @@
+#!/usr/bin/env python3
+# This file is part of Tryton. The COPYRIGHT file at the top level of
+# this repository contains the full copyright notices and license terms.
+
+import io
+import os
+import re
+from configparser import ConfigParser
+from setuptools import setup, find_packages
+
+
+def read(fname):
+ return io.open(
+ os.path.join(os.path.dirname(__file__), fname),
+ 'r', encoding='utf-8').read()
+
+
+def get_require_version(name):
+ if minor_version % 2:
+ require = '%s >= %s.%s.dev0, < %s.%s'
+ else:
+ require = '%s >= %s.%s, < %s.%s'
+ require %= (name, major_version, minor_version,
+ major_version, minor_version + 1)
+ return require
+
+
+config = ConfigParser()
+config.read_file(open(os.path.join(os.path.dirname(__file__), 'tryton.cfg')))
+info = dict(config.items('tryton'))
+for key in ('depends', 'extras_depend', 'xml'):
+ if key in info:
+ info[key] = info[key].strip().splitlines()
+version = info.get('version', '0.0.1')
+major_version, minor_version, _ = version.split('.', 2)
+major_version = int(major_version)
+minor_version = int(minor_version)
+name = 'trytond_sale_subscription_asset'
+
+download_url = 'http://downloads.tryton.org/%s.%s/' % (
+ major_version, minor_version)
+if minor_version % 2:
+ version = '%s.%s.dev0' % (major_version, minor_version)
+ download_url = (
+ 'hg+http://hg.tryton.org/modules/%s#egg=%s-%s' % (
+ name[8:], name, version))
+local_version = []
+if os.environ.get('CI_JOB_ID'):
+ local_version.append(os.environ['CI_JOB_ID'])
+else:
+ for build in ['CI_BUILD_NUMBER', 'CI_JOB_NUMBER']:
+ if os.environ.get(build):
+ local_version.append(os.environ[build])
+ else:
+ local_version = []
+ break
+if local_version:
+ version += '+' + '.'.join(local_version)
+
+requires = []
+for dep in info.get('depends', []):
+ if not re.match(r'(ir|res)(\W|$)', dep):
+ requires.append(get_require_version('trytond_%s' % dep))
+requires.append(get_require_version('trytond'))
+
+tests_require = [get_require_version('proteus')]
+dependency_links = []
+if minor_version % 2:
+ dependency_links.append(
+ 'https://trydevpi.tryton.org/?local_version='
+ + '.'.join(local_version))
+
+setup(name=name,
+ version=version,
+ description='A module to handle asset in the sale subscriptions',
+ long_description=read('README.rst'),
+ author='Tryton',
+ author_email='bugs@tryton.org',
+ url='http://www.tryton.org/',
+ download_url=download_url,
+ project_urls={
+ "Bug Tracker": 'https://bugs.tryton.org/',
+ "Documentation": 'https://docs.tryton.org/',
+ "Forum": 'https://www.tryton.org/forum',
+ "Source Code": 'https://hg.tryton.org/modules/sale_subscription_asset',
+ },
+ keywords='',
+ package_dir={'trytond.modules.sale_subscription_asset': '.'},
+ packages=(
+ ['trytond.modules.sale_subscription_asset']
+ + ['trytond.modules.sale_subscription_asset.%s' % p
+ for p in find_packages()]
+ ),
+ package_data={
+ 'trytond.modules.sale_subscription_asset': (info.get('xml', [])
+ + ['tryton.cfg', 'view/*.xml', 'locale/*.po', '*.fodt',
+ 'icons/*.svg', 'tests/*.rst']),
+ },
+ classifiers=[
+ 'Development Status :: 5 - Production/Stable',
+ 'Environment :: Plugins',
+ 'Framework :: Tryton',
+ 'Intended Audience :: Developers',
+ 'Intended Audience :: Financial and Insurance Industry',
+ 'Intended Audience :: Legal Industry',
+ 'License :: OSI Approved :: '
+ 'GNU General Public License v3 or later (GPLv3+)',
+ 'Natural Language :: Bulgarian',
+ 'Natural Language :: Catalan',
+ 'Natural Language :: Chinese (Simplified)',
+ 'Natural Language :: Czech',
+ 'Natural Language :: Dutch',
+ 'Natural Language :: English',
+ 'Natural Language :: Finnish',
+ 'Natural Language :: French',
+ 'Natural Language :: German',
+ 'Natural Language :: Hungarian',
+ 'Natural Language :: Indonesian',
+ 'Natural Language :: Italian',
+ 'Natural Language :: Persian',
+ 'Natural Language :: Polish',
+ 'Natural Language :: Portuguese (Brazilian)',
+ 'Natural Language :: Romanian',
+ 'Natural Language :: Russian',
+ 'Natural Language :: Slovenian',
+ 'Natural Language :: Spanish',
+ 'Natural Language :: Turkish',
+ 'Operating System :: OS Independent',
+ 'Programming Language :: Python :: 3',
+ 'Programming Language :: Python :: 3.6',
+ 'Programming Language :: Python :: 3.7',
+ 'Programming Language :: Python :: 3.8',
+ 'Programming Language :: Python :: 3.9',
+ 'Programming Language :: Python :: Implementation :: CPython',
+ 'Programming Language :: Python :: Implementation :: PyPy',
+ 'Topic :: Office/Business',
+ ],
+ license='GPL-3',
+ python_requires='>=3.6',
+ install_requires=requires,
+ dependency_links=dependency_links,
+ zip_safe=False,
+ entry_points="""
+ [trytond.modules]
+ sale_subscription_asset = trytond.modules.sale_subscription_asset
+ """,
+ test_suite='tests',
+ test_loader='trytond.test_loader:Loader',
+ tests_require=tests_require,
+ )
diff --git a/modules/sale_subscription_asset/stock.py b/modules/sale_subscription_asset/stock.py
new file mode 100644
index 0000000000..b9405f0c13
--- /dev/null
+++ b/modules/sale_subscription_asset/stock.py
@@ -0,0 +1,73 @@
+# This file is part of Tryton. The COPYRIGHT file at the top level of
+# this repository contains the full copyright notices and license terms.
+from trytond.model import fields
+from trytond.pool import Pool, PoolMeta
+from trytond.tools import grouped_slice
+from trytond.transaction import Transaction
+
+
+class Lot(metaclass=PoolMeta):
+ __name__ = 'stock.lot'
+
+ subscription_services = fields.Many2Many(
+ 'sale.subscription.service-stock.lot.asset',
+ 'lot', 'service', "Services")
+ subscription_lines = fields.One2Many(
+ 'sale.subscription.line', 'asset_lot', "Subscription Lines")
+ subscribed = fields.Function(
+ fields.Many2One('sale.subscription.line', "Subscribed"),
+ 'get_subscribed', searcher='search_subscribed')
+
+ @classmethod
+ def get_subscribed(cls, lots, name):
+ pool = Pool()
+ Date = pool.get('ir.date')
+ SubscriptionLine = pool.get('sale.subscription.line')
+
+ subscribed_lines = {l.id: None for l in lots}
+ date = Transaction().context.get('date', Date.today())
+ for sub_lots in grouped_slice(lots):
+ lines = SubscriptionLine.search([
+ ('asset_lot', 'in', [l.id for l in sub_lots]),
+ [
+ ('start_date', '<=', date),
+ ['OR',
+ ('end_date', '=', None),
+ ('end_date', '>', date),
+ ],
+ ]
+ ])
+ subscribed_lines.update((s.asset_lot.id, s.id) for s in lines)
+ return subscribed_lines
+
+ @classmethod
+ def search_subscribed(cls, name, clause):
+ pool = Pool()
+ Date = pool.get('ir.date')
+
+ name, operator, value = clause[:3]
+ date = Transaction().context.get('date', Date.today())
+ domain = [
+ ('asset_lot', '!=', None),
+ ('start_date', '<=', date),
+ ['OR',
+ ('end_date', '=', None),
+ ('end_date', '>', date),
+ ],
+ ]
+ if '.' in name:
+ _, target_name = name.split('.', 1)
+ domain.append((target_name,) + tuple(clause[1:]))
+ return [('subscription_lines', 'where', domain)]
+ else:
+ if (operator, value) == ('=', None):
+ return [('subscription_lines', 'not where', domain)]
+ elif (operator, value) == ('!=', None):
+ return [('subscription_lines', 'where', domain)]
+ else:
+ if isinstance(value, str):
+ target_name = 'rec_name'
+ else:
+ target_name = 'id'
+ domain.append((target_name,) + tuple(clause[1:]))
+ return [('subscription_lines', 'where', domain)]
diff --git a/modules/sale_subscription_asset/stock.xml b/modules/sale_subscription_asset/stock.xml
new file mode 100644
index 0000000000..aec2c26425
--- /dev/null
+++ b/modules/sale_subscription_asset/stock.xml
@@ -0,0 +1,12 @@
+
+
+
+
+
+ stock.lot
+
+ stock_lot_form
+
+
+
diff --git a/modules/sale_subscription_asset/tests/__init__.py b/modules/sale_subscription_asset/tests/__init__.py
new file mode 100644
index 0000000000..68971822d7
--- /dev/null
+++ b/modules/sale_subscription_asset/tests/__init__.py
@@ -0,0 +1,9 @@
+# This file is part of Tryton. The COPYRIGHT file at the top level of
+# this repository contains the full copyright notices and license terms.
+
+try:
+ from trytond.modules.sale_subscription_asset.tests.test_sale_subscription_asset import suite # noqa: E501
+except ImportError:
+ from .test_sale_subscription_asset import suite
+
+__all__ = ['suite']
diff --git a/modules/sale_subscription_asset/tests/scenario_sale_subscription_asset.rst b/modules/sale_subscription_asset/tests/scenario_sale_subscription_asset.rst
new file mode 100644
index 0000000000..b3559d031a
--- /dev/null
+++ b/modules/sale_subscription_asset/tests/scenario_sale_subscription_asset.rst
@@ -0,0 +1,165 @@
+================================
+Sale Subscription Asset Scenario
+================================
+
+Imports::
+
+ >>> import datetime
+ >>> from decimal import Decimal
+ >>> from proteus import Model, Wizard
+ >>> from trytond.tests.tools import activate_modules
+ >>> from trytond.modules.company.tests.tools import create_company, \
+ ... get_company
+ >>> from trytond.modules.account.tests.tools import create_chart, \
+ ... get_accounts
+
+Activate modules::
+
+ >>> config = activate_modules('sale_subscription_asset')
+
+Create company::
+
+ >>> _ = create_company()
+ >>> company = get_company()
+
+Create chart of accounts::
+
+ >>> _ = create_chart(company)
+ >>> accounts = get_accounts(company)
+ >>> revenue = accounts['revenue']
+
+Create party::
+
+ >>> Party = Model.get('party.party')
+
+ >>> customer = Party(name='Customer')
+ >>> customer.save()
+
+Create some assets::
+
+ >>> ProductTemplate = Model.get('product.template')
+ >>> Uom = Model.get('product.uom')
+ >>> unit, = Uom.find([('name', '=', 'Unit')])
+
+ >>> template = ProductTemplate()
+ >>> template.name = 'Asset'
+ >>> template.default_uom = unit
+ >>> template.type = 'assets'
+ >>> template.list_price = Decimal(1000)
+ >>> template.save()
+ >>> asset, = template.products
+
+And some lots linked to the asset::
+
+ >>> StockLot = Model.get('stock.lot')
+ >>> lot1 = StockLot(number='001', product=asset)
+ >>> lot1.save()
+ >>> lot2 = StockLot(number='002', product=asset)
+ >>> lot2.save()
+
+Create subscription recurrence rule sets::
+
+ >>> RecurrenceRuleSet = Model.get('sale.subscription.recurrence.rule.set')
+
+ >>> monthly = RecurrenceRuleSet(name='Monthly')
+ >>> rule, = monthly.rules
+ >>> rule.freq = 'monthly'
+ >>> rule.interval = 1
+ >>> monthly.save()
+
+Create subscription service::
+
+ >>> template = ProductTemplate()
+ >>> template.name = 'Rental'
+ >>> template.default_uom = unit
+ >>> template.type = 'service'
+ >>> template.list_price = Decimal('10')
+ >>> template.save()
+ >>> product, = template.products
+
+ >>> Service = Model.get('sale.subscription.service')
+ >>> service = Service()
+ >>> service.product = product
+ >>> service.asset_lots.extend([lot1, lot2])
+ >>> service.save()
+
+ >>> sorted(l.number for l in service.asset_lots_available)
+ ['001', '002']
+
+Subscribe::
+
+ >>> Subscription = Model.get('sale.subscription')
+
+ >>> subscription = Subscription()
+ >>> subscription.party = customer
+ >>> subscription.start_date = datetime.date(2016, 1, 1)
+ >>> subscription.invoice_start_date = datetime.date(2016, 2, 1)
+ >>> subscription.invoice_recurrence = monthly
+ >>> line = subscription.lines.new()
+ >>> line.service = service
+ >>> line.quantity = 1
+
+ >>> subscription.click('quote')
+ >>> subscription.click('run') # doctest: +IGNORE_EXCEPTION_DETAIL
+ Traceback (most recent call last):
+ ...
+ RequiredValidationError: ...
+
+ >>> subscription.click('draft')
+ >>> line, = subscription.lines
+ >>> line.asset_lot = lot1
+ >>> subscription.click('quote')
+ >>> subscription.click('run')
+
+ >>> with config.set_context(date=datetime.date(2017, 1, 1)):
+ ... lot1.reload()
+ ... subscribed_line = lot1.subscribed
+ ... service.reload()
+ ... lots_available = sorted(
+ ... l.number for l in service.asset_lots_available)
+ >>> subscribed_line == line
+ True
+ >>> lots_available
+ ['002']
+
+Creating an overlapping line won't work::
+
+ >>> overlapping = Subscription()
+ >>> overlapping.party = customer
+ >>> overlapping.start_date = datetime.date(2017, 1, 1)
+ >>> overlapping.invoice_start_date = datetime.date(2017, 2, 1)
+ >>> overlapping.invoice_recurrence = monthly
+ >>> line = overlapping.lines.new()
+ >>> line.service = service
+ >>> line.start_date = datetime.date(2017, 1, 1)
+ >>> line.quantity = 1
+ >>> line.asset_lot = lot1
+ >>> overlapping.save() # doctest: +IGNORE_EXCEPTION_DETAIL
+ Traceback (most recent call last):
+ ...
+ ValidationError: ....
+
+Cancelling the subscription will remove lot from the lines thus making it
+available again::
+
+ >>> another_subscription = Subscription()
+ >>> another_subscription.party = customer
+ >>> another_subscription.start_date = datetime.date(2018, 1, 1)
+ >>> another_subscription.invoice_start_date = datetime.date(2018, 2, 1)
+ >>> another_subscription.invoice_recurrence = monthly
+ >>> line = another_subscription.lines.new()
+ >>> line.service = service
+ >>> line.asset_lot = lot2
+ >>> line.quantity = 1
+
+ >>> another_subscription.click('quote')
+ >>> service.reload()
+ >>> sorted(l.number for l in service.asset_lots_available)
+ []
+
+ >>> another_subscription.click('cancel')
+ >>> [l.asset_lot for l in another_subscription.lines]
+ [None]
+ >>> service.reload()
+ >>> sorted(l.number for l in service.asset_lots_available)
+ ['002']
diff --git a/modules/sale_subscription_asset/tests/test_sale_subscription_asset.py b/modules/sale_subscription_asset/tests/test_sale_subscription_asset.py
new file mode 100644
index 0000000000..9d5c448b89
--- /dev/null
+++ b/modules/sale_subscription_asset/tests/test_sale_subscription_asset.py
@@ -0,0 +1,28 @@
+# This file is part of Tryton. The COPYRIGHT file at the top level of
+# this repository contains the full copyright notices and license terms.
+
+import unittest
+
+import doctest
+
+from trytond.tests.test_tryton import ModuleTestCase
+from trytond.tests.test_tryton import suite as test_suite
+from trytond.tests.test_tryton import doctest_teardown
+from trytond.tests.test_tryton import doctest_checker
+
+
+class SaleSubscriptionAssetTestCase(ModuleTestCase):
+ 'Test Sale Subscription Asset module'
+ module = 'sale_subscription_asset'
+
+
+def suite():
+ suite = test_suite()
+ suite.addTests(unittest.TestLoader().loadTestsFromTestCase(
+ SaleSubscriptionAssetTestCase))
+ suite.addTests(doctest.DocFileSuite(
+ 'scenario_sale_subscription_asset.rst',
+ tearDown=doctest_teardown, encoding='utf-8',
+ checker=doctest_checker,
+ optionflags=doctest.REPORT_ONLY_FIRST_FAILURE))
+ return suite
diff --git a/modules/sale_subscription_asset/tox.ini b/modules/sale_subscription_asset/tox.ini
new file mode 100644
index 0000000000..197496c0cb
--- /dev/null
+++ b/modules/sale_subscription_asset/tox.ini
@@ -0,0 +1,15 @@
+[tox]
+envlist = {py36,py37,py38,py39}-{sqlite,postgresql},pypy3-{sqlite,postgresql}
+
+[testenv]
+commands = {envpython} setup.py test
+deps =
+ {py36,py37,py38,py39}-postgresql: psycopg2 >= 2.5
+ pypy3-postgresql: psycopg2cffi >= 2.5
+ py36-sqlite: sqlitebck
+setenv =
+ sqlite: TRYTOND_DATABASE_URI={env:SQLITE_URI:sqlite://}
+ postgresql: TRYTOND_DATABASE_URI={env:POSTGRESQL_URI:postgresql://}
+ sqlite: DB_NAME={env:SQLITE_NAME::memory:}
+ postgresql: DB_NAME={env:POSTGRESQL_NAME:test}
+install_command = pip install --pre --find-links https://trydevpi.tryton.org/?local_version={env:CI_JOB_ID:{env:CI_BUILD_NUMBER}.{env:CI_JOB_NUMBER}} {opts} {packages}
diff --git a/modules/sale_subscription_asset/tryton.cfg b/modules/sale_subscription_asset/tryton.cfg
new file mode 100644
index 0000000000..734f6870d7
--- /dev/null
+++ b/modules/sale_subscription_asset/tryton.cfg
@@ -0,0 +1,10 @@
+[tryton]
+version=6.0.2
+depends:
+ ir
+ sale_subscription
+ stock_lot
+xml:
+ sale.xml
+ stock.xml
+ message.xml
diff --git a/modules/sale_subscription_asset/view/stock_lot_form.xml b/modules/sale_subscription_asset/view/stock_lot_form.xml
new file mode 100644
index 0000000000..80146503e2
--- /dev/null
+++ b/modules/sale_subscription_asset/view/stock_lot_form.xml
@@ -0,0 +1,9 @@
+
+
+
+
+
+
+
+
diff --git a/modules/sale_subscription_asset/view/subscription_line_form.xml b/modules/sale_subscription_asset/view/subscription_line_form.xml
new file mode 100644
index 0000000000..7b53d94ade
--- /dev/null
+++ b/modules/sale_subscription_asset/view/subscription_line_form.xml
@@ -0,0 +1,10 @@
+
+
+
+
+
+
+
+
+
diff --git a/modules/sale_subscription_asset/view/subscription_line_list.xml b/modules/sale_subscription_asset/view/subscription_line_list.xml
new file mode 100644
index 0000000000..7238a6ce31
--- /dev/null
+++ b/modules/sale_subscription_asset/view/subscription_line_list.xml
@@ -0,0 +1,8 @@
+
+
+
+
+
+
+
diff --git a/modules/sale_subscription_asset/view/subscription_service_form.xml b/modules/sale_subscription_asset/view/subscription_service_form.xml
new file mode 100644
index 0000000000..460411adfe
--- /dev/null
+++ b/modules/sale_subscription_asset/view/subscription_service_form.xml
@@ -0,0 +1,9 @@
+
+
+
+
+
+
+
+
diff --git a/modules/sale_supply/.drone.yml b/modules/sale_supply/.drone.yml
new file mode 100644
index 0000000000..2049d30a49
--- /dev/null
+++ b/modules/sale_supply/.drone.yml
@@ -0,0 +1,68 @@
+clone:
+ hg:
+ image: plugins/hg
+ environment:
+ - HG_SHARE_POOL=/root/.cache/hg
+ volumes:
+ - cache:/root/.cache
+
+pipeline:
+ tox:
+ image: ${IMAGE}
+ environment:
+ - CFLAGS=-O0
+ - DB_CACHE=/cache
+ - TOX_TESTENV_PASSENV=CFLAGS DB_CACHE CI_BUILD_NUMBER CI_JOB_NUMBER CI_JOB_ID
+ - POSTGRESQL_URI=postgresql://postgres@postgresql:5432/
+ commands:
+ - echo "[extensions]" >> /root/.hgrc
+ - echo "hgext.share =" >> /root/.hgrc
+ - echo "[share]" >> /root/.hgrc
+ - echo "pool = /root/.cache/hg" >> /root/.hgrc
+ - pip install tox
+ - tox -e "${TOXENV}-${DATABASE}"
+ volumes:
+ - cache:/root/.cache
+ check_dist:
+ image: ${IMAGE}
+ commands:
+ - pip install twine
+ - python setup.py sdist
+ - twine check dist/*
+
+services:
+ postgresql:
+ image: postgres
+ environment:
+ - POSTGRES_HOST_AUTH_METHOD=trust
+ command: "-c fsync=off -c synchronous_commit=off -c full_page_writes=off"
+ when:
+ matrix:
+ DATABASE: postgresql
+
+matrix:
+ include:
+ - IMAGE: python:3.6
+ TOXENV: py36
+ DATABASE: sqlite
+ - IMAGE: python:3.6
+ TOXENV: py36
+ DATABASE: postgresql
+ - IMAGE: python:3.7
+ TOXENV: py37
+ DATABASE: sqlite
+ - IMAGE: python:3.7
+ TOXENV: py37
+ DATABASE: postgresql
+ - IMAGE: python:3.8
+ TOXENV: py38
+ DATABASE: sqlite
+ - IMAGE: python:3.8
+ TOXENV: py38
+ DATABASE: postgresql
+ - IMAGE: python:3.9
+ TOXENV: py39
+ DATABASE: sqlite
+ - IMAGE: python:3.9
+ TOXENV: py39
+ DATABASE: postgresql
diff --git a/modules/sale_supply/.flake8 b/modules/sale_supply/.flake8
new file mode 100644
index 0000000000..fa6b4f66d1
--- /dev/null
+++ b/modules/sale_supply/.flake8
@@ -0,0 +1,2 @@
+[flake8]
+ignore=E123,E124,E126,E128,E741,W503
diff --git a/modules/sale_supply/CHANGELOG b/modules/sale_supply/CHANGELOG
new file mode 100644
index 0000000000..2c33eed749
--- /dev/null
+++ b/modules/sale_supply/CHANGELOG
@@ -0,0 +1,60 @@
+Version 6.0.1 - 2022-10-17
+* Bug fixes (see mercurial logs for details)
+
+Version 6.0.0 - 2021-05-03
+* Bug fixes (see mercurial logs for details)
+
+Version 5.8.0 - 2020-11-02
+* Bug fixes (see mercurial logs for details)
+* Remove support for Python 3.5
+
+Version 5.6.0 - 2020-05-04
+* Bug fixes (see mercurial logs for details)
+* Rename purchase request state into supply state
+
+Version 5.4.0 - 2019-11-04
+* Bug fixes (see mercurial logs for details)
+
+Version 5.2.0 - 2019-05-06
+* Bug fixes (see mercurial logs for details)
+
+Version 5.0.0 - 2018-10-01
+* Bug fixes (see mercurial logs for details)
+* Remove support for Python 2.7
+
+Version 4.8.0 - 2018-04-23
+* Bug fixes (see mercurial logs for details)
+* Create requests depending on the shipment method
+
+Version 4.6.0 - 2017-10-30
+* Bug fixes (see mercurial logs for details)
+
+Version 4.4.0 - 2017-05-01
+* Bug fixes (see mercurial logs for details)
+
+Version 4.2.0 - 2016-11-28
+* Bug fixes (see mercurial logs for details)
+
+Version 4.0.0 - 2016-05-02
+* Bug fixes (see mercurial logs for details)
+* Add Python3 support
+
+Version 3.8.0 - 2015-11-02
+* Bug fixes (see mercurial logs for details)
+
+Version 3.6.0 - 2015-04-20
+* Bug fixes (see mercurial logs for details)
+* Add support for PyPy
+* Add sale supplied move to shipment in state 'staging'
+
+Version 3.4.0 - 2014-10-20
+* Bug fixes (see mercurial logs for details)
+
+Version 3.2.0 - 2014-04-21
+* Bug fixes (see mercurial logs for details)
+
+Version 3.0.0 - 2013-10-21
+* Bug fixes (see mercurial logs for details)
+
+Version 2.8.0 - 2013-04-22
+* Initial release
diff --git a/modules/sale_supply/COPYRIGHT b/modules/sale_supply/COPYRIGHT
new file mode 100644
index 0000000000..51a574630e
--- /dev/null
+++ b/modules/sale_supply/COPYRIGHT
@@ -0,0 +1,15 @@
+Copyright (C) 2011-2022 Cédric Krier.
+Copyright (C) 2011-2022 B2CK SPRL.
+
+This program is free software: you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation, either version 3 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program. If not, see .
diff --git a/modules/sale_supply/LICENSE b/modules/sale_supply/LICENSE
new file mode 100644
index 0000000000..94a9ed024d
--- /dev/null
+++ b/modules/sale_supply/LICENSE
@@ -0,0 +1,674 @@
+ GNU GENERAL PUBLIC LICENSE
+ Version 3, 29 June 2007
+
+ Copyright (C) 2007 Free Software Foundation, Inc.
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+ Preamble
+
+ The GNU General Public License is a free, copyleft license for
+software and other kinds of works.
+
+ The licenses for most software and other practical works are designed
+to take away your freedom to share and change the works. By contrast,
+the GNU General Public License is intended to guarantee your freedom to
+share and change all versions of a program--to make sure it remains free
+software for all its users. We, the Free Software Foundation, use the
+GNU General Public License for most of our software; it applies also to
+any other work released this way by its authors. You can apply it to
+your programs, too.
+
+ When we speak of free software, we are referring to freedom, not
+price. Our General Public Licenses are designed to make sure that you
+have the freedom to distribute copies of free software (and charge for
+them if you wish), that you receive source code or can get it if you
+want it, that you can change the software or use pieces of it in new
+free programs, and that you know you can do these things.
+
+ To protect your rights, we need to prevent others from denying you
+these rights or asking you to surrender the rights. Therefore, you have
+certain responsibilities if you distribute copies of the software, or if
+you modify it: responsibilities to respect the freedom of others.
+
+ For example, if you distribute copies of such a program, whether
+gratis or for a fee, you must pass on to the recipients the same
+freedoms that you received. You must make sure that they, too, receive
+or can get the source code. And you must show them these terms so they
+know their rights.
+
+ Developers that use the GNU GPL protect your rights with two steps:
+(1) assert copyright on the software, and (2) offer you this License
+giving you legal permission to copy, distribute and/or modify it.
+
+ For the developers' and authors' protection, the GPL clearly explains
+that there is no warranty for this free software. For both users' and
+authors' sake, the GPL requires that modified versions be marked as
+changed, so that their problems will not be attributed erroneously to
+authors of previous versions.
+
+ Some devices are designed to deny users access to install or run
+modified versions of the software inside them, although the manufacturer
+can do so. This is fundamentally incompatible with the aim of
+protecting users' freedom to change the software. The systematic
+pattern of such abuse occurs in the area of products for individuals to
+use, which is precisely where it is most unacceptable. Therefore, we
+have designed this version of the GPL to prohibit the practice for those
+products. If such problems arise substantially in other domains, we
+stand ready to extend this provision to those domains in future versions
+of the GPL, as needed to protect the freedom of users.
+
+ Finally, every program is threatened constantly by software patents.
+States should not allow patents to restrict development and use of
+software on general-purpose computers, but in those that do, we wish to
+avoid the special danger that patents applied to a free program could
+make it effectively proprietary. To prevent this, the GPL assures that
+patents cannot be used to render the program non-free.
+
+ The precise terms and conditions for copying, distribution and
+modification follow.
+
+ TERMS AND CONDITIONS
+
+ 0. Definitions.
+
+ "This License" refers to version 3 of the GNU General Public License.
+
+ "Copyright" also means copyright-like laws that apply to other kinds of
+works, such as semiconductor masks.
+
+ "The Program" refers to any copyrightable work licensed under this
+License. Each licensee is addressed as "you". "Licensees" and
+"recipients" may be individuals or organizations.
+
+ To "modify" a work means to copy from or adapt all or part of the work
+in a fashion requiring copyright permission, other than the making of an
+exact copy. The resulting work is called a "modified version" of the
+earlier work or a work "based on" the earlier work.
+
+ A "covered work" means either the unmodified Program or a work based
+on the Program.
+
+ To "propagate" a work means to do anything with it that, without
+permission, would make you directly or secondarily liable for
+infringement under applicable copyright law, except executing it on a
+computer or modifying a private copy. Propagation includes copying,
+distribution (with or without modification), making available to the
+public, and in some countries other activities as well.
+
+ To "convey" a work means any kind of propagation that enables other
+parties to make or receive copies. Mere interaction with a user through
+a computer network, with no transfer of a copy, is not conveying.
+
+ An interactive user interface displays "Appropriate Legal Notices"
+to the extent that it includes a convenient and prominently visible
+feature that (1) displays an appropriate copyright notice, and (2)
+tells the user that there is no warranty for the work (except to the
+extent that warranties are provided), that licensees may convey the
+work under this License, and how to view a copy of this License. If
+the interface presents a list of user commands or options, such as a
+menu, a prominent item in the list meets this criterion.
+
+ 1. Source Code.
+
+ The "source code" for a work means the preferred form of the work
+for making modifications to it. "Object code" means any non-source
+form of a work.
+
+ A "Standard Interface" means an interface that either is an official
+standard defined by a recognized standards body, or, in the case of
+interfaces specified for a particular programming language, one that
+is widely used among developers working in that language.
+
+ The "System Libraries" of an executable work include anything, other
+than the work as a whole, that (a) is included in the normal form of
+packaging a Major Component, but which is not part of that Major
+Component, and (b) serves only to enable use of the work with that
+Major Component, or to implement a Standard Interface for which an
+implementation is available to the public in source code form. A
+"Major Component", in this context, means a major essential component
+(kernel, window system, and so on) of the specific operating system
+(if any) on which the executable work runs, or a compiler used to
+produce the work, or an object code interpreter used to run it.
+
+ The "Corresponding Source" for a work in object code form means all
+the source code needed to generate, install, and (for an executable
+work) run the object code and to modify the work, including scripts to
+control those activities. However, it does not include the work's
+System Libraries, or general-purpose tools or generally available free
+programs which are used unmodified in performing those activities but
+which are not part of the work. For example, Corresponding Source
+includes interface definition files associated with source files for
+the work, and the source code for shared libraries and dynamically
+linked subprograms that the work is specifically designed to require,
+such as by intimate data communication or control flow between those
+subprograms and other parts of the work.
+
+ The Corresponding Source need not include anything that users
+can regenerate automatically from other parts of the Corresponding
+Source.
+
+ The Corresponding Source for a work in source code form is that
+same work.
+
+ 2. Basic Permissions.
+
+ All rights granted under this License are granted for the term of
+copyright on the Program, and are irrevocable provided the stated
+conditions are met. This License explicitly affirms your unlimited
+permission to run the unmodified Program. The output from running a
+covered work is covered by this License only if the output, given its
+content, constitutes a covered work. This License acknowledges your
+rights of fair use or other equivalent, as provided by copyright law.
+
+ You may make, run and propagate covered works that you do not
+convey, without conditions so long as your license otherwise remains
+in force. You may convey covered works to others for the sole purpose
+of having them make modifications exclusively for you, or provide you
+with facilities for running those works, provided that you comply with
+the terms of this License in conveying all material for which you do
+not control copyright. Those thus making or running the covered works
+for you must do so exclusively on your behalf, under your direction
+and control, on terms that prohibit them from making any copies of
+your copyrighted material outside their relationship with you.
+
+ Conveying under any other circumstances is permitted solely under
+the conditions stated below. Sublicensing is not allowed; section 10
+makes it unnecessary.
+
+ 3. Protecting Users' Legal Rights From Anti-Circumvention Law.
+
+ No covered work shall be deemed part of an effective technological
+measure under any applicable law fulfilling obligations under article
+11 of the WIPO copyright treaty adopted on 20 December 1996, or
+similar laws prohibiting or restricting circumvention of such
+measures.
+
+ When you convey a covered work, you waive any legal power to forbid
+circumvention of technological measures to the extent such circumvention
+is effected by exercising rights under this License with respect to
+the covered work, and you disclaim any intention to limit operation or
+modification of the work as a means of enforcing, against the work's
+users, your or third parties' legal rights to forbid circumvention of
+technological measures.
+
+ 4. Conveying Verbatim Copies.
+
+ You may convey verbatim copies of the Program's source code as you
+receive it, in any medium, provided that you conspicuously and
+appropriately publish on each copy an appropriate copyright notice;
+keep intact all notices stating that this License and any
+non-permissive terms added in accord with section 7 apply to the code;
+keep intact all notices of the absence of any warranty; and give all
+recipients a copy of this License along with the Program.
+
+ You may charge any price or no price for each copy that you convey,
+and you may offer support or warranty protection for a fee.
+
+ 5. Conveying Modified Source Versions.
+
+ You may convey a work based on the Program, or the modifications to
+produce it from the Program, in the form of source code under the
+terms of section 4, provided that you also meet all of these conditions:
+
+ a) The work must carry prominent notices stating that you modified
+ it, and giving a relevant date.
+
+ b) The work must carry prominent notices stating that it is
+ released under this License and any conditions added under section
+ 7. This requirement modifies the requirement in section 4 to
+ "keep intact all notices".
+
+ c) You must license the entire work, as a whole, under this
+ License to anyone who comes into possession of a copy. This
+ License will therefore apply, along with any applicable section 7
+ additional terms, to the whole of the work, and all its parts,
+ regardless of how they are packaged. This License gives no
+ permission to license the work in any other way, but it does not
+ invalidate such permission if you have separately received it.
+
+ d) If the work has interactive user interfaces, each must display
+ Appropriate Legal Notices; however, if the Program has interactive
+ interfaces that do not display Appropriate Legal Notices, your
+ work need not make them do so.
+
+ A compilation of a covered work with other separate and independent
+works, which are not by their nature extensions of the covered work,
+and which are not combined with it such as to form a larger program,
+in or on a volume of a storage or distribution medium, is called an
+"aggregate" if the compilation and its resulting copyright are not
+used to limit the access or legal rights of the compilation's users
+beyond what the individual works permit. Inclusion of a covered work
+in an aggregate does not cause this License to apply to the other
+parts of the aggregate.
+
+ 6. Conveying Non-Source Forms.
+
+ You may convey a covered work in object code form under the terms
+of sections 4 and 5, provided that you also convey the
+machine-readable Corresponding Source under the terms of this License,
+in one of these ways:
+
+ a) Convey the object code in, or embodied in, a physical product
+ (including a physical distribution medium), accompanied by the
+ Corresponding Source fixed on a durable physical medium
+ customarily used for software interchange.
+
+ b) Convey the object code in, or embodied in, a physical product
+ (including a physical distribution medium), accompanied by a
+ written offer, valid for at least three years and valid for as
+ long as you offer spare parts or customer support for that product
+ model, to give anyone who possesses the object code either (1) a
+ copy of the Corresponding Source for all the software in the
+ product that is covered by this License, on a durable physical
+ medium customarily used for software interchange, for a price no
+ more than your reasonable cost of physically performing this
+ conveying of source, or (2) access to copy the
+ Corresponding Source from a network server at no charge.
+
+ c) Convey individual copies of the object code with a copy of the
+ written offer to provide the Corresponding Source. This
+ alternative is allowed only occasionally and noncommercially, and
+ only if you received the object code with such an offer, in accord
+ with subsection 6b.
+
+ d) Convey the object code by offering access from a designated
+ place (gratis or for a charge), and offer equivalent access to the
+ Corresponding Source in the same way through the same place at no
+ further charge. You need not require recipients to copy the
+ Corresponding Source along with the object code. If the place to
+ copy the object code is a network server, the Corresponding Source
+ may be on a different server (operated by you or a third party)
+ that supports equivalent copying facilities, provided you maintain
+ clear directions next to the object code saying where to find the
+ Corresponding Source. Regardless of what server hosts the
+ Corresponding Source, you remain obligated to ensure that it is
+ available for as long as needed to satisfy these requirements.
+
+ e) Convey the object code using peer-to-peer transmission, provided
+ you inform other peers where the object code and Corresponding
+ Source of the work are being offered to the general public at no
+ charge under subsection 6d.
+
+ A separable portion of the object code, whose source code is excluded
+from the Corresponding Source as a System Library, need not be
+included in conveying the object code work.
+
+ A "User Product" is either (1) a "consumer product", which means any
+tangible personal property which is normally used for personal, family,
+or household purposes, or (2) anything designed or sold for incorporation
+into a dwelling. In determining whether a product is a consumer product,
+doubtful cases shall be resolved in favor of coverage. For a particular
+product received by a particular user, "normally used" refers to a
+typical or common use of that class of product, regardless of the status
+of the particular user or of the way in which the particular user
+actually uses, or expects or is expected to use, the product. A product
+is a consumer product regardless of whether the product has substantial
+commercial, industrial or non-consumer uses, unless such uses represent
+the only significant mode of use of the product.
+
+ "Installation Information" for a User Product means any methods,
+procedures, authorization keys, or other information required to install
+and execute modified versions of a covered work in that User Product from
+a modified version of its Corresponding Source. The information must
+suffice to ensure that the continued functioning of the modified object
+code is in no case prevented or interfered with solely because
+modification has been made.
+
+ If you convey an object code work under this section in, or with, or
+specifically for use in, a User Product, and the conveying occurs as
+part of a transaction in which the right of possession and use of the
+User Product is transferred to the recipient in perpetuity or for a
+fixed term (regardless of how the transaction is characterized), the
+Corresponding Source conveyed under this section must be accompanied
+by the Installation Information. But this requirement does not apply
+if neither you nor any third party retains the ability to install
+modified object code on the User Product (for example, the work has
+been installed in ROM).
+
+ The requirement to provide Installation Information does not include a
+requirement to continue to provide support service, warranty, or updates
+for a work that has been modified or installed by the recipient, or for
+the User Product in which it has been modified or installed. Access to a
+network may be denied when the modification itself materially and
+adversely affects the operation of the network or violates the rules and
+protocols for communication across the network.
+
+ Corresponding Source conveyed, and Installation Information provided,
+in accord with this section must be in a format that is publicly
+documented (and with an implementation available to the public in
+source code form), and must require no special password or key for
+unpacking, reading or copying.
+
+ 7. Additional Terms.
+
+ "Additional permissions" are terms that supplement the terms of this
+License by making exceptions from one or more of its conditions.
+Additional permissions that are applicable to the entire Program shall
+be treated as though they were included in this License, to the extent
+that they are valid under applicable law. If additional permissions
+apply only to part of the Program, that part may be used separately
+under those permissions, but the entire Program remains governed by
+this License without regard to the additional permissions.
+
+ When you convey a copy of a covered work, you may at your option
+remove any additional permissions from that copy, or from any part of
+it. (Additional permissions may be written to require their own
+removal in certain cases when you modify the work.) You may place
+additional permissions on material, added by you to a covered work,
+for which you have or can give appropriate copyright permission.
+
+ Notwithstanding any other provision of this License, for material you
+add to a covered work, you may (if authorized by the copyright holders of
+that material) supplement the terms of this License with terms:
+
+ a) Disclaiming warranty or limiting liability differently from the
+ terms of sections 15 and 16 of this License; or
+
+ b) Requiring preservation of specified reasonable legal notices or
+ author attributions in that material or in the Appropriate Legal
+ Notices displayed by works containing it; or
+
+ c) Prohibiting misrepresentation of the origin of that material, or
+ requiring that modified versions of such material be marked in
+ reasonable ways as different from the original version; or
+
+ d) Limiting the use for publicity purposes of names of licensors or
+ authors of the material; or
+
+ e) Declining to grant rights under trademark law for use of some
+ trade names, trademarks, or service marks; or
+
+ f) Requiring indemnification of licensors and authors of that
+ material by anyone who conveys the material (or modified versions of
+ it) with contractual assumptions of liability to the recipient, for
+ any liability that these contractual assumptions directly impose on
+ those licensors and authors.
+
+ All other non-permissive additional terms are considered "further
+restrictions" within the meaning of section 10. If the Program as you
+received it, or any part of it, contains a notice stating that it is
+governed by this License along with a term that is a further
+restriction, you may remove that term. If a license document contains
+a further restriction but permits relicensing or conveying under this
+License, you may add to a covered work material governed by the terms
+of that license document, provided that the further restriction does
+not survive such relicensing or conveying.
+
+ If you add terms to a covered work in accord with this section, you
+must place, in the relevant source files, a statement of the
+additional terms that apply to those files, or a notice indicating
+where to find the applicable terms.
+
+ Additional terms, permissive or non-permissive, may be stated in the
+form of a separately written license, or stated as exceptions;
+the above requirements apply either way.
+
+ 8. Termination.
+
+ You may not propagate or modify a covered work except as expressly
+provided under this License. Any attempt otherwise to propagate or
+modify it is void, and will automatically terminate your rights under
+this License (including any patent licenses granted under the third
+paragraph of section 11).
+
+ However, if you cease all violation of this License, then your
+license from a particular copyright holder is reinstated (a)
+provisionally, unless and until the copyright holder explicitly and
+finally terminates your license, and (b) permanently, if the copyright
+holder fails to notify you of the violation by some reasonable means
+prior to 60 days after the cessation.
+
+ Moreover, your license from a particular copyright holder is
+reinstated permanently if the copyright holder notifies you of the
+violation by some reasonable means, this is the first time you have
+received notice of violation of this License (for any work) from that
+copyright holder, and you cure the violation prior to 30 days after
+your receipt of the notice.
+
+ Termination of your rights under this section does not terminate the
+licenses of parties who have received copies or rights from you under
+this License. If your rights have been terminated and not permanently
+reinstated, you do not qualify to receive new licenses for the same
+material under section 10.
+
+ 9. Acceptance Not Required for Having Copies.
+
+ You are not required to accept this License in order to receive or
+run a copy of the Program. Ancillary propagation of a covered work
+occurring solely as a consequence of using peer-to-peer transmission
+to receive a copy likewise does not require acceptance. However,
+nothing other than this License grants you permission to propagate or
+modify any covered work. These actions infringe copyright if you do
+not accept this License. Therefore, by modifying or propagating a
+covered work, you indicate your acceptance of this License to do so.
+
+ 10. Automatic Licensing of Downstream Recipients.
+
+ Each time you convey a covered work, the recipient automatically
+receives a license from the original licensors, to run, modify and
+propagate that work, subject to this License. You are not responsible
+for enforcing compliance by third parties with this License.
+
+ An "entity transaction" is a transaction transferring control of an
+organization, or substantially all assets of one, or subdividing an
+organization, or merging organizations. If propagation of a covered
+work results from an entity transaction, each party to that
+transaction who receives a copy of the work also receives whatever
+licenses to the work the party's predecessor in interest had or could
+give under the previous paragraph, plus a right to possession of the
+Corresponding Source of the work from the predecessor in interest, if
+the predecessor has it or can get it with reasonable efforts.
+
+ You may not impose any further restrictions on the exercise of the
+rights granted or affirmed under this License. For example, you may
+not impose a license fee, royalty, or other charge for exercise of
+rights granted under this License, and you may not initiate litigation
+(including a cross-claim or counterclaim in a lawsuit) alleging that
+any patent claim is infringed by making, using, selling, offering for
+sale, or importing the Program or any portion of it.
+
+ 11. Patents.
+
+ A "contributor" is a copyright holder who authorizes use under this
+License of the Program or a work on which the Program is based. The
+work thus licensed is called the contributor's "contributor version".
+
+ A contributor's "essential patent claims" are all patent claims
+owned or controlled by the contributor, whether already acquired or
+hereafter acquired, that would be infringed by some manner, permitted
+by this License, of making, using, or selling its contributor version,
+but do not include claims that would be infringed only as a
+consequence of further modification of the contributor version. For
+purposes of this definition, "control" includes the right to grant
+patent sublicenses in a manner consistent with the requirements of
+this License.
+
+ Each contributor grants you a non-exclusive, worldwide, royalty-free
+patent license under the contributor's essential patent claims, to
+make, use, sell, offer for sale, import and otherwise run, modify and
+propagate the contents of its contributor version.
+
+ In the following three paragraphs, a "patent license" is any express
+agreement or commitment, however denominated, not to enforce a patent
+(such as an express permission to practice a patent or covenant not to
+sue for patent infringement). To "grant" such a patent license to a
+party means to make such an agreement or commitment not to enforce a
+patent against the party.
+
+ If you convey a covered work, knowingly relying on a patent license,
+and the Corresponding Source of the work is not available for anyone
+to copy, free of charge and under the terms of this License, through a
+publicly available network server or other readily accessible means,
+then you must either (1) cause the Corresponding Source to be so
+available, or (2) arrange to deprive yourself of the benefit of the
+patent license for this particular work, or (3) arrange, in a manner
+consistent with the requirements of this License, to extend the patent
+license to downstream recipients. "Knowingly relying" means you have
+actual knowledge that, but for the patent license, your conveying the
+covered work in a country, or your recipient's use of the covered work
+in a country, would infringe one or more identifiable patents in that
+country that you have reason to believe are valid.
+
+ If, pursuant to or in connection with a single transaction or
+arrangement, you convey, or propagate by procuring conveyance of, a
+covered work, and grant a patent license to some of the parties
+receiving the covered work authorizing them to use, propagate, modify
+or convey a specific copy of the covered work, then the patent license
+you grant is automatically extended to all recipients of the covered
+work and works based on it.
+
+ A patent license is "discriminatory" if it does not include within
+the scope of its coverage, prohibits the exercise of, or is
+conditioned on the non-exercise of one or more of the rights that are
+specifically granted under this License. You may not convey a covered
+work if you are a party to an arrangement with a third party that is
+in the business of distributing software, under which you make payment
+to the third party based on the extent of your activity of conveying
+the work, and under which the third party grants, to any of the
+parties who would receive the covered work from you, a discriminatory
+patent license (a) in connection with copies of the covered work
+conveyed by you (or copies made from those copies), or (b) primarily
+for and in connection with specific products or compilations that
+contain the covered work, unless you entered into that arrangement,
+or that patent license was granted, prior to 28 March 2007.
+
+ Nothing in this License shall be construed as excluding or limiting
+any implied license or other defenses to infringement that may
+otherwise be available to you under applicable patent law.
+
+ 12. No Surrender of Others' Freedom.
+
+ If conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License. If you cannot convey a
+covered work so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you may
+not convey it at all. For example, if you agree to terms that obligate you
+to collect a royalty for further conveying from those to whom you convey
+the Program, the only way you could satisfy both those terms and this
+License would be to refrain entirely from conveying the Program.
+
+ 13. Use with the GNU Affero General Public License.
+
+ Notwithstanding any other provision of this License, you have
+permission to link or combine any covered work with a work licensed
+under version 3 of the GNU Affero General Public License into a single
+combined work, and to convey the resulting work. The terms of this
+License will continue to apply to the part which is the covered work,
+but the special requirements of the GNU Affero General Public License,
+section 13, concerning interaction through a network will apply to the
+combination as such.
+
+ 14. Revised Versions of this License.
+
+ The Free Software Foundation may publish revised and/or new versions of
+the GNU General Public License from time to time. Such new versions will
+be similar in spirit to the present version, but may differ in detail to
+address new problems or concerns.
+
+ Each version is given a distinguishing version number. If the
+Program specifies that a certain numbered version of the GNU General
+Public License "or any later version" applies to it, you have the
+option of following the terms and conditions either of that numbered
+version or of any later version published by the Free Software
+Foundation. If the Program does not specify a version number of the
+GNU General Public License, you may choose any version ever published
+by the Free Software Foundation.
+
+ If the Program specifies that a proxy can decide which future
+versions of the GNU General Public License can be used, that proxy's
+public statement of acceptance of a version permanently authorizes you
+to choose that version for the Program.
+
+ Later license versions may give you additional or different
+permissions. However, no additional obligations are imposed on any
+author or copyright holder as a result of your choosing to follow a
+later version.
+
+ 15. Disclaimer of Warranty.
+
+ THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY
+APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT
+HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY
+OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO,
+THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM
+IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF
+ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
+
+ 16. Limitation of Liability.
+
+ IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS
+THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY
+GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE
+USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF
+DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD
+PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS),
+EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF
+SUCH DAMAGES.
+
+ 17. Interpretation of Sections 15 and 16.
+
+ If the disclaimer of warranty and limitation of liability provided
+above cannot be given local legal effect according to their terms,
+reviewing courts shall apply local law that most closely approximates
+an absolute waiver of all civil liability in connection with the
+Program, unless a warranty or assumption of liability accompanies a
+copy of the Program in return for a fee.
+
+ END OF TERMS AND CONDITIONS
+
+ How to Apply These Terms to Your New Programs
+
+ If you develop a new program, and you want it to be of the greatest
+possible use to the public, the best way to achieve this is to make it
+free software which everyone can redistribute and change under these terms.
+
+ To do so, attach the following notices to the program. It is safest
+to attach them to the start of each source file to most effectively
+state the exclusion of warranty; and each file should have at least
+the "copyright" line and a pointer to where the full notice is found.
+
+
+ Copyright (C)
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see .
+
+Also add information on how to contact you by electronic and paper mail.
+
+ If the program does terminal interaction, make it output a short
+notice like this when it starts in an interactive mode:
+
+ Copyright (C)